Skip to content

S3 providers should support temporary AWS credentials (STS/IRSA) #2772

@MKL2000

Description

@MKL2000

Component(s)

router, controlplane

Is your feature request related to a problem? Please describe.

Self-hosted Cosmo cannot use AWS temporary credentials (STS AssumeRole, IRSA, EKS Pod Identity) for S3 storage. This is the standard credential model in most Kubernetes environments, and the lack of support blocks adoption for anyone following AWS security best practices.

There are two root causes:

  1. No default credential chain fallback. The Node.js components (controlplane + CDN server) throw an error when credentials are empty, preventing the @aws-sdk default credential provider chain from being used. This blocks IRSA and other IAM-based auth that requires zero explicit credential configuration.
  2. No session token passthrough. The router, controlplane, and CDN server all accept accessKeyId / secretAccessKey but there is no config field for a sessionToken. All AWS temporary credentials consist of a three-tuple (access key + secret key + session token); the token is required at the AWS signing layer, even though in most deployments the SDK can obtain it transparently (see Fix 1). This matters when credentials are provided explicitly via Cosmo's own config.

Related: #2159 (covers CDN server IRSA only — this issue expands to all components + adds session token passthrough).

Describe the solution you'd like

Two complementary fixes. Priority depends on the component:

  • Node.js components (controlplane + CDN server): Fix 1 alone covers the most common deployments (IRSA, env vars, instance metadata). Fix 2 is a nice-to-have.
  • Go router: Fix 1 provides only partial coverage due to minio-go's limited built-in credential chain (see note below). Fix 2 is the more impactful change, letting operators pass STS credentials from an external source.

Fix 1 — Default credential chain fallback (Node.js)

When accessKeyId and secretAccessKey are both empty, omit the credentials field instead of throwing. The @aws-sdk SDK will then use its default credential provider chain:

  1. Environment variables (AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY + AWS_SESSION_TOKEN)
  2. Shared credentials file (~/.aws/credentials)
  3. IRSA / EKS Pod Identity — SDK internally calls STS AssumeRoleWithWebIdentity and manages session token rotation transparently
  4. EC2 / ECS instance metadata (IMDSv2)

Session tokens are handled transparently in all of these paths — the SDK manages them without the application needing to pass them explicitly.

const config: S3ClientConfig = { region, endpoint, forcePathStyle };

if (accessKeyId && secretAccessKey) {
    config.credentials = {
        accessKeyId,
        secretAccessKey,
        ...(sessionToken && { sessionToken }),
    };
}

return config;

Note on the Go router and minio-go

The router uses minio-go's NewChainCredentials([Static, IAM]). When static credentials are empty, the chain falls through to the IAM provider — but this only queries the EC2/ECS metadata endpoint (169.254.169.254). It does not read AWS_* environment variables and does not support IRSA web identity tokens.

To match Node.js coverage, the Go chain would need additional providers (EnvAWS, a web-identity provider, etc.). This is a larger change and is why Fix 2 (explicit session token passthrough) is the more practical short-term path for the router.

Fix 2 — Session token passthrough

Add an optional sessionToken / S3_SESSION_TOKEN field to all S3 client configurations. This lets operators obtain STS credentials externally (e.g. via an init container) and pass them through Cosmo's own config.

Go example:

&credentials.Static{
    Value: credentials.Value{
        AccessKeyID:     options.AccessKeyID,
        SecretAccessKey: options.SecretAccessKey,
        SessionToken:    options.SessionToken,
        SignerType:      credentials.SignatureV4,
    },
}

Node.js: add S3_SESSION_TOKEN env var and pass it through to the credentials object.

Which fix covers which scenario?

Node.js components (controlplane + CDN server):

Scenario Fix 1 alone Needs Fix 2
IRSA / EKS Pod Identity
AWS_* env vars (including AWS_SESSION_TOKEN)
EC2 / ECS instance metadata
~/.aws/credentials file
STS credentials passed via Cosmo config (S3_SESSION_TOKEN)

Go router:

Scenario Fix 1 alone Needs Fix 2
EC2 / ECS instance metadata
IRSA / EKS Pod Identity ❌ (minio-go limitation) ✅ (via external STS tooling + S3_SESSION_TOKEN)
AWS_* env vars ❌ (minio-go limitation)
STS credentials passed via Cosmo config (S3_SESSION_TOKEN)

Describe alternatives you've considered

No response

Additional context

  • All changes are purely additive — new fields are optional, existing configurations continue to work without modification.
  • Affects any self-hosted Cosmo deployment in an AWS environment using credential rotation: EKS (IRSA / Pod Identity), ECS task roles, EC2 instance roles, or any setup where IAM credentials are injected via STS rather than long-lived access keys. AWS recommends temporary credentials as a best practice.
  • Community interest: Add IAM IRSA Support for S3 Authentication in CDN Server #2159 (CDN server IRSA) has been open and internally-reviewed since Aug 2025 without resolution. This issue expands the scope to all three components (router, controlplane, CDN server) — fixing only the CDN server would leave controlplane and router broken in the same deployment, since controlplane is the S3 writer and its failure blocks the entire schema pipeline.
  • I'm happy to submit a PR for this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions