Skip to content

fix(security): use secretKeyRef for S3 credentials - #678

Open
platex-rehor-bot wants to merge 4 commits into
RedHatInsights:mainfrom
platex-rehor-bot:bot/RHCLOUD-49507
Open

fix(security): use secretKeyRef for S3 credentials#678
platex-rehor-bot wants to merge 4 commits into
RedHatInsights:mainfrom
platex-rehor-bot:bot/RHCLOUD-49507

Conversation

@platex-rehor-bot

@platex-rehor-bot platex-rehor-bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Resolves RHCLOUD-49507 — AWS S3 credentials (PUSHCACHE_AWS_ACCESS_KEY_ID, PUSHCACHE_AWS_SECRET_ACCESS_KEY) were embedded as literal value: entries in generated Deployment and Job specs, making them visible to any namespace viewer.

Changes

  • controllers/reconcile.go: Added ensurePushCacheCredentialsSecret() helper that creates/updates an opaque pushcache-s3-credentials Secret, and pushCacheCredentialEnvVars() returning env vars with valueFrom.secretKeyRef. Modified populatePushCacheContainer() to use env-var expansion ($PUSHCACHE_AWS_ACCESS_KEY_ID) in the valpop command instead of literal credentials.
  • controllers/reconcile_reverse_proxy.go: Changed createReverseProxyContainer() to source S3 credentials from the managed Secret via secretKeyRef instead of literal values. Updated compareEnvVars() to handle ValueFrom comparison. Switched from ExtractBucketConfigFromEnv() to getObjectStoreConfig() for Clowder secret fallback support.
  • deploy.yml: Operator's own Deployment template now references a ${PUSHCACHE_AWS_SECRET_NAME} Secret (default: pushcache-aws-credentials) via secretKeyRef instead of literal template parameter values.
  • Tests: Updated unit tests and e2e assertions (reverse-proxy, pushcache) to expect secretKeyRef env vars.

Deployment note

The operator's own Deployment now expects a pre-existing Secret named by the PUSHCACHE_AWS_SECRET_NAME parameter (default pushcache-aws-credentials) in the operator namespace, containing keys aws-access-key-id and aws-secret-access-key. This Secret must be provisioned by the deployment infrastructure (e.g. app-interface / Vault) before the operator pod starts.

🤖 Generated with Claude Code

platex-rehor-bot and others added 2 commits July 30, 2026 12:02
RHCLOUD-49507
Replace literal env values with valueFrom.secretKeyRef for
PUSHCACHE_AWS_ACCESS_KEY_ID and PUSHCACHE_AWS_SECRET_ACCESS_KEY
in generated Deployments and Jobs. The operator now creates a
managed pushcache-s3-credentials Secret and all containers
reference it instead of embedding credentials as plain text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Hyperkid123

Copy link
Copy Markdown
Contributor

@platex-rehor-bot can you fix up the linter?

RHCLOUD-49507
The constant is a Kubernetes Secret resource name, not a hardcoded credential.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@platex-rehor-bot

Copy link
Copy Markdown
Contributor Author

Fixed — suppressed the gosec G101 false positive on the PushCacheCredentialsSecretName constant (it's a Secret resource name, not a hardcoded credential). Pushed in 09bed85.

@tahmidefaz tahmidefaz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @platex-rehor-bot — solid security improvement! A few questions about the approach:

  1. Missing owner reference on pushcache-s3-credentials Secret: I noticed ensurePushCacheCredentialsSecret() doesn't call SetOwnerReferences(), unlike every other resource the reconciler creates (Deployments, ConfigMaps, Jobs, etc.). Was this intentional — e.g. because the Secret is shared across multiple Frontends and shouldn't be owned by a single one? Or was it an oversight? Curious about your thinking here.

  2. deploy.yml secretKeyRef without optional: true: The operator's Deployment now requires a pre-existing pushcache-aws-credentials Secret to start. In Clowder environments, credentials come from env-<ns>-minio instead. Was there a reason not to set optional: true on the secretKeyRef, or is the expectation that Clowder environments don't use deploy.yml at all?

  3. compareEnvVars only handles SecretKeyRef: The updated comparison logic checks ValueFrom.SecretKeyRef but doesn't handle ConfigMapKeyRef, FieldRef, or ResourceFieldRef. Was this a deliberate scope decision (only comparing what's currently used), or would you want to handle those for completeness?

Just want to understand the reasoning. Thanks!

…pareEnvVars

RHCLOUD-49507

- Move secretKeyRef changes from deploy.yml to kustomize source
  (config/deployment-template/manager.yaml) and template.yml so
  `make build-template` stays in sync. Fixes Konflux CI failure.
- Replace PUSHCACHE_AWS_ACCESS_KEY_ID/SECRET_ACCESS_KEY template
  params with PUSHCACHE_AWS_SECRET_NAME (Secret resource name).
- Extend compareEnvVars to handle ConfigMapKeyRef, FieldRef, and
  ResourceFieldRef for completeness alongside existing SecretKeyRef.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@platex-rehor-bot

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review, @tahmidefaz! Great questions — here's the reasoning for each:

1. Missing owner reference on pushcache-s3-credentials Secret

Intentional. The Secret is shared across all Frontends in the namespace — every Frontend reconciler calls ensurePushCacheCredentialsSecret() with the same credentials. If we set an owner reference to a single Frontend CR, Kubernetes garbage collection would delete the Secret when that Frontend is removed, breaking all other Frontends that depend on it.

FrontendEnvironment would be the natural owner, but it's cluster-scoped and cannot own namespace-scoped resources (K8s constraint). So the Secret is intentionally unowned — it persists independently and is updated in-place on each reconcile.

2. deploy.yml secretKeyRef without optional: true

deploy.yml (the OpenShift template) is only used in non-Clowder environments (stage/prod) where the Secret is expected to be pre-provisioned by the platform team. In Clowder environments, the deployment is managed via ClowdApp, not this template — Clowder provides credentials through env-<ns>-minio.

Leaving optional: true off is a deliberate fail-fast decision: if the Secret isn't provisioned, the operator Pod won't start, which is preferable to starting without credentials and failing silently at runtime when it tries to push to S3.

3. compareEnvVars scope — now extended

Originally a deliberate scope decision (only comparing what's currently used). But your point about completeness is valid — if the function is called compareEnvVars it should handle all ValueFrom types correctly.

Pushed b80947f which extends compareEnvVars to also handle ConfigMapKeyRef, FieldRef, and ResourceFieldRef. Same commit also fixes the Konflux CI failure — the deploy.yml was previously hand-edited rather than regenerated from the kustomize source (config/deployment-template/manager.yaml + template.yml). Now make build-template stays in sync.

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.

4 participants