Configuration

Secrets

Argus can resolve its secrets (registry credentials and the GitLab token) from a secret manager instead of plain environment variables. AWS Secrets Manager is supported today, through a provider model built to take more clouds.

Overview

Anywhere Argus reads a secret (a registry username/password in config.yml, or the GITLAB_PRIVATE_TOKEN), the value may be a $${{...}} reference. A reference is resolved at startup to its plaintext value; a plain value is used as-is. The same three reference forms work in both config.yml and environment variables, and secret values are never logged.

Reference syntax

  • $${{ENV_VAR}} reads from the environment (the original behaviour, unchanged).
  • $${{secret:<key>}} reads <key> from the configured secret bundle. Provider-neutral: the reference looks identical whichever cloud backs it.
  • $${{aws-secretsmanager:<secret-id>#<json-key>}} reads a specific key from a specific secret.

Secret-manager secrets are JSON documents, so the #<json-key> (and the bundle key) selects a field from the JSON. An unknown scheme is a hard error that lists the schemes Argus knows, so a typo never silently falls through to a literal.

AWS Secrets Manager

On EKS, Argus uses the pod’s IAM identity (IRSA / Pod Identity) via the standard AWS credential chain: no keys in the environment. If ARGUS_AWS_ROLE_ARN is set, Argus assumes that role (via STS) on top of the ambient identity, which covers cross-account setups. Region comes from AWS_REGION/AWS_DEFAULT_REGION. The AWS client is built lazily, so projects that use no AWS references never initialise it.

config.yml
version: 3
registries:
  internal-artifactory:
    url: https://artifactory.example.internal/artifactory/all-repos
    username: ${{secret:artifactory-username}}
    password: ${{secret:artifactory-password}}
    replaces-base: true
environment
# The role to assume (optional; omit to use the pod's IRSA identity directly)
ARGUS_AWS_ROLE_ARN=arn:aws:iam::123456789012:role/argus-secrets-reader
# The one JSON secret that holds Argus' secrets, backing ${{secret:KEY}}
ARGUS_AWS_SECRET_ARN=arn:aws:secretsmanager:eu-west-1:123456789012:secret:argus/secrets
# Standard AWS settings are honoured
AWS_REGION=eu-west-1

# The GitLab token can itself come from the bundle:
GITLAB_PRIVATE_TOKEN=${{secret:gitlab-token}}

AWS setup walkthrough

A complete EKS setup is three steps: store the secret, grant read access, and let the Argus pod assume an identity that holds it. The example uses one JSON bundle secret and IRSA; adapt the names to your account.

1. Create the secret

Store Argus’ secrets as a single JSON document in AWS Secrets Manager:

create the bundle secret
aws secretsmanager create-secret \
  --name argus/secrets \
  --description "Secrets read by Argus" \
  --secret-string '{
    "gitlab-token": "glpat-xxxxxxxxxxxxxxxxxxxx",
    "artifactory-username": "svc-argus",
    "artifactory-password": "ory-xxxxxxxx"
  }'

# Note the returned ARN and set it as ARGUS_AWS_SECRET_ARN.
# Rotate later with:  aws secretsmanager put-secret-value --secret-id argus/secrets --secret-string '{...}'

2. Grant read access

Create a least-privilege IAM policy that allows reading only Argus’ secrets. Scope the resource to your secret’s ARN prefix:

argus-secrets-read policy (least privilege)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ArgusReadSecrets",
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:eu-west-1:123456789012:secret:argus/*"
    }
  ]
}

3. Wire the pod identity

Give the Argus job’s pod an identity that carries the policy, using IAM Roles for Service Accounts (IRSA) or EKS Pod Identity. No access keys ever enter the environment.

EKS IRSA
# IRSA: bind a Kubernetes service account to the IAM role, then run Argus under it.
eksctl create iamserviceaccount \
  --cluster my-cluster --namespace ci --name argus \
  --attach-policy-arn arn:aws:iam::123456789012:policy/argus-secrets-read \
  --approve

# The service account is annotated with the role; the SDK picks it up automatically:
#   eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/argus-secrets-reader
# Run the Argus job's pod with  serviceAccountName: argus  (no keys in the environment).

The secret bundle

Rather than naming a secret in every reference, point Argus at one JSON secret that holds all of its secrets and reference the keys by name. Set ARGUS_AWS_SECRET_ARN to that secret’s ARN, store a JSON object like {"gitlab-token": "…", "artifactory-password": "…"}, and reference each value as $${{secret:<key>}}. The bundle is fetched once per run. This is the recommended setup: a single role and a single secret ARN, then short references everywhere.

The GitLab token

GITLAB_PRIVATE_TOKEN is resolved through the same mechanism, so it can be a reference: GITLAB_PRIVATE_TOKEN=$${{secret:gitlab-token}} pulls it from the bundle, or $${{aws-secretsmanager:argus/gitlab#token}} from a specific secret. A plain token value still works unchanged, and the CI_JOB_TOKEN upload fallback is preserved.

Providers

Secret resolution is built on a small provider interface, so support for more clouds can be added without changing the reference syntax or your configuration.

ProviderSchemeStatus
Environment$${{ENV_VAR}}Built in
AWS Secrets Manageraws-secretsmanagerSupported
GCP Secret Managergcp-secretmanagerPlanned
Azure Key Vaultazure-keyvaultPlanned
HashiCorp VaultvaultPlanned

The design rationale and the extension contract are recorded in ADR-021. When a new provider lands, the $${{secret:<key>}} references in your config stay exactly the same.