Repository navigation
Object Storage Configuration Contract
type: deployment-guide description: Configuration contract for object storage endpoints, credentials, buckets, and signing settings across PR, test, and prod deployments. tags: [deployment, openshift, object-storage, minio, secrets] timestamp: 2026-10-23T00:00:00Z
This page defines where the object storage configuration comes from, how it reaches the backend, and how operators rotate, verify, and diagnose it.
Spring Boot binds the environment variables to properties under
ca.bc.gov.nrs.object-storage.
| Property | Environment variable |
|---|---|
endpoint |
OBJECT_STORAGE_ENDPOINT |
presigner-endpoint |
OBJECT_STORAGE_PRESIGNER_ENDPOINT |
access-key |
OBJECT_STORAGE_ACCESS_KEY |
secret-key |
OBJECT_STORAGE_SECRET_KEY |
bucket |
OBJECT_STORAGE_BUCKET |
region |
OBJECT_STORAGE_REGION |
force-path-style |
OBJECT_STORAGE_FORCE_PATH_STYLE |
-
endpointis the S3 endpoint URL. -
presigner-endpointis optional. It is the client-facing host used to sign presigned URLs. Empty for PR/dev because the MinIO service has no public Route, so URLs are signed against the in-cluster endpoint. Set it only when the store needs a different signing host than the API host. -
access-keyis the access key id or username. -
secret-keyis the secret access key. -
bucketis the bucket name. -
regionis the SigV4 region. Defaultca-central-1. -
force-path-styleistruefor path-style addressing (https://host/bucket/key);falsefor virtual-host addressing.
-
PR / dev uses OpenShift namespace
cffaf3-dev. Object storage is the shared MinIO service incffaf3-tools, athttp://nr-waste-plus-tools-minio.cffaf3-tools.svc.cluster.local:9000. The service is in-cluster only and has no Route. The path uses a per-PR bucket on the shared MinIO instance, named<base>-pr-<PR number>(base bucketnr-waste). The per-PR bucket is created and cleaned up by the PR pipeline. -
test uses OpenShift namespace
cffaf3-testand the BC Gov object store athttps://nrs.objectstore.gov.bc.ca:443. -
prod uses OpenShift namespace
cffaf3-prodand the same BC Gov object store endpoint.
One bucket is used per environment.
- Values are supplied ONLY through GitHub Actions secrets. The endpoint is never hardcoded in a workflow.
- The resolution order for every value is workflow input, then GitHub environment secret, then GitHub repository secret, then the built-in default in the workflow.
- Repository-level secrets carry the PR/dev defaults: the MinIO endpoint, the
base bucket
nr-waste, regionca-central-1, andforce-path-style=true. - The
testandprodGitHub environments override the repository values for the BC Gov object store endpoint, access key, secret key, and bucket.
.github/workflows/pr-open.yml resolves the endpoint and base bucket in its
vars job. Reusable-workflow with: inputs cannot read the secrets context,
so the values are resolved there and passed to
.github/workflows/.deploy.yml as the object-storage-endpoint and
object-storage-bucket inputs. The per-PR bucket is derived as
<base>-pr-<PR number>. The workflow also sets force-path-style to true.
It does not set a presigner endpoint because the shared MinIO service has no
public Route.
.github/workflows/merge.yml declares environment: test or
environment: prod, so environment secrets take precedence over repository
secrets.
The init job in .github/workflows/.deploy.yml passes the resolved values as
parameters to common/openshift.init.yml. The template writes them into the
OpenShift Secret nr-waste-plus-${ZONE} under these stringData keys:
object-storage-endpointobject-storage-presigner-endpointobject-storage-access-keyobject-storage-secret-keyobject-storage-bucketobject-storage-regionobject-storage-force-path-style
The template is applied with overwrite: true. GitHub is the source of truth,
and the OpenShift Secret is rewritten on every deploy.
The backend reads these keys with secretKeyRef from that Secret in
backend/openshift.deploy.yml. Each key is declared optional: true, so an
unset key leaves the default in backend/src/main/resources/application.yml in
place. The property binding and client setup are in:
backend/src/main/java/ca/bc/gov/nrs/hrs/configuration/ObjectStorageProperties.javabackend/src/main/java/ca/bc/gov/nrs/hrs/configuration/ObjectStorageConfiguration.java
When the resolved endpoint is the tools MinIO, the deploy uses the repository
secrets MINIO_ROOT_USER and MINIO_ROOT_PASSWORD as the credentials instead
of the S3 access and secret keys. Every other endpoint uses
OBJECT_STORAGE_ACCESS_KEY and OBJECT_STORAGE_SECRET_KEY.
The init job in .github/workflows/.deploy.yml runs the Require object
storage credentials step before anything is applied.
- For the tools MinIO endpoint,
MINIO_ROOT_USER,MINIO_ROOT_PASSWORD, and a non-empty bucket are required. - For any other endpoint, a non-empty
OBJECT_STORAGE_ENDPOINTthat is anhttp(s)URL, plusOBJECT_STORAGE_ACCESS_KEY,OBJECT_STORAGE_SECRET_KEY, and a non-empty bucket are required. - If a value is missing, the job fails with a message naming the missing secret. A deployment never starts against an unconfigured or half-configured store.
-
Update the secret in GitHub: use the repository secret, or the
testorprodenvironment secret. -
Re-run the Merge deployment for that environment. The merge workflow supports
workflow_dispatch. -
The
initjob rewrites the OpenShift Secretnr-waste-plus-${ZONE}from the new values. -
The application pods roll automatically. Each application template passes a
RANDOM_EXPRESSIONparameter, so a re-applied deployment changes the pod template and replaces the pods. -
Verify the update:
gh secret list --env prod oc get secret nr-waste-plus-prod -n cffaf3-prod -o yaml
gh secret list shows names and update timestamps only. The OpenShift command
shows the values that reached the cluster.
Check the GitHub side:
gh secret list --repo bcgov/nr-waste-plus
gh secret list --env test --repo bcgov/nr-waste-plus
gh secret list --env prod --repo bcgov/nr-waste-plusCheck the OpenShift side:
oc get secret nr-waste-plus-prod -n cffaf3-prod -o yaml
oc set env deploy/nr-waste-plus-backend -n cffaf3-prod --list | grep OBJECT_STORAGEThe first OpenShift command shows the Secret that reached the cluster. The second lists the values that the running pods actually received.
The configured region does not match the region the store expects in its SigV4
signature. Check OBJECT_STORAGE_REGION.
Check force-path-style; the store may only accept path-style addressing. A
key scoped to another bucket cannot access this one. Also check the bucket
policy.
The client-facing host differs from the signing host. Set presigner-endpoint.
The PR/dev MinIO has no public Route, so its presigned URLs are only reachable
from inside the cluster.
DefaultCredentialsProvider or a no-credentials-found error means the
OpenShift Secret carries empty values. This happens when a deployment ran
before the GitHub secrets existed. Re-run the deployment after setting the
secrets.
The message names the missing secret. Set the value at the environment level for test/prod, or at the repository level for PR/dev.
.github/workflows/pr-open.yml.github/workflows/merge.yml.github/workflows/.deploy.yml.github/workflows/.tools-deploy.yml.github/workflows/.tools-cleanup.ymlcommon/openshift.init.ymlbackend/openshift.deploy.ymlbackend/src/main/resources/application.ymlbackend/src/main/java/ca/bc/gov/nrs/hrs/configuration/ObjectStorageProperties.javabackend/src/main/java/ca/bc/gov/nrs/hrs/configuration/ObjectStorageConfiguration.java
This wiki documents NR Waste Plus for users and developers. Verify security and deployment guidance against the current application configuration before applying it elsewhere.
- Report an issue or ask a question in the GitHub repository.
- Follow the Contributing Guidelines to propose an update.
- Read the Code of Conduct.
Collection indexes support human browsing and machine retrieval. Keep both current when adding or moving wiki pages.
NR Waste Plus Wiki | GitHub Repository