module Ecluse.Core.Credential.CodeArtifact (
CodeArtifactConfig (..),
newCodeArtifactProvider,
providerForEnv,
) where
import Amazonka qualified as AWS
import Amazonka.CodeArtifact.GetAuthorizationToken qualified as CA
import Control.Monad.Trans.Resource (runResourceT)
import Data.Time (getCurrentTime)
import Lens.Micro (Lens', (?~), (^.))
import UnliftIO.Exception (throwIO)
import Ecluse.Core.Credential (AuthToken (..), CredentialProvider, mkSecret)
import Ecluse.Core.Credential.Refresh (
CredentialReporters (..),
RefreshConfig (..),
defaultRefreshConfig,
refreshingProvider,
)
data CodeArtifactMintError = AuthorizationTokenMissing
deriving stock (CodeArtifactMintError -> CodeArtifactMintError -> Bool
(CodeArtifactMintError -> CodeArtifactMintError -> Bool)
-> (CodeArtifactMintError -> CodeArtifactMintError -> Bool)
-> Eq CodeArtifactMintError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CodeArtifactMintError -> CodeArtifactMintError -> Bool
== :: CodeArtifactMintError -> CodeArtifactMintError -> Bool
$c/= :: CodeArtifactMintError -> CodeArtifactMintError -> Bool
/= :: CodeArtifactMintError -> CodeArtifactMintError -> Bool
Eq, Int -> CodeArtifactMintError -> ShowS
[CodeArtifactMintError] -> ShowS
CodeArtifactMintError -> String
(Int -> CodeArtifactMintError -> ShowS)
-> (CodeArtifactMintError -> String)
-> ([CodeArtifactMintError] -> ShowS)
-> Show CodeArtifactMintError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CodeArtifactMintError -> ShowS
showsPrec :: Int -> CodeArtifactMintError -> ShowS
$cshow :: CodeArtifactMintError -> String
show :: CodeArtifactMintError -> String
$cshowList :: [CodeArtifactMintError] -> ShowS
showList :: [CodeArtifactMintError] -> ShowS
Show)
instance Exception CodeArtifactMintError
data CodeArtifactConfig = CodeArtifactConfig
{ CodeArtifactConfig -> Text
caRegion :: Text
, CodeArtifactConfig -> Text
caDomain :: Text
, CodeArtifactConfig -> Maybe Text
caDomainOwner :: Maybe Text
, CodeArtifactConfig -> Maybe Natural
caDurationSeconds :: Maybe Natural
}
deriving stock (CodeArtifactConfig -> CodeArtifactConfig -> Bool
(CodeArtifactConfig -> CodeArtifactConfig -> Bool)
-> (CodeArtifactConfig -> CodeArtifactConfig -> Bool)
-> Eq CodeArtifactConfig
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CodeArtifactConfig -> CodeArtifactConfig -> Bool
== :: CodeArtifactConfig -> CodeArtifactConfig -> Bool
$c/= :: CodeArtifactConfig -> CodeArtifactConfig -> Bool
/= :: CodeArtifactConfig -> CodeArtifactConfig -> Bool
Eq, Int -> CodeArtifactConfig -> ShowS
[CodeArtifactConfig] -> ShowS
CodeArtifactConfig -> String
(Int -> CodeArtifactConfig -> ShowS)
-> (CodeArtifactConfig -> String)
-> ([CodeArtifactConfig] -> ShowS)
-> Show CodeArtifactConfig
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CodeArtifactConfig -> ShowS
showsPrec :: Int -> CodeArtifactConfig -> ShowS
$cshow :: CodeArtifactConfig -> String
show :: CodeArtifactConfig -> String
$cshowList :: [CodeArtifactConfig] -> ShowS
showList :: [CodeArtifactConfig] -> ShowS
Show)
newCodeArtifactProvider :: CredentialReporters -> CodeArtifactConfig -> IO CredentialProvider
newCodeArtifactProvider :: CredentialReporters -> CodeArtifactConfig -> IO CredentialProvider
newCodeArtifactProvider CredentialReporters
reporters CodeArtifactConfig
cfg =
(EnvNoAuth -> IO Env) -> IO Env
forall (m :: * -> *). MonadIO m => (EnvNoAuth -> m Env) -> m Env
AWS.newEnv EnvNoAuth -> IO Env
forall (m :: * -> *) (withAuth :: * -> *).
(MonadCatch m, MonadIO m, Foldable withAuth) =>
Env' withAuth -> m Env
AWS.discover IO Env -> (Env -> IO CredentialProvider) -> IO CredentialProvider
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Env
env -> CredentialReporters
-> Env -> CodeArtifactConfig -> IO CredentialProvider
providerForEnv CredentialReporters
reporters Env
env CodeArtifactConfig
cfg
providerForEnv :: CredentialReporters -> AWS.Env -> CodeArtifactConfig -> IO CredentialProvider
providerForEnv :: CredentialReporters
-> Env -> CodeArtifactConfig -> IO CredentialProvider
providerForEnv CredentialReporters
reporters Env
env CodeArtifactConfig
cfg =
RefreshConfig -> IO CredentialProvider
refreshingProvider
RefreshConfig
defaultRefreshConfig
{ rcMint = mintToken (regioned env) (tokenRequest cfg)
, rcClock = getCurrentTime
, rcBreakerReporter = crBreakerReporter reporters
, rcRefreshReporter = crRefreshReporter reporters
}
where
regioned :: AWS.Env -> AWS.Env
regioned :: Env -> Env
regioned Env
e = Env
e{AWS.region = AWS.Region' (caRegion cfg)}
tokenRequest :: CodeArtifactConfig -> CA.GetAuthorizationToken
tokenRequest :: CodeArtifactConfig -> GetAuthorizationToken
tokenRequest CodeArtifactConfig
cfg =
Lens' GetAuthorizationToken (Maybe Text)
-> Maybe Text -> GetAuthorizationToken -> GetAuthorizationToken
forall s a. Lens' s (Maybe a) -> Maybe a -> s -> s
setOptional (Maybe Text -> f (Maybe Text))
-> GetAuthorizationToken -> f GetAuthorizationToken
Lens' GetAuthorizationToken (Maybe Text)
CA.getAuthorizationToken_domainOwner (CodeArtifactConfig -> Maybe Text
caDomainOwner CodeArtifactConfig
cfg)
(GetAuthorizationToken -> GetAuthorizationToken)
-> (GetAuthorizationToken -> GetAuthorizationToken)
-> GetAuthorizationToken
-> GetAuthorizationToken
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' GetAuthorizationToken (Maybe Natural)
-> Maybe Natural -> GetAuthorizationToken -> GetAuthorizationToken
forall s a. Lens' s (Maybe a) -> Maybe a -> s -> s
setOptional (Maybe Natural -> f (Maybe Natural))
-> GetAuthorizationToken -> f GetAuthorizationToken
Lens' GetAuthorizationToken (Maybe Natural)
CA.getAuthorizationToken_durationSeconds (CodeArtifactConfig -> Maybe Natural
caDurationSeconds CodeArtifactConfig
cfg)
(GetAuthorizationToken -> GetAuthorizationToken)
-> GetAuthorizationToken -> GetAuthorizationToken
forall a b. (a -> b) -> a -> b
$ Text -> GetAuthorizationToken
CA.newGetAuthorizationToken (CodeArtifactConfig -> Text
caDomain CodeArtifactConfig
cfg)
mintToken :: AWS.Env -> CA.GetAuthorizationToken -> IO AuthToken
mintToken :: Env -> GetAuthorizationToken -> IO AuthToken
mintToken Env
env GetAuthorizationToken
request = do
response <- ResourceT IO GetAuthorizationTokenResponse
-> IO GetAuthorizationTokenResponse
forall (m :: * -> *) a. MonadUnliftIO m => ResourceT m a -> m a
runResourceT (Env
-> GetAuthorizationToken
-> ResourceT IO (AWSResponse GetAuthorizationToken)
forall (m :: * -> *) a.
(MonadResource m, AWSRequest a) =>
Env -> a -> m (AWSResponse a)
AWS.send Env
env GetAuthorizationToken
request)
secret <- case response ^. CA.getAuthorizationTokenResponse_authorizationToken of
Just Text
token -> Secret -> IO Secret
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Secret
mkSecret Text
token)
Maybe Text
Nothing -> CodeArtifactMintError -> IO Secret
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO CodeArtifactMintError
AuthorizationTokenMissing
pure
AuthToken
{ authSecret = secret
, authExpiresAt = response ^. CA.getAuthorizationTokenResponse_expiration
}
setOptional :: Lens' s (Maybe a) -> Maybe a -> s -> s
setOptional :: forall s a. Lens' s (Maybe a) -> Maybe a -> s -> s
setOptional Lens' s (Maybe a)
l = (s -> s) -> (a -> s -> s) -> Maybe a -> s -> s
forall b a. b -> (a -> b) -> Maybe a -> b
maybe s -> s
forall a. a -> a
id ((Maybe a -> Identity (Maybe a)) -> s -> Identity s
Lens' s (Maybe a)
l ((Maybe a -> Identity (Maybe a)) -> s -> Identity s) -> a -> s -> s
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~)