ecluse
Safe HaskellNone
LanguageGHC2021

Ecluse.Composition.Credential

Description

The composition root's credential build: turn each active mount's resolved mirror-write credential into a live, process-global CredentialProvider.

Global providers, per-mount reference

A CredentialProvider is the service's own cloud identity, built once here from the resolved config and held process-global; a mount references one by its ecosystem and never holds its own. Which credential each mount uses is no longer selected here: it is __derived from the mirror-target URL at config load__ (resolveMirrorCredential) and carried on the mount as a MirrorCredential, so a CodeArtifact token can only ever be minted for the domain the worker actually writes to (issue #808). This module just realises that resolved plan:

  • MirrorStatic -- a stateless static provider from the operator-supplied token.
  • MirrorCodeArtifact -- the refresh/cache wrapper around the CodeArtifact mint leaf (newCodeArtifactProvider), which mints once eagerly, so a misconfigured identity or a missing permission fails loudly here at boot as a CodeArtifactMintFailed. AWS credentials are the ambient container/task role (the standard chain), never an Écluse key.

Provider granularity follows the credential's real scope, not the mount count: a CodeArtifact token is minted per domain, so mounts whose resolved CodeArtifact identities coincide (codeArtifactIdentityGroups) share one provider -- one eager boot mint, one refresh schedule, one breaker -- while each still looks its provider up by its own ecosystem.

The CredentialReporters are handed to the refreshing CodeArtifact provider so its mint breaker and refresh outcomes record to telemetry; the static provider never refreshes, so they do not concern it. The composition root supplies the deferred reporters that go live once the telemetry substrate exists. Failures aggregate as BootErrors, so one run reports every domain that failed to mint.

Synopsis

Global credential providers

data CredentialProviders Source #

The process-global credential providers, keyed by the ecosystem they serve. Built once at the composition root from the resolved config; a mount references one by ecosystem and never holds its own.

The keyset (see initializedEcosystems) is the boot-check's pure surface -- a mount that names an ecosystem absent from it has an unresolved credential reference.

initCredentialProviders :: CredentialReporters -> Config -> IO (Either [BootError] CredentialProviders) Source #

Build the global credential providers from the resolved config, or the aggregated boot errors that block them. Each mirrored mount already carries its resolved MirrorCredential (derived from its mirror-target URL at load), so this only realises it: a MirrorStatic becomes a stateless static provider; the MirrorCodeArtifact identities are grouped by domain and each built once, minting eagerly so a bad identity, region, or permission is a fail-loud CodeArtifactMintFailed here at boot rather than a first-publish surprise. A serve-only mount holds no write credential and contributes nothing; with zero mirrored mounts the provider map is empty and nothing mints.

initializedEcosystems :: CredentialProviders -> Set Ecosystem Source #

The set of ecosystems that resolved to an initialised provider -- the pure surface the boot-time credential-reference check reasons over.

lookupProvider :: Ecosystem -> CredentialProviders -> Maybe CredentialProvider Source #

Look up the initialised provider for an ecosystem, Nothing when none is initialised (the unresolved-reference case the boot check rejects).

Internals exported for testing

codeArtifactIdentityGroups :: [(Ecosystem, CodeArtifactConfig)] -> [(CodeArtifactConfig, NonEmpty Ecosystem)] Source #

Group the mounts' resolved CodeArtifact identities: one group per distinct CodeArtifactConfig (domain, owner, region, and the requested token duration), carrying every ecosystem that resolved it. The mint's real scope is the domain, not the repository endpoint, so ecosystems whose mirror targets live in one domain legitimately share one provider; a differing duration is a different requested credential and keeps its own. Pure, so the sharing decision is pinned without touching AWS.