Use ADTs instead of Either String in GCP Auth code
This commit is contained in:
@@ -39,7 +39,7 @@ data GCPAuth = GCPAuth { gcpAccessToken :: TVar(Maybe Text)
|
|||||||
instance AuthMethod GCPAuth where
|
instance AuthMethod GCPAuth where
|
||||||
applyAuthMethod _ gcp req = do
|
applyAuthMethod _ gcp req = do
|
||||||
token <- getToken gcp
|
token <- getToken gcp
|
||||||
>>= either (throwM . GCPGetTokenException) pure
|
>>= either throwM pure
|
||||||
pure
|
pure
|
||||||
$ setHeader req [("Authorization", "Bearer " <> (Text.encodeUtf8 token))]
|
$ setHeader req [("Authorization", "Bearer " <> (Text.encodeUtf8 token))]
|
||||||
& L.set rAuthTypesL []
|
& L.set rAuthTypesL []
|
||||||
@@ -50,19 +50,25 @@ gcpAuth AuthInfo{authProvider = Just(AuthProviderConfig "gcp" (Just cfg))} (tls,
|
|||||||
= Just $ do
|
= Just $ do
|
||||||
configOrErr <- parseGCPAuthInfo cfg
|
configOrErr <- parseGCPAuthInfo cfg
|
||||||
case configOrErr of
|
case configOrErr of
|
||||||
Left e -> throwM $ GCPAuthParsingException e
|
Left e -> throwM e
|
||||||
Right gcp -> pure (tls, addAuthMethod kubecfg gcp)
|
Right gcp -> pure (tls, addAuthMethod kubecfg gcp)
|
||||||
gcpAuth _ _ = Nothing
|
gcpAuth _ _ = Nothing
|
||||||
|
|
||||||
data GCPAuthParsingException = GCPAuthParsingException String
|
data GCPAuthParsingException = GCPAuthMissingInformation String
|
||||||
|
| GCPAuthInvalidExpiry String
|
||||||
|
| GCPAuthInvalidTokenJSONPath String
|
||||||
|
| GCPAuthInvalidExpiryJSONPath String
|
||||||
deriving Show
|
deriving Show
|
||||||
instance Exception GCPAuthParsingException
|
instance Exception GCPAuthParsingException
|
||||||
|
|
||||||
data GCPGetTokenException = GCPGetTokenException String
|
data GCPGetTokenException = GCPCmdProducedInvalidJSON String
|
||||||
|
| GCPTokenNotFound String
|
||||||
|
| GCPTokenExpiryNotFound String
|
||||||
|
| GCPTokenExpiryInvalid String
|
||||||
deriving Show
|
deriving Show
|
||||||
instance Exception GCPGetTokenException
|
instance Exception GCPGetTokenException
|
||||||
|
|
||||||
getToken :: GCPAuth -> IO (Either String Text)
|
getToken :: GCPAuth -> IO (Either GCPGetTokenException Text)
|
||||||
getToken g@(GCPAuth{..}) = getCurrentToken g
|
getToken g@(GCPAuth{..}) = getCurrentToken g
|
||||||
>>= maybe (fetchToken g) (return . Right)
|
>>= maybe (fetchToken g) (return . Right)
|
||||||
|
|
||||||
@@ -77,38 +83,49 @@ getCurrentToken (GCPAuth{..}) = do
|
|||||||
then maybeToken
|
then maybeToken
|
||||||
else Nothing
|
else Nothing
|
||||||
|
|
||||||
-- TODO: log if parsed expiry is invalid
|
fetchToken :: GCPAuth -> IO (Either GCPGetTokenException Text)
|
||||||
fetchToken :: GCPAuth -> IO (Either String Text)
|
|
||||||
fetchToken GCPAuth{..} = do
|
fetchToken GCPAuth{..} = do
|
||||||
(stdOut, _) <- readProcess_ gcpCmd
|
(stdOut, _) <- readProcess_ gcpCmd
|
||||||
let credsJSON = Aeson.eitherDecode stdOut
|
case parseTokenAndExpiry stdOut of
|
||||||
token = runJSONPath gcpTokenKey =<< credsJSON
|
Right (token, expiry) -> do
|
||||||
expText = runJSONPath gcpExpiryKey =<< credsJSON
|
atomically $ do
|
||||||
expiry :: Either String (Maybe UTCTime)
|
writeTVar gcpAccessToken (Just token)
|
||||||
expiry = Just <$> (parseExpiryTime =<< expText)
|
writeTVar gcpTokenExpiry (Just expiry)
|
||||||
atomically $ do
|
return $ Right token
|
||||||
writeTVar gcpAccessToken (rightToMaybe token)
|
Left x -> return $ Left x
|
||||||
writeTVar gcpTokenExpiry (either (const Nothing) id expiry)
|
where
|
||||||
return token
|
parseTokenAndExpiry credsStr = do
|
||||||
|
credsJSON <- Aeson.eitherDecode credsStr
|
||||||
|
& mapLeft GCPCmdProducedInvalidJSON
|
||||||
|
token <- runJSONPath gcpTokenKey credsJSON
|
||||||
|
& mapLeft GCPTokenNotFound
|
||||||
|
expText <- runJSONPath gcpExpiryKey credsJSON
|
||||||
|
& mapLeft GCPTokenExpiryNotFound
|
||||||
|
expiry <- parseExpiryTime expText
|
||||||
|
& mapLeft GCPTokenExpiryInvalid
|
||||||
|
return (token, expiry)
|
||||||
|
|
||||||
parseGCPAuthInfo :: Map Text Text -> IO (Either String GCPAuth)
|
parseGCPAuthInfo :: Map Text Text -> IO (Either GCPAuthParsingException GCPAuth)
|
||||||
parseGCPAuthInfo m = do
|
parseGCPAuthInfo m = do
|
||||||
gcpAccessToken <- atomically $ newTVar $ Map.lookup "access-token" m
|
gcpAccessToken <- atomically $ newTVar $ Map.lookup "access-token" m
|
||||||
case maybe (pure Nothing) ((Just <$>) . parseExpiryTime) $ Map.lookup "expiry" m of
|
eitherGCPExpiryToken <- sequence $ fmap (atomically . newTVar) lookupAndParseExpiry
|
||||||
(Left e) -> return $ Left e
|
return $ do
|
||||||
Right t -> do
|
gcpTokenExpiry <- mapLeft GCPAuthInvalidExpiry eitherGCPExpiryToken
|
||||||
gcpTokenExpiry <- atomically $ newTVar t
|
cmdPath <- Text.unpack <$> lookupEither "cmd-path"
|
||||||
return $ do
|
cmdArgs <- Text.splitOn " " <$> lookupEither "cmd-args"
|
||||||
cmdPath <- Text.unpack <$> lookupEither m "cmd-path"
|
gcpTokenKey <- readJSONPath m "token-key" [JSONPath [KeyChild "token_expiry"]]
|
||||||
cmdArgs <- Text.splitOn " " <$> lookupEither m "cmd-args"
|
& mapLeft GCPAuthInvalidTokenJSONPath
|
||||||
gcpTokenKey <- readJSONPath m "token-key" [JSONPath [KeyChild "token_expiry"]]
|
gcpExpiryKey <- readJSONPath m "expiry-key" [JSONPath [KeyChild "access_token"]]
|
||||||
gcpExpiryKey <- readJSONPath m "expiry-key" [JSONPath [KeyChild "access_token"]]
|
& mapLeft GCPAuthInvalidExpiryJSONPath
|
||||||
let gcpCmd = proc cmdPath (map Text.unpack cmdArgs)
|
let gcpCmd = proc cmdPath (map Text.unpack cmdArgs)
|
||||||
pure $ GCPAuth{..}
|
pure $ GCPAuth{..}
|
||||||
|
where
|
||||||
lookupEither :: (Show key, Ord key) => Map key val -> key -> Either String val
|
lookupAndParseExpiry =
|
||||||
lookupEither m k = maybeToRight e $ Map.lookup k m
|
case Map.lookup "expiry" m of
|
||||||
where e = "Couldn't find key: " <> show k <> " in GCP auth info"
|
Nothing -> Right Nothing
|
||||||
|
Just expiryText -> Just <$> parseExpiryTime expiryText
|
||||||
|
lookupEither key = Map.lookup key m
|
||||||
|
& maybeToRight (GCPAuthMissingInformation $ Text.unpack key)
|
||||||
|
|
||||||
parseExpiryTime :: Text -> Either String UTCTime
|
parseExpiryTime :: Text -> Either String UTCTime
|
||||||
parseExpiryTime s = zonedTimeToUTC <$> parseTimeRFC3339 s
|
parseExpiryTime s = zonedTimeToUTC <$> parseTimeRFC3339 s
|
||||||
|
|||||||
Reference in New Issue
Block a user