@@ -133,34 +133,10 @@ import Network.HTTP.Conduit hiding
133 (Request)
133 (Request)
134import qualified Network.HTTP.Conduit as Client
134import qualified Network.HTTP.Conduit as Client
135import Network.HTTP.Types
135import Network.HTTP.Types
136−
136+import System.Directory (doesFileExist, getHomeDirectory)
137−-- | Attempt credentials discovery via the following steps:
137+import System.Environment (lookupEnv)
138−--
138+import System.FilePath ((</>))
139−-- * Read the default credentials from a file specified by
139+import System.Info (os)
140−-- the environment variable @GOOGLE_APPLICATION_CREDENTIALS@ if it exists.
142−-- * Read the platform equivalent of @~\/.config\/gcloud\/application_default_credentials.json@ if it exists.
143−-- The @~/.config@ component of the path can be overriden by the environment
144−-- variable @CLOUDSDK_CONFIG@ if it exists.
146−-- * Retrieve the default service account application credentials if
147−-- running on GCE. The environment variable @NO_GCE_CHECK@ can be used to
148−-- skip this check if set to a truthy value such as @1@ or @true@.
150−-- The specified 'Scope's are used to authorize any @service_account@ that is
151−-- found with the appropriate scopes, otherwise they are not used. See the
152−-- top-level module of each individual @gogol-*@ library for a list of available
153−-- scopes, such as @Network.Google.Compute.computeScope@.
154−-- discover :: (MonadIO m, MonadCatch m)
159−-- catching _MissingFileError (fromFile ss) $ \f -> do
162−-- throwingM _MissingFileError f
163−-- pure $! FromMetadata "default"
165-- | The supported credential mechanisms.
141-- | The supported credential mechanisms.
166data Credentials
142data Credentials
@@ -189,6 +165,85 @@ data Credentials
189 -- An 'AuthorizedUser' is typically created by the @gcloud init@ command
165 -- An 'AuthorizedUser' is typically created by the @gcloud init@ command
190 -- of the Google CloudSDK Tools.
166 -- of the Google CloudSDK Tools.
168+-- | Attempt credentials discovery via the following steps:
170+-- * Read the default credentials from a file specified by
171+-- the environment variable @GOOGLE_APPLICATION_CREDENTIALS@ if it exists.
173+-- * Read the platform equivalent of @~\/.config\/gcloud\/application_default_credentials.json@ if it exists.
174+-- The @~/.config@ component of the path can be overriden by the environment
175+-- variable @CLOUDSDK_CONFIG@ if it exists.
177+-- * Retrieve the default service account application credentials if
178+-- running on GCE. The environment variable @NO_GCE_CHECK@ can be used to
179+-- skip this check if set to a truthy value such as @1@ or @true@.
181+-- The specified 'Scope's are used to authorize any @service_account@ that is
182+-- found with the appropriate scopes, otherwise they are not used. See the
183+-- top-level module of each individual @gogol-*@ library for a list of available
184+-- scopes, such as @Network.Google.Compute.computeScope@.
185+discover :: (MonadIO m, MonadCatch m)
190+ catching _MissingFileError (fromFile ss) $ \f -> do
193+ throwingM _MissingFileError f
194+ pure $! FromMetadata "default"
196+-- | Attempt to load either a @service_account@ or @authorized_user@ formatted
197+-- file to obtain the credentials neccessary to perform a token refresh.
199+-- The specified 'Scope's are used to authorize any @service_account@ that is
200+-- found with the appropriate scopes, otherwise they are not used. See the
201+-- top-level module of each individual @gogol-*@ library for a list of available
202+-- scopes, such as @Network.Google.Compute.computeScope@.
204+-- /See:/ 'cloudSDKConfigPath', 'defaultCredentialsPath'.
205+fromFile :: (MonadIO m, MonadCatch m) => [OAuthScope] -> m Credentials
207+ f <- defaultCredentialsPath
209+ Just x -> fromFilePath ss x
211+ x <- cloudSDKConfigPath
214+-- | Attempt to load either a @service_account@ or @authorized_user@ formatted
215+-- file to obtain the credentials neccessary to perform a token refresh from
216+-- the specified file.
218+-- The specified 'Scope's are used to authorize any @service_account@ that is
219+-- found with the appropriate scopes, otherwise they are not used. See the
220+-- top-level module of each individual @gogol-*@ library for a list of available
221+-- scopes, such as @Network.Google.Compute.computeScope@.
222+fromFilePath :: (MonadIO m, MonadCatch m)
226+fromFilePath ss f = do
227+ p <- liftIO (doesFileExist f)
229+ throwM (MissingFileError f)
230+ bs <- liftIO (LBS.readFile f)
231+ either (throwM . InvalidFileError f . Text.pack) pure
232+ (fromJSONCredentials ss bs)
234+fromJSONCredentials :: [OAuthScope]
236+ -> Either String Credentials
237+fromJSONCredentials ss bs = do
238+ v <- eitherDecode' bs
239+ let x = (`FromAccount` ss) <$> parseEither parseJSON v
240+ y = FromUser <$> parseEither parseJSON v
242+ (Left xe, Left ye) -> Left $
243+ "Failed parsing service_account: " ++ xe ++
244+ ", Failed parsing authorized_user: " ++ ye
192exchange :: (MonadIO m, MonadCatch m)
247exchange :: (MonadIO m, MonadCatch m)
193 => Credentials
248 => Credentials
194 -> Logger
249 -> Logger