module Ecluse.Config.MirrorCredential (
resolveMirrorCredential,
parseCodeArtifactHost,
isAccountId,
) where
import Data.Char (isDigit)
import Data.Text qualified as T
import Ecluse.Config.Types (ConfigError (..), MirrorCredential (..))
import Ecluse.Core.Credential (Secret)
import Ecluse.Core.Ecosystem (Ecosystem)
import Ecluse.Core.Security (hostAddress)
import Ecluse.Core.Security.Egress (RegistryUrl, registryUrlText)
import Ecluse.Core.Text (nonBlank)
import Ecluse.Runtime.Credential.CodeArtifact (CodeArtifactConfig (..))
resolveMirrorCredential ::
Ecosystem ->
RegistryUrl ->
Maybe Secret ->
Maybe Natural ->
Either ConfigError MirrorCredential
resolveMirrorCredential :: Ecosystem
-> RegistryUrl
-> Maybe Secret
-> Maybe Natural
-> Either ConfigError MirrorCredential
resolveMirrorCredential Ecosystem
eco RegistryUrl
url Maybe Secret
mToken Maybe Natural
mDuration =
case Text -> Maybe (Text, Text, Text)
parseCodeArtifactHost (Text -> Text
hostAddress (RegistryUrl -> Text
registryUrlText RegistryUrl
url)) of
Just (Text
domain, Text
owner, Text
region) -> case Maybe Secret
mToken of
Just Secret
_ -> ConfigError -> Either ConfigError MirrorCredential
forall a b. a -> Either a b
Left (Ecosystem -> ConfigError
MirrorCredentialConflict Ecosystem
eco)
Maybe Secret
Nothing ->
MirrorCredential -> Either ConfigError MirrorCredential
forall a b. b -> Either a b
Right
( CodeArtifactConfig -> MirrorCredential
MirrorCodeArtifact
CodeArtifactConfig
{ caRegion :: Text
caRegion = Text
region
, caDomain :: Text
caDomain = Text
domain
, caDomainOwner :: Maybe Text
caDomainOwner = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
owner
, caDurationSeconds :: Maybe Natural
caDurationSeconds = Maybe Natural
mDuration
}
)
Maybe (Text, Text, Text)
Nothing -> case Maybe Secret
mToken of
Just Secret
token -> MirrorCredential -> Either ConfigError MirrorCredential
forall a b. b -> Either a b
Right (Secret -> MirrorCredential
MirrorStatic Secret
token)
Maybe Secret
Nothing -> ConfigError -> Either ConfigError MirrorCredential
forall a b. a -> Either a b
Left (Ecosystem -> ConfigError
MirrorCredentialTokenMissing Ecosystem
eco)
parseCodeArtifactHost :: Text -> Maybe (Text, Text, Text)
parseCodeArtifactHost :: Text -> Maybe (Text, Text, Text)
parseCodeArtifactHost Text
host =
case HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
".d.codeartifact." Text
host of
[Text
domainOwner, Text
regionTail] -> do
region <- Text -> Maybe Text
nonBlank (Text -> Maybe Text) -> Maybe Text -> Maybe Text
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Text -> Text -> Maybe Text
T.stripSuffix Text
".amazonaws.com" Text
regionTail
let (domainDash, owner) = T.breakOnEnd "-" domainOwner
domain <- nonBlank (T.dropEnd 1 domainDash)
guard (isAccountId owner)
pure (domain, owner, region)
[Text]
_ -> Maybe (Text, Text, Text)
forall a. Maybe a
Nothing
isAccountId :: Text -> Bool
isAccountId :: Text -> Bool
isAccountId Text
t = Text -> Int -> Ordering
T.compareLength Text
t Int
12 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
EQ Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isDigit Text
t