module Ecluse.Composition.Credential (
CredentialProviders,
initCredentialProviders,
initializedEcosystems,
lookupProvider,
codeArtifactIdentityGroups,
) where
import Data.Map.Strict qualified as Map
import UnliftIO (tryAny)
import Ecluse.Composition.BootError (BootError (..))
import Ecluse.Config (
Config (..),
MirrorCredential (..),
MirrorTarget (..),
Mount (..),
regMirrorTarget,
)
import Ecluse.Core.Credential (AuthToken (..), CredentialProvider, Secret, staticProvider)
import Ecluse.Core.Credential.Refresh (CredentialReporters)
import Ecluse.Core.Ecosystem (Ecosystem)
import Ecluse.Core.Text (displayExceptionT)
import Ecluse.Runtime.Credential.CodeArtifact (CodeArtifactConfig, newCodeArtifactProvider)
newtype CredentialProviders = CredentialProviders (Map Ecosystem CredentialProvider)
initCredentialProviders :: CredentialReporters -> Config -> IO (Either [BootError] CredentialProviders)
initCredentialProviders :: CredentialReporters
-> Config -> IO (Either [BootError] CredentialProviders)
initCredentialProviders CredentialReporters
reporters Config
config = do
let creds :: [(Ecosystem, MirrorCredential)]
creds =
[ (Ecosystem
eco, MirrorTarget -> MirrorCredential
mtCredential MirrorTarget
target)
| (Ecosystem
eco, Mount
mount) <- Map Ecosystem Mount -> [(Ecosystem, Mount)]
forall k a. Map k a -> [(k, a)]
Map.toList (Config -> Map Ecosystem Mount
configMounts Config
config)
, Just MirrorTarget
target <- [MountRegistries -> Maybe MirrorTarget
regMirrorTarget (Mount -> MountRegistries
mountRegistries Mount
mount)]
]
let statics :: [(Ecosystem, CredentialProvider)]
statics = [(Ecosystem
eco, Secret -> CredentialProvider
staticProviderFor Secret
token) | (Ecosystem
eco, MirrorStatic Secret
token) <- [(Ecosystem, MirrorCredential)]
creds]
let caPlans :: [(Ecosystem, CodeArtifactConfig)]
caPlans = [(Ecosystem
eco, CodeArtifactConfig
ca) | (Ecosystem
eco, MirrorCodeArtifact CodeArtifactConfig
ca) <- [(Ecosystem, MirrorCredential)]
creds]
results <- ((CodeArtifactConfig, NonEmpty Ecosystem)
-> IO (Either [BootError] [(Ecosystem, CredentialProvider)]))
-> [(CodeArtifactConfig, NonEmpty Ecosystem)]
-> IO [Either [BootError] [(Ecosystem, CredentialProvider)]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (CredentialReporters
-> (CodeArtifactConfig, NonEmpty Ecosystem)
-> IO (Either [BootError] [(Ecosystem, CredentialProvider)])
initSharedCodeArtifact CredentialReporters
reporters) ([(Ecosystem, CodeArtifactConfig)]
-> [(CodeArtifactConfig, NonEmpty Ecosystem)]
codeArtifactIdentityGroups [(Ecosystem, CodeArtifactConfig)]
caPlans)
let (initErrs, shared) = partitionEithers results
if not (null initErrs)
then pure (Left (concat initErrs))
else pure (Right (CredentialProviders (Map.fromList (statics <> concat shared))))
initSharedCodeArtifact :: CredentialReporters -> (CodeArtifactConfig, NonEmpty Ecosystem) -> IO (Either [BootError] [(Ecosystem, CredentialProvider)])
initSharedCodeArtifact :: CredentialReporters
-> (CodeArtifactConfig, NonEmpty Ecosystem)
-> IO (Either [BootError] [(Ecosystem, CredentialProvider)])
initSharedCodeArtifact CredentialReporters
reporters (CodeArtifactConfig
caConfig, NonEmpty Ecosystem
ecosystems) =
IO CredentialProvider
-> IO (Either SomeException CredentialProvider)
forall (m :: * -> *) a.
MonadUnliftIO m =>
m a -> m (Either SomeException a)
tryAny (CredentialReporters -> CodeArtifactConfig -> IO CredentialProvider
newCodeArtifactProvider CredentialReporters
reporters CodeArtifactConfig
caConfig) IO (Either SomeException CredentialProvider)
-> (Either SomeException CredentialProvider
-> Either [BootError] [(Ecosystem, CredentialProvider)])
-> IO (Either [BootError] [(Ecosystem, CredentialProvider)])
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
Left SomeException
err -> [BootError] -> Either [BootError] [(Ecosystem, CredentialProvider)]
forall a b. a -> Either a b
Left [Text -> BootError
CodeArtifactMintFailed (SomeException -> Text
forall e. Exception e => e -> Text
displayExceptionT SomeException
err)]
Right CredentialProvider
provider -> [(Ecosystem, CredentialProvider)]
-> Either [BootError] [(Ecosystem, CredentialProvider)]
forall a b. b -> Either a b
Right [(Ecosystem
eco, CredentialProvider
provider) | Ecosystem
eco <- NonEmpty Ecosystem -> [Ecosystem]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty Ecosystem
ecosystems]
codeArtifactIdentityGroups :: [(Ecosystem, CodeArtifactConfig)] -> [(CodeArtifactConfig, NonEmpty Ecosystem)]
codeArtifactIdentityGroups :: [(Ecosystem, CodeArtifactConfig)]
-> [(CodeArtifactConfig, NonEmpty Ecosystem)]
codeArtifactIdentityGroups [(Ecosystem, CodeArtifactConfig)]
plans =
Map CodeArtifactConfig (NonEmpty Ecosystem)
-> [(CodeArtifactConfig, NonEmpty Ecosystem)]
forall k a. Map k a -> [(k, a)]
Map.toAscList ((NonEmpty Ecosystem -> NonEmpty Ecosystem -> NonEmpty Ecosystem)
-> [(CodeArtifactConfig, NonEmpty Ecosystem)]
-> Map CodeArtifactConfig (NonEmpty Ecosystem)
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith NonEmpty Ecosystem -> NonEmpty Ecosystem -> NonEmpty Ecosystem
forall a. Semigroup a => a -> a -> a
(<>) [(CodeArtifactConfig
ca, Ecosystem
eco Ecosystem -> [Ecosystem] -> NonEmpty Ecosystem
forall a. a -> [a] -> NonEmpty a
:| []) | (Ecosystem
eco, CodeArtifactConfig
ca) <- [(Ecosystem, CodeArtifactConfig)]
plans])
staticProviderFor :: Secret -> CredentialProvider
staticProviderFor :: Secret -> CredentialProvider
staticProviderFor Secret
token = AuthToken -> CredentialProvider
staticProvider AuthToken{authSecret :: Secret
authSecret = Secret
token, authExpiresAt :: Maybe UTCTime
authExpiresAt = Maybe UTCTime
forall a. Maybe a
Nothing}
initializedEcosystems :: CredentialProviders -> Set Ecosystem
initializedEcosystems :: CredentialProviders -> Set Ecosystem
initializedEcosystems (CredentialProviders Map Ecosystem CredentialProvider
ps) = Map Ecosystem CredentialProvider -> Set Ecosystem
forall k a. Map k a -> Set k
Map.keysSet Map Ecosystem CredentialProvider
ps
lookupProvider :: Ecosystem -> CredentialProviders -> Maybe CredentialProvider
lookupProvider :: Ecosystem -> CredentialProviders -> Maybe CredentialProvider
lookupProvider Ecosystem
eco (CredentialProviders Map Ecosystem CredentialProvider
ps) = Ecosystem
-> Map Ecosystem CredentialProvider -> Maybe CredentialProvider
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Ecosystem
eco Map Ecosystem CredentialProvider
ps