on develop help sign in
Commenting authentication variables and functions
commit197d3ade645d03ab2eb9f74a11e12cdcd875563b authorBrendan Hay <brendan.g.hay@gmail.com> dateSun 18 Oct 2015, 11:24 (11 years ago) parentd93bd0d
1 file changed+115−12
gogol/src/Network/Google/Auth.hs+115−12
gogol/src/Network/Google/Auth.hs+115−12
@@ -18,7 +18,52 @@
1818--
1919-- Explicitly specify your Google credentials, or retrieve them
2020-- from the underlying OS.
21−module Network.Google.Auth where
21+module Network.Google.Auth
22+ (
23+ -- * Authentication
24+ -- ** Retrieving Authentication
25+ getAuth
26+ , Credentials (..)
27+ , Auth
28+
29+ -- ** Defaults
30+ -- *** Metadata
31+ , metadataHost
32+ , metadataFlavorHeader
33+ , metadataFlavorDesired
34+
35+ -- *** GCE
36+ , checkGCEVar
37+
38+ -- *** Cloud SDK
39+ , cloudSDKCredentialsDirVar
40+ , cloudSDKCredentialsDir
41+ , cloudSDKCredentialsFile
42+ , cloudSDKCredentialsPath
43+
44+ -- *** Application Default Credentials
45+ , defaultCredentialsFileVar
46+ , defaultCredentialsPath
47+
48+ -- ** Credentials
49+ , fromToken
50+ , fromFile
51+ , fromFilePath
52+ , fromAccount
53+
54+ -- ** Authentication Tokens
55+ , refreshToken
56+
57+ -- ** Handling Errors
58+ , AsAuthError (..)
59+ , AuthError (..)
60+
61+ -- ** Re-exported Types
62+ , OAuthScope (..)
63+ , OAuthToken (..)
64+ , ServiceId (..)
65+ , ClientId (..)
66+ ) where
2267
2368import Control.Concurrent
2469import Control.Exception.Lens
@@ -44,8 +89,10 @@ import System.Environment (lookupEnv)
4489import System.FilePath ((</>))
4590import System.Info (os)
4691
47−accountsHost, metadataHost :: ByteString
92+accountsHost :: ByteString
4893accountsHost = "accounts.google.com"
94+
95+metadataHost :: ByteString
4996metadataHost = "metadata.google.internal"
5097
5198metadataFlavorHeader :: HeaderName
@@ -54,8 +101,8 @@ metadataFlavorHeader = "Metadata-Flavor"
54101metadataFlavorDesired :: ByteString
55102metadataFlavorDesired = "Google"
56103
57−noGCECheck :: String
58−noGCECheck = "NO_GCE_CHECK"
104+checkGCEVar :: String
105+checkGCEVar = "NO_GCE_CHECK"
59106
60107-- | The environment variable name which can replace ~/.config if set.
61108cloudSDKCredentialsDirVar :: String
@@ -72,6 +119,7 @@ cloudSDKCredentialsFile = "application_default_credentials.json"
72119defaultCredentialsFileVar :: String
73120defaultCredentialsFileVar = "GOOGLE_APPLICATION_CREDENTIALS"
74121
122+-- | An error thrown when attempting to read AuthN/AuthZ information.
75123data AuthError
76124 = RetrievalError HttpException
77125 | MissingFileError FilePath
@@ -130,13 +178,36 @@ instance AsAuthError AuthError where
130178 TokenRefreshError s e d -> Right (s, e, d)
131179 x -> Left x)
132180
181+-- | Determines how AuthN/AuthZ information is retrieved.
133182data Credentials
134− = FromToken !OAuthToken
135− | FromFile !FilePath
183+ = FromToken !OAuthToken
184+ -- ^ Supply an explicit access token. See 'fromToken'.
185+
186+ | FromFile !FilePath
187+ -- ^ Load the Application Default Credentials from a specific filepath.
188+
136189 | FromAccount !ServiceId
190+ -- ^ Retrieve the Application Default Credentials using the speicfic
191+ -- 'ServiceId' from the local metadata endpoint.
192+
137193 | Discover
194+ -- ^ Attempt credentials discovery via the following steps:
195+ --
196+ -- * Read the default credentials from a file specified by
197+ -- the environment variable @GOOGLE_APPLICATION_CREDENTIALS@ if it exists.
198+ --
199+ -- * Read the platform equivalent of @~/.config/gcloud/application_default_credentials.json@ if it exists.
200+ -- The @~/.config@ component of the path can be overriden by the environment
201+ -- variable @CLOUDSDK_CONFIG@ if it exists.
202+ --
203+ -- * Retrieve the default service account application credentials if
204+ -- running on GCE.
138205 deriving (Eq, Show)
139206
207+-- | Retrieve authentication information via the specified 'Credentials' mechanism.
208+--
209+-- Throws 'AuthError' when environment variables or service account information
210+-- cannot be read, and credentials files are invalid or cannot be found.
140211getAuth :: (MonadIO m, MonadCatch m) => Manager -> Credentials -> m Auth
141212getAuth m = \case
142213 FromToken t -> pure (fromToken t)
@@ -149,9 +220,21 @@ getAuth m = \case
149220 throwingM _MissingFileError f
150221 fromAccount m "default"
151222
223+-- | An explicit access token.
152224fromToken :: OAuthToken -> Auth
153225fromToken = Tok
154226
227+-- | Try the two offical locations for the application credentials:
228+--
229+-- * Read the default credentials from a file specified by
230+-- the environment variable @GOOGLE_APPLICATION_CREDENTIALS@ if it exists.
231+--
232+-- * Read the platform equivalent of @~/.config/gcloud/application_default_credentials.json@ if it exists.
233+-- The @~/.config@ component of the path can be overriden by the environment
234+-- variable @CLOUDSDK_CONFIG@ if it exists.
235+--
236+-- The read credentials will then be automatically refreshed to obtain a valid
237+-- access token, eagerly, to ensure errors propagate promptly.
155238fromFile :: MonadIO m => Manager -> m Auth
156239fromFile m = do
157240 mf <- defaultCredentialsPath
@@ -159,6 +242,10 @@ fromFile m = do
159242 Just f -> fromFilePath m f
160243 Nothing -> cloudSDKCredentialsPath >>= fromFilePath m
161244
245+-- | Read a specific file for the application credentials.
246+--
247+-- The read credentials will then be automatically refreshed to obtain a valid
248+-- access token, eagerly, to ensure errors propagate promptly.
162249fromFilePath :: MonadIO m => Manager -> FilePath -> m Auth
163250fromFilePath m f = liftIO $ do
164251 p <- doesFileExist f
@@ -169,6 +256,8 @@ fromFilePath m f = liftIO $ do
169256 !r <- refresh m u
170257 Ref m <$> newMVar (r :: Refresh User)
171258
259+-- | Retrieve the credentials from the @/computeMetadata/v1/instance/service-accounts/@
260+-- endpoint using the specific service identifier.
172261fromAccount :: MonadIO m => Manager -> ServiceId -> m Auth
173262fromAccount m s = liftIO $ do
174263 !r <- refresh m s
@@ -178,6 +267,9 @@ data Auth where
178267 Tok :: OAuthToken -> Auth
179268 Ref :: RefreshToken a => Manager -> MVar (Refresh a) -> Auth
180269
270+-- | Perform a safe refresh of the access token by performing a non-blocking
271+-- read. Ensures there is only a single producer for the underlying authentication
272+-- refresh, causing other readers to block during the refresh process.
181273refreshToken :: MonadIO m => Auth -> m OAuthToken
182274refreshToken (Tok t) = pure t
183275refreshToken (Ref m r) = liftIO $ do
@@ -193,25 +285,36 @@ refreshToken (Ref m r) = liftIO $ do
193285 z <- refresh m (_rTarget y)
194286 pure (z, _rToken z)
195287
288+-- | Check if the refresh context is still valid, that is, has not expired.
196289isValid :: Refresh a -> IO Bool
197290isValid r = (< _rExpiry r) <$> getCurrentTime
198291
292+-- | Return the filepath to the Cloud SDK well known file location such as
293+-- @~/.config/gcloud/application_default_credentials.json@.
199294cloudSDKCredentialsPath :: MonadIO m => m FilePath
200295cloudSDKCredentialsPath = liftIO $ do
201296 v <- lookupEnv cloudSDKCredentialsDirVar
202297 h <- getHomeDirectory
203298 let d = case v of
204− Nothing | os == "windows" -> h </> cloudSDKCredentialsDir
205− Nothing -> h </> ".config" </> cloudSDKCredentialsDir
206− Just x -> h </> x
207− pure $! d </> cloudSDKCredentialsFile
208−
299+ Nothing | os == "windows" -> h
300+ Nothing -> h </> ".config"
301+ Just x -> x
302+ pure $! d
303+ </> cloudSDKCredentialsDir
304+ </> cloudSDKCredentialsFile
305+
306+-- | Lookup the @GOOGLE_APPLICATION_CREDENTIALS@ environment variable for the
307+-- default application credentials filepath.
209308defaultCredentialsPath :: MonadIO m => m (Maybe FilePath)
210309defaultCredentialsPath = liftIO (lookupEnv defaultCredentialsFileVar)
211310
311+-- | Detect if the underlying host is running on GCE.
312+--
313+-- The environment variable @NO_GCE_CHECK@ can be set to @1@, @true@, @yes@, or @on@
314+-- to skip this check and always return @False@.
212315detectGCE :: MonadIO m => Manager -> m Bool
213316detectGCE m = liftIO $ do
214− p <- check <$> lookupEnv noGCECheck
317+ p <- check <$> lookupEnv checkGCEVar
215318 if p
216319 then (success <$> httpLbs rq m) `catch` failure
217320 else pure False