Modernize demo sample to Radius.* resource types and add Redis/PostgreSQL variants with secret binding - #2646
Open
willdavsmith wants to merge 3 commits into
Open
Modernize demo sample to Radius.* resource types and add Redis/PostgreSQL variants with secret binding#2646willdavsmith wants to merge 3 commits into
willdavsmith wants to merge 3 commits into
Conversation
…eSQL variants with secret binding Mirrors #2645 and additionally applies the Radius secret-binding pattern: secrets are bound into the demo container by reference with env valueFrom.secretKeyRef instead of plain env values.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
PR #2645 dropped the 'image' parameter from samples/demo/app.bicep, but the demo entry in .github/workflows/test.yaml deploys with '-p image=sampleregistry:5000/samples/demo' so the test exercises the freshly-built image rather than the published ghcr.io one. ARM rejects -p for an undeclared parameter, so the job would fail. Restore the parameter (default-valued, so plain 'rad deploy' is unchanged) in all three files instead of editing the workflow.
The demo app reads its PostgreSQL credentials from CONNECTION_POSTGRESQL_* (see samples/demo/src/db/repository.ts), so the secretKeyRef binding must use CONNECTION_POSTGRESQL_PASSWORD. Bound as POSTGRES_PASSWORD the app fell through to an empty password and failed authentication. The connection supplies host, port, username, and database but never emits CONNECTION_POSTGRESQL_PASSWORD, because the property is x-radius-sensitive and redacts to null, so this binding fills that gap rather than colliding with it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Updates the
demosample to the currentRadius.*resource types and adds two datastore variants that show how to connect the demo container to a managed cache and database. This mirrors #2645, and additionally applies the Radius secret-binding pattern so credentials are never rendered as plain containerenvvalues.Changes
samples/demo/app.bicepApplications.*(2023-10-01-preview) toRadius.*(2025-08-01-preview) resource types.Radius.Core/applicationsresource plus aRadius.Compute/containersresource using the new nestedcontainersmap schema.environmentNamefrom the Environment ID and suffix resource names (demo-${environmentName}) so multiple environments (dev/test/prod) can coexist in the same resource group without name collisions.samples/demo/app-redis.bicep(new)Radius.Data/redisCachescache via aconnections.redislink.REDIS_URLis bound from the cache's managed secret withsecretKeyRef.samples/demo/app-postgresql.bicep(new)Radius.Data/postgreSqlDatabasesdatabase via aconnections.postgresqllink.@secure()parameter (never stored in the file), stored in aRadius.Security/secretsresource and bound into the container withsecretKeyRef.The
imageparameterAll three files declare a default-valued
imageparameter:This restores the parameter that existed in
app.bicepbefore #2645 removed it. It is required by CI: thedemomatrix entry in.github/workflows/test.yamlruns on pull requests and deploys with-p image=sampleregistry:5000/samples/demo, and ARM rejects-pfor a parameter the template does not declare. That override exists on purpose — the workflow builds the demo image fromsamples/demo/and pushes it to the localsampleregistry:5000registry so the test exercises the freshly-built image; dropping the override would silently test the publishedghcr.ioimage instead and defeat the job. Because the parameter is default-valued,rad deploy samples/demo/app.bicepwith no arguments behaves exactly as documented. No workflow changes are needed —--applicationindeployArgsis arad deployCLI scope flag, not a template parameter.Secret handling
Both variants deliberately avoid passing credentials as plain container
envvalues:enventry of the form{ value: <string> }is rendered literally into the Kubernetes pod spec and stored unencrypted on the containers resource — the containers resource type schema has nox-radius-sensitivemarker onenv.value. A secret passed this way is visible to anyone withget pod/describe deploymentin the namespace, and viarad resource show.Radius.Security/secretsmarksdata.*.valueasx-radius-sensitive: true, so Radius encrypts it at rest and redacts it on reads. Binding viaenv.valueFrom.secretKeyRefkeeps the value out of the pod spec and out of container state.urlsecret is already materialized into a managedRadius.Security/secretsresource reachable atredis.properties.secrets.name, so it is bound directly withsecretKeyRef.@secure()param) and the type exposes nosecretsproperty, so the app creates its ownRadius.Security/secretsresource to hand the password to the container. It is bound asCONNECTION_POSTGRESQL_PASSWORD, matching theCONNECTION_<CONNECTION-NAME>_<PROPERTY-NAME>scheme the demo app reads (seesamples/demo/src/db/repository.ts). The connection itself suppliesCONNECTION_POSTGRESQL_HOST,_PORT,_USERNAME, and_DATABASE, but never_PASSWORD— that property isx-radius-sensitive, so it redacts to null on reads and is skipped by the containers recipe. This binding fills the one gap the connection leaves rather than colliding with it.env+secretKeyRefrather than a secondconnectionsentry pointing at the secrets resource: a connection to aRadius.Security/secretssource producesenvFrom.secretRef, and Kubernetes does not expandenvFrom-sourced variables in$(VAR)references inside containerargs.Deploy
rad deploy samples/demo/app.bicep rad deploy samples/demo/app-redis.bicep rad deploy samples/demo/app-postgresql.bicep -p password=$(openssl rand -hex 16)Validation
bicep buildwas run locally againstbr:biceptypes.azurecr.io/radius:latest:app.bicep— builds cleanapp-postgresql.bicep— builds cleanapp-redis.bicep— fails locally withBCP053: The type "redisCachesProperties" does not contain property "secrets".The
app-redis.bicepfailure is a stale published type index, not a defect in the sample. Theredis.properties.secrets.name+ keyurlexpression matches the committedredisCachestype definition inradius-project/resource-types-contrib(Data/redisCaches/redisCaches.yamldefinesproperties.secretswith the reservednamesub-property and documents this exactsecretKeyRefbinding), and it is identical to the expression used by that repo's own test app atData/redisCaches/test/app.bicep. The type simply has not been republished tobiceptypes.azurecr.io/radius:latestyet; the file will build once the index is refreshed.