@@ -11,21 +11,25 @@ import qualified Data.ByteString as B
11
11
import qualified Data.ByteString.Lazy as LazyB
12
12
import Data.Default.Class (def )
13
13
import Data.Either (rights )
14
+ import Data.Monoid ((<>) )
14
15
import Data.PEM (pemContent , pemParseBS )
15
16
import qualified Data.Text as T
16
17
import qualified Data.Text.Encoding as T
18
+ import qualified Data.Text.IO as T
17
19
import Data.Typeable (Typeable )
18
20
import Data.X509 (SignedCertificate ,
19
21
decodeSignedCertificate )
20
22
import qualified Data.X509 as X509
21
- import Data.X509.CertificateStore (makeCertificateStore )
23
+ import Data.X509.CertificateStore (CertificateStore , makeCertificateStore )
22
24
import qualified Data.X509.Validation as X509
25
+ import Lens.Micro (Lens' , lens , set )
23
26
import Network.Connection (TLSSettings (.. ))
24
27
import qualified Network.HTTP.Client as NH
25
28
import Network.HTTP.Client.TLS (mkManagerSettings )
26
29
import Network.TLS (Credential , defaultParamsClient )
27
30
import qualified Network.TLS as TLS
28
31
import qualified Network.TLS.Extra as TLS
32
+ import System.Environment (getEnv )
29
33
import System.X509 (getSystemCertificateStore )
30
34
31
35
-- | Sets the master URI in the 'K.KubernetesConfig'.
@@ -46,7 +50,7 @@ setTokenAuth
46
50
-> K. KubernetesConfig
47
51
-> K. KubernetesConfig
48
52
setTokenAuth token kcfg = kcfg
49
- { K. configAuthMethods = [K. AnyAuthMethod (K. AuthApiKeyBearerToken token)]
53
+ { K. configAuthMethods = [K. AnyAuthMethod (K. AuthApiKeyBearerToken $ " Bearer " <> token)]
50
54
}
51
55
52
56
-- | Creates a 'NH.Manager' that can handle TLS.
@@ -67,25 +71,22 @@ defaultTLSClientParams = do
67
71
}
68
72
}
69
73
74
+ clientHooksL :: Lens' TLS. ClientParams TLS. ClientHooks
75
+ clientHooksL = lens TLS. clientHooks (\ cp ch -> cp { TLS. clientHooks = ch })
76
+
77
+ onServerCertificateL :: Lens' TLS. ClientParams (CertificateStore -> TLS. ValidationCache -> X509. ServiceID -> X509. CertificateChain -> IO [X509. FailedReason ])
78
+ onServerCertificateL =
79
+ clientHooksL . lens TLS. onServerCertificate (\ ch osc -> ch { TLS. onServerCertificate = osc })
80
+
70
81
-- | Don't check whether the cert presented by the server matches the name of the server you are connecting to.
71
82
-- This is necessary if you specify the server host by its IP address.
72
83
disableServerNameValidation :: TLS. ClientParams -> TLS. ClientParams
73
- disableServerNameValidation cp = cp
74
- { TLS. clientHooks = (TLS. clientHooks cp)
75
- { TLS. onServerCertificate = X509. validate
76
- X509. HashSHA256
77
- def
78
- def { X509. checkFQHN = False }
79
- }
80
- }
84
+ disableServerNameValidation =
85
+ set onServerCertificateL (X509. validate X509. HashSHA256 def (def { X509. checkFQHN = False }))
81
86
82
87
-- | Insecure mode. The client will not validate the server cert at all.
83
88
disableServerCertValidation :: TLS. ClientParams -> TLS. ClientParams
84
- disableServerCertValidation cp = cp
85
- { TLS. clientHooks = (TLS. clientHooks cp)
86
- { TLS. onServerCertificate = (\ _ _ _ _ -> return [] )
87
- }
88
- }
89
+ disableServerCertValidation = set onServerCertificateL (\ _ _ _ _ -> return [] )
89
90
90
91
-- | Use a custom CA store.
91
92
setCAStore :: [SignedCertificate ] -> TLS. ClientParams -> TLS. ClientParams
@@ -95,13 +96,13 @@ setCAStore certs cp = cp
95
96
}
96
97
}
97
98
99
+ onCertificateRequestL :: Lens' TLS. ClientParams (([TLS. CertificateType ], Maybe [TLS. HashAndSignatureAlgorithm ], [X509. DistinguishedName ]) -> IO (Maybe (X509. CertificateChain , TLS. PrivKey )))
100
+ onCertificateRequestL =
101
+ clientHooksL . lens TLS. onCertificateRequest (\ ch ocr -> ch { TLS. onCertificateRequest = ocr })
102
+
98
103
-- | Use a client cert for authentication.
99
104
setClientCert :: Credential -> TLS. ClientParams -> TLS. ClientParams
100
- setClientCert cred cp = cp
101
- { TLS. clientHooks = (TLS. clientHooks cp)
102
- { TLS. onCertificateRequest = (\ _ -> return (Just cred))
103
- }
104
- }
105
+ setClientCert cred = set onCertificateRequestL (\ _ -> return $ Just cred)
105
106
106
107
-- | Parses a PEM-encoded @ByteString@ into a list of certificates.
107
108
parsePEMCerts :: B. ByteString -> Either String [SignedCertificate ]
@@ -119,3 +120,17 @@ loadPEMCerts p = do
119
120
liftIO (B. readFile p)
120
121
>>= either (throwM . ParsePEMCertsException ) return
121
122
. parsePEMCerts
123
+
124
+ serviceAccountDir :: FilePath
125
+ serviceAccountDir = " /var/run/secrets/kubernetes.io/serviceaccount"
126
+
127
+ cluster :: (MonadIO m , MonadThrow m ) => m (NH. Manager , K. KubernetesConfig )
128
+ cluster = do
129
+ caStore <- loadPEMCerts $ serviceAccountDir ++ " /ca.crt"
130
+ defTlsParams <- liftIO defaultTLSClientParams
131
+ mgr <- liftIO . newManager . setCAStore caStore $ disableServerNameValidation defTlsParams
132
+ tok <- liftIO . T. readFile $ serviceAccountDir ++ " /token"
133
+ host <- liftIO $ getEnv " KUBERNETES_SERVICE_HOST"
134
+ port <- liftIO $ getEnv " KUBERNETES_SERVICE_PORT"
135
+ config <- setTokenAuth tok . setMasterURI (T. pack $ " https://" ++ host ++ " :" ++ port) <$> liftIO K. newConfig
136
+ return (mgr, config)
0 commit comments