Skip to main content

Application Secrets Management

The app submission workflow lets ISVs provision the credentials their application needs before the release is built and deployed to the sandbox cluster. The submission UI surfaces a vault and secret management view, plus a Generate YAML action that produces the Kubernetes custom resources reconciled by the Secret Management Operator.

There are two kinds of vaults you can create from the submission UI:

  • Registry vault — holds container registry credentials. Restricted to exactly two secrets: username and password.
  • Application vault — holds arbitrary application secrets (API keys, DB passwords, tokens, etc.). No limit on the number of secrets.
Vault names are globally unique

Vault names must be unique across all tenants in the secret store, not just within your account. If the name you submit is already taken, Armada's secrets runtime returns the existing vault and the request is rejected with a vault with the name '<name>' already exists. Pick a name with an account-specific prefix (e.g., acme-registry, acme-app-secrets) to avoid collisions.


Security Posture

Secret material handled by this workflow is never stored or transmitted in plaintext on the platform:

  • At rest — secret values are kept in Armada's managed secret stores, never on application Kubernetes resources, in intake databases, or in build artifacts.
  • In transit — values are passed over TLS between the submission UI, the secrets runtime, and the operator that reconciles them onto the sandbox cluster.
  • In logs — secret values are redacted from service logs and audit trails. Only metadata (vault names, secret names, credential refs) is logged.
  • On the cluster — at deploy time, the Secret Management Operator delivers the values as standard Kubernetes secrets in the application's namespace.

You do not need to encrypt values yourself before submitting them.


Registry Vault

A registry vault stores the credentials used to pull images from a single container registry. It is keyed by the registry URL: only one registry vault per (account, registry URL) pair is allowed. Attempting to create a second one for the same URL is rejected — rotate credentials in the existing vault instead.

Spec

FieldRequiredDescription
nameYesVault name. Must be globally unique across the secret store (see callout above).
vaultTypeYesregistry
registryUrlYesUpstream host of the container registry (e.g., acme.azurecr.io).
registryTypeYesOne of ACR, ECR, GCR, DOCKER_HUB, OTHER.

Allowed secrets

A registry vault can hold only these two secrets:

SecretcredentialRefPurpose
UsernameusernameRegistry username (or service principal client ID for ACR).
PasswordpasswordRegistry password (or client secret for ACR).

Constraints enforced at create time:

  • credentialRef is required and must be username or password.
  • Each ref can be set exactly once. Re-creating a username after one is already mapped is rejected.
  • A third secret (any other credentialRef or any other name) is rejected.

To rotate a credential, update the existing secret's value — do not create a new one. Updates are scoped to the registered username/password secret names; updating any other name is rejected.

Create registry secret modal


Application Vault

An application vault is scoped to the ISV account and accepts any number of secrets with arbitrary names.

Spec

FieldRequiredDescription
nameYesVault name. Must be globally unique across the secret store (see callout above).
vaultTypeYesapplication

registryUrl and registryType do not apply.

Secrets

Each secret is a name/value pair. The name becomes both the sourceKey and the targetKey in the generated ManagedSecretConfig (see Generate YAML), so it must satisfy the operator's sourceKey rule: alphanumeric and hyphens only (no underscores), 1–127 characters. Pick hyphenated names that map to the secrets your application expects, e.g., database-url, api-key, stripe-webhook-secret.

Underscores are not allowed in secret names

The operator validates sourceKey as alphanumeric-and-hyphens (see SecretMapping). A secret named DATABASE_URL would generate a ManagedSecretConfig the operator rejects. If your application reads an environment variable like DATABASE_URL, name the vault secret database-url and map it to the underscored variable in your Helm chart — the operator's targetKey permits underscores even though sourceKey does not.

There is no per-vault secret count limit imposed by app submission.

Create application secret modal


Generate YAML

The Generate YAML action in the submission UI produces the CRDs that the Secret Management Operator consumes on the sandbox cluster. It exposes two dropdowns:

Generate YAML modal

DropdownRequiredPopulated from
Registry vaultYesRegistry-type vaults in the account.
Application vaultNoApplication-type vaults in the account.

What gets generated depends on which vaults are selected:

SelectionGenerated CRDs
Registry vault onlyHarborRegistrySecret
Registry vault + application vaultManagedSecretConfig + HarborRegistrySecret

Validation performed before YAML is returned

  1. The registry vault must exist, be of type registry, and have both usernameRef and passwordRef mapped.
  2. The username and password are pulled from the secret store and verified by a live credential check against the registry. If the credentials are invalid, generation fails with the validation message and no YAML is produced.
  3. If an application vault is provided, it must exist and be of type application. Each secret in the vault contributes one secretMapping entry (sourceKey == targetKey).

Example output

Generate YAML output

For a registry vault acme-registry (ACR, acme.azurecr.io) plus an application vault acme-app-secrets containing two secrets database-url and api-key:

apiVersion: security.armada.ai/v1alpha2
kind: ManagedSecretConfig
metadata:
name: {{ .Release.Name }}-managed-secrets
namespace: {{ .Release.Namespace }}
spec:
secretVaultName: acme-app-secrets
secretMapping:
- sourceKey: database-url
targetKey: database-url
- sourceKey: api-key
targetKey: api-key
targetSecretName: acme-app-secrets
---
apiVersion: security.armada.ai/v1alpha1
kind: HarborRegistrySecret
metadata:
labels:
app.kubernetes.io/name: armada-sm-operator
app.kubernetes.io/managed-by: kustomize
name: {{ .Release.Name }}-harbor-registry
namespace: {{ .Release.Namespace }}
spec:
akvSource:
vaultName: acme-registry
usernameSecretKey: acme-registry-username
passwordSecretKey: acme-registry-password
harbor:
vendorName: <accountId>
upstreamHost: acme.azurecr.io
registryType: docker-registry

Drop the YAML into your Helm chart's templates/ directory. The Helm template variables ({{ .Release.Name }}, {{ .Release.Namespace }}) are emitted intentionally so the resources are scoped to the release at install time. At deploy time the Secret Management Operator reconciles them into the namespace's imagePullSecret and the application Kubernetes secret.