Skip to content

Bind Radius.Security/secrets to postgreSqlDatabases and mySqlDatabases, retained at rest - #197

Closed
willdavsmith wants to merge 5 commits into
mainfrom
willdavsmith-retain-encrypted-secrets
Closed

Bind Radius.Security/secrets to postgreSqlDatabases and mySqlDatabases, retained at rest#197
willdavsmith wants to merge 5 commits into
mainfrom
willdavsmith-retain-encrypted-secrets

Conversation

@willdavsmith

Copy link
Copy Markdown
Contributor

Description

Two related changes that let developers hand secrets to direct-module recipes, consolidated from the previously stacked draft #193:

1. secretName → a secrets array on postgreSqlDatabases and mySqlDatabases

Replaces the single secretName string on Radius.Data/postgreSqlDatabases and Radius.Data/mySqlDatabases with a secrets array annotated x-radius-secret-binding: true. Each entry is the resource ID of a Radius.Security/secrets resource (for example dbSecret.id):

resource postgresql 'Radius.Data/postgreSqlDatabases@2025-08-01-preview' = {
  name: 'postgresql'
  properties: {
    environment: environment
    application: myApplication.id
    size: 'S'
    secrets: [
      dbCredentials.id
    ]
  }
}

Radius recognizes a property carrying this annotation as a list of secret bindings. For every listed secret it loads all of the secret's keys and exposes them to direct-module recipes as {{context.resource.secrets.<secretName>.<key>}}. Platform recipes therefore consume real credentials without the developer ever placing them in the app definition. required is updated from [environment, secretName] to [environment, secrets] on both types.

Why an array of resource IDs instead of a single name string:

  • Natural, scalable shape. A database may need more than one secret (credentials, TLS material, …).
  • Consistent with connections. Developers already reference other resources by .id.
  • Namespaced, collision-free. References are qualified by secret name (...secrets.<secretName>.<key>), so multiple bound secrets never clash.

2. Mark Radius.Security/secrets values x-radius-retain

Adds x-radius-retain: true to the secret value field (already x-radius-sensitive). This keeps the canonical contrib definition in sync with the built-in type: the encrypted value is retained at rest (still redacted on GET/LIST) so recipes can decrypt it from Radius's own store rather than reading a Kubernetes Secret — required for multi-cluster-safe secret resolution.

Important

Depends on the engine support in radius-project/radius (the x-radius-secret-binding resolution path and x-radius-retain persistence). The annotations are inert on engine versions without it, so this stays a draft until the radius change lands. Design context: radius-project/radius#12244.

Related GitHub Issue: N/A (tracked in radius-project/radius#12244)

Testing

Exercised end-to-end by the manual resource-type verification workflow in radius-project/resource-types-verification — the Azure (Bicep AVM) direct-module flow registers each manifest, deploys a postgreSqlDatabases resource whose secrets array points at a Radius.Security/secrets resource, and proves the injected secret value (retained encrypted at rest, decrypted from Radius's store) reaches the real Azure database, then validates delete.

Contributor Checklist

  • File names follow naming conventions and folder structure
  • All properties in the Resource Type definition have clear descriptions
  • Required properties are listed in required: [] for every object property
  • Properties about the deployed resource are defined as read-only (readOnly: true)
  • Resource types and recipes were tested

Mark the secretName property with x-radius-secret-reference so Radius resolves the referenced Radius.Security/secrets resource and injects its values into direct-module recipe parameters (context.resource.secrets.<key>), rather than passing the literal secret name to the recipe. Mirrors the existing x-radius-sensitive precedent on Radius.Security/secrets.

Requires the engine support added in radius-project/radius#12254; the marker is inert on engine versions without it, so this stays draft until that lands.

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Replace the secretName string property with a secrets array marked
x-radius-secret-binding. Each entry is a Radius.Security/secrets resource
ID; Radius loads every key of each listed secret and exposes it to the
recipe as context.resource.secrets.<secretName>.<key>, where <secretName>
is the secret resource's name.

This supersedes the earlier x-radius-secret-reference marker on secretName
and lets direct-module recipes inject developer-authored secret values
(admin username/password) into the provisioned database.

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Mirror the postgreSqlDatabases change: replace the single secretName string
property with a secrets array carrying x-radius-secret-binding, so MySQL
credentials are injected into the direct-module recipe via
{{context.resource.secrets.<secretName>.<key>}}. Lowercase the example secret
data keys (username/password) to match.

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Keep the secret value encrypted at rest so the dynamic-rp secrets loader can
decrypt it from the Radius control-plane store. Without this, the value is
redacted to nil after recipe execution and the loader must read the secret
from the application's target-cluster Kubernetes Secret, which breaks
multi-cluster deployments.

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Replace the required `secrets` array with required `username` and
`password` properties. `password` is marked x-radius-sensitive, so
Radius encrypts it at rest, redacts it on reads, and exposes it
decrypted only to the recipe via
{{context.resource.properties.username}} / {{...password}}.

`secrets` is retained as an optional, legacy alternative. The
description and example are updated to show the direct-property model.

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant