Skip to content

Tokenize Credential Request GCP#856

Open
desmax74 wants to merge 4 commits into
trustification:release/2.y.zfrom
desmax74:occ-gcp
Open

Tokenize Credential Request GCP#856
desmax74 wants to merge 4 commits into
trustification:release/2.y.zfrom
desmax74:occ-gcp

Conversation

@desmax74

@desmax74 desmax74 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

https://redhat.atlassian.net/browse/TC-4308

Summary by Sourcery

Integrate OpenShift Cloud Credentials Operator support for managing cloud storage credentials across AWS and GCP, including manual STS/WIF modes, and advertise token-based auth support in the operator bundle.

New Features:

  • Add Helm values and templates to create a cloud-provider-specific CredentialsRequest and consume CCO-managed credentials for S3-compatible storage on AWS and GCP, including manual STS/WIF modes.
  • Introduce CCO helper templates to configure pods with projected service account tokens, cloud credential volumes, and provider-specific SDK environment variables in manual mode.
  • Expose ccoMode and cloudCredentials configuration in the chart schema and default values to control CCO behavior and cloud permissions.

Enhancements:

  • Relax S3 storage configuration to make accessKey and secretKey optional when using CCO-managed credentials.
  • Advertise AWS and GCP token authentication support via updated operator bundle and CSV feature labels.
  • Extend RBAC with a ClusterRole and ClusterRoleBinding granting the operator permission to manage CredentialsRequest resources.

Documentation:

  • Add documentation describing how the operator integrates with Cloud Credentials Operator and how to configure CCO-backed deployments.

Tests:

  • Add extensive Helm rendering e2e tests covering AWS and GCP, all CCO modes, and storage env var behavior with and without CCO.
  • Add integration tests to validate presence and structure of CCO-related fields in the Helm values schema and RBAC resources for CredentialsRequest management.
  • Add CR fixtures for various AWS and GCP CCO configurations to support testing.

desmax74 and others added 3 commits June 22, 2026 14:45
Signed-off-by: desmax74 <mdessi@redhat.com>
…/manual)

Enable Cloud Credential Operator support for AWS with all standard OpenShift
CCO modes. Manual mode (STS) auto-configures projected SA token volumes and
AWS SDK credential chain env vars. The ccoMode field is fixed from broken {}
default to a proper string enum.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extend CCO integration to GCP: add serviceAccountEmail to schemas and
CredentialsRequest, GCP-specific GOOGLE_APPLICATION_CREDENTIALS env var
for manual mode, and enable token-auth-gcp OLM annotation.

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

sourcery-ai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds Cloud Credentials Operator (CCO) integration for AWS and GCP to the RHTPA Helm chart/operator, including schema and values support, CredentialRequest templating, runtime wiring for S3 credentials across CCO modes, RBAC to manage CredentialsRequest objects, OpenShift feature labels for token-based auth, and comprehensive e2e/integration tests plus fixtures for the new behavior.

File-Level Changes

Change Details Files
Introduce CCO-related configuration options and relax S3 credential requirements in the Helm values schema.
  • Add ccoMode, cloudProvider, and cloudCredentials (aws/gcp) objects to values.schema.yaml with enums and field descriptions
  • Document that S3 accessKey and secretKey become optional and auto-populated when cloudProvider is set
  • Add corresponding JSON schema (values.schema.json) and defaults/examples in values.yaml for the new CCO-related fields
helm-charts/redhat-trusted-profile-analyzer/values.schema.yaml
helm-charts/redhat-trusted-profile-analyzer/values.schema.json
helm-charts/redhat-trusted-profile-analyzer/values.yaml
Wire S3 environment variables to use CCO-managed secrets when enabled and not in manual mode.
  • Update storage helper template so TRUSTD_S3_ACCESS_KEY and TRUSTD_S3_SECRET_KEY are sourced from a CCO-created secret when cloudProvider is set and no explicit accessKey/secretKey are provided
  • Guard S3 ACCESS_KEY/SECRET_KEY env var emission so they are skipped entirely in CCO manual mode
helm-charts/redhat-trusted-profile-analyzer/templates/helpers/_storage.tpl
Add dedicated Helm helpers and deployment wiring for CCO manual (STS/WIF) mode.
  • Introduce helpers to detect manual mode, compute the CCO secret name, and emit CCO-specific volumes, volumeMounts, and env vars for AWS (STS) and GCP (WIF)
  • Mount CCO credentials and projected SA token into importer and server Deployments and inject the CCO env vars via the new helpers
helm-charts/redhat-trusted-profile-analyzer/templates/helpers/_cco.tpl
helm-charts/redhat-trusted-profile-analyzer/templates/services/importer/030-Deployment.yaml
helm-charts/redhat-trusted-profile-analyzer/templates/services/server/030-Deployment.yaml
Template a CCO CredentialsRequest resource for AWS and GCP with mode-dependent fields.
  • Add a credentialrequest.yaml template that conditionally renders a CredentialsRequest when cloudProvider is set
  • Populate providerSpec differently for AWS (statementEntries, optional stsIAMRoleARN in manual mode) vs GCP (predefinedRoles, optional serviceAccountEmail in manual mode) and set cloudTokenPath only in manual mode
helm-charts/redhat-trusted-profile-analyzer/templates/credentialrequest.yaml
Grant the operator permissions to manage CredentialsRequest resources via new RBAC, and ensure they are included in kustomization.
  • Define a ClusterRole that allows full CRUD/watch on cloudcredential.openshift.io credentialsrequests
  • Bind the operator controller-manager ServiceAccount to this ClusterRole via a ClusterRoleBinding
  • Reference the new RBAC manifests from config/rbac/kustomization.yaml
  • Add integration tests that assert presence and correctness of the CCO ClusterRole, ClusterRoleBinding, and kustomization entries
config/rbac/clusterrole.yaml
config/rbac/clusterrolebinding_cco.yaml
config/rbac/kustomization.yaml
test/integration/cco_rbac_test.go
Advertise support for token-based AWS and GCP auth via operator bundle metadata.
  • Flip token-auth-aws and token-auth-gcp feature labels from false to true in the bundle Dockerfile, CSVs, and bundle annotations so OpenShift recognizes token-based auth support
bundle.Dockerfile
bundle/manifests/rhtpa-operator.clusterserviceversion.yaml
bundle/metadata/annotations.yaml
config/manifests/bases/rhtpa-operator.clusterserviceversion.yaml
Extend e2e and integration tests to cover CCO configuration, credential wiring, and Helm rendering across providers/modes.
  • Add an integration test that validates values.schema.json includes the new CCO fields with correct types and enums
  • Introduce a large e2e suite (cco_helm_rendering_test.go) that renders the Helm chart with various cloudProvider/ccoMode combinations (AWS/GCP, mint/passthrough/default/manual) and asserts on rendered CredentialsRequest, env vars, volumes, and absence/presence of S3 keys or provider-specific sections
  • Add constants for storage-related keys and reuse helpers for test values in e2e helpers
  • Provide CR fixtures for AWS and GCP CCO configurations in different modes (mint/default/passthrough/manual) for use in tests
test/integration/helm_chart_test.go
test/e2e/helpers_test.go
test/e2e/cco_helm_rendering_test.go
test/fixtures/aws_cco_cr.yaml
test/fixtures/aws_cco_manual_cr.yaml
test/fixtures/aws_cco_default_cr.yaml
test/fixtures/aws_cco_passthrough_cr.yaml
test/fixtures/gcp_cco_cr.yaml
test/fixtures/gcp_cco_manual_cr.yaml
Add developer/operator documentation and sample CCO CredentialRequest manifest.
  • Document how to check CCO status, how the operator interacts with CCO, and how to integrate CCO with the Helm chart, including manual/STSlWIF considerations
  • Provide a development example CredentialsRequest manifest for AWS in devel/cco/credentialRequest.yaml
extensions/README.md
devel/cco/credentialRequest.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In _storage.tpl the CCO-backed secret keys are hard-coded to aws_access_key_id/aws_secret_access_key for all non-manual cloudProvider values; for GCP mint/passthrough this is unlikely to match the secret layout emitted by the GCP provider and should either be specialized per provider or disabled for GCP.
  • In credentialrequest.yaml manual mode does not guard against missing stsIAMRoleARN/serviceAccountEmail, which will render an invalid CredentialsRequest; consider using Helm required (or similar) to fail the render when these fields are omitted in manual mode.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `_storage.tpl` the CCO-backed secret keys are hard-coded to `aws_access_key_id`/`aws_secret_access_key` for all non-manual `cloudProvider` values; for GCP mint/passthrough this is unlikely to match the secret layout emitted by the GCP provider and should either be specialized per provider or disabled for GCP.
- In `credentialrequest.yaml` manual mode does not guard against missing `stsIAMRoleARN`/`serviceAccountEmail`, which will render an invalid `CredentialsRequest`; consider using Helm `required` (or similar) to fail the render when these fields are omitted in manual mode.

## Individual Comments

### Comment 1
<location path="test/integration/cco_rbac_test.go" line_range="111-127" />
<code_context>
+	assert.Equal(t, "cco-credentialsrequest-access", binding.RoleRef.Name, "roleRef name should match the CCO ClusterRole")
+}
+
+func TestCCOClusterRoleBindingSubjects(t *testing.T) {
+	bindingPath := filepath.Join("config", "rbac", "clusterrolebinding_cco.yaml")
+
+	data, err := os.ReadFile(bindingPath)
+	require.NoError(t, err, "CCO ClusterRoleBinding should be readable")
+
+	var binding ClusterRoleBinding
+	err = yaml.Unmarshal(data, &binding)
+	require.NoError(t, err, "CCO ClusterRoleBinding should be valid YAML")
+
+	require.NotEmpty(t, binding.Subjects, "ClusterRoleBinding should have at least one subject")
+
+	assert.Equal(t, "ServiceAccount", binding.Subjects[0].Kind,
+		"subject should be a ServiceAccount")
+	assert.Equal(t, "rhtpa-operator-controller-manager", binding.Subjects[0].Name,
+		"subject should reference the operator's service account")
+}
</code_context>
<issue_to_address>
**suggestion (testing):** Avoid relying on the first subject in the ClusterRoleBinding; search for the expected service account explicitly

This test currently assumes the operator service account is always `binding.Subjects[0]`. If another subject is added before it, the test will fail despite the binding being correct. Instead, iterate over `binding.Subjects` and assert that at least one subject has `Kind == "ServiceAccount"` and `Name == "rhtpa-operator-controller-manager"`.

```suggestion
func TestCCOClusterRoleBindingSubjects(t *testing.T) {
	bindingPath := filepath.Join("config", "rbac", "clusterrolebinding_cco.yaml")

	data, err := os.ReadFile(bindingPath)
	require.NoError(t, err, "CCO ClusterRoleBinding should be readable")

	var binding ClusterRoleBinding
	err = yaml.Unmarshal(data, &binding)
	require.NoError(t, err, "CCO ClusterRoleBinding should be valid YAML")

	require.NotEmpty(t, binding.Subjects, "ClusterRoleBinding should have at least one subject")

	found := false
	for _, subject := range binding.Subjects {
		if subject.Kind == "ServiceAccount" && subject.Name == "rhtpa-operator-controller-manager" {
			found = true
			break
		}
	}

	assert.True(t, found, "ClusterRoleBinding should contain a ServiceAccount subject named rhtpa-operator-controller-manager")
}
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +111 to +127
func TestCCOClusterRoleBindingSubjects(t *testing.T) {
bindingPath := filepath.Join("config", "rbac", "clusterrolebinding_cco.yaml")

data, err := os.ReadFile(bindingPath)
require.NoError(t, err, "CCO ClusterRoleBinding should be readable")

var binding ClusterRoleBinding
err = yaml.Unmarshal(data, &binding)
require.NoError(t, err, "CCO ClusterRoleBinding should be valid YAML")

require.NotEmpty(t, binding.Subjects, "ClusterRoleBinding should have at least one subject")

assert.Equal(t, "ServiceAccount", binding.Subjects[0].Kind,
"subject should be a ServiceAccount")
assert.Equal(t, "rhtpa-operator-controller-manager", binding.Subjects[0].Name,
"subject should reference the operator's service account")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (testing): Avoid relying on the first subject in the ClusterRoleBinding; search for the expected service account explicitly

This test currently assumes the operator service account is always binding.Subjects[0]. If another subject is added before it, the test will fail despite the binding being correct. Instead, iterate over binding.Subjects and assert that at least one subject has Kind == "ServiceAccount" and Name == "rhtpa-operator-controller-manager".

Suggested change
func TestCCOClusterRoleBindingSubjects(t *testing.T) {
bindingPath := filepath.Join("config", "rbac", "clusterrolebinding_cco.yaml")
data, err := os.ReadFile(bindingPath)
require.NoError(t, err, "CCO ClusterRoleBinding should be readable")
var binding ClusterRoleBinding
err = yaml.Unmarshal(data, &binding)
require.NoError(t, err, "CCO ClusterRoleBinding should be valid YAML")
require.NotEmpty(t, binding.Subjects, "ClusterRoleBinding should have at least one subject")
assert.Equal(t, "ServiceAccount", binding.Subjects[0].Kind,
"subject should be a ServiceAccount")
assert.Equal(t, "rhtpa-operator-controller-manager", binding.Subjects[0].Name,
"subject should reference the operator's service account")
}
func TestCCOClusterRoleBindingSubjects(t *testing.T) {
bindingPath := filepath.Join("config", "rbac", "clusterrolebinding_cco.yaml")
data, err := os.ReadFile(bindingPath)
require.NoError(t, err, "CCO ClusterRoleBinding should be readable")
var binding ClusterRoleBinding
err = yaml.Unmarshal(data, &binding)
require.NoError(t, err, "CCO ClusterRoleBinding should be valid YAML")
require.NotEmpty(t, binding.Subjects, "ClusterRoleBinding should have at least one subject")
found := false
for _, subject := range binding.Subjects {
if subject.Kind == "ServiceAccount" && subject.Name == "rhtpa-operator-controller-manager" {
found = true
break
}
}
assert.True(t, found, "ClusterRoleBinding should contain a ServiceAccount subject named rhtpa-operator-controller-manager")
}

Signed-off-by: desmax74 <mdessi@redhat.com>
@desmax74 desmax74 changed the title Occ gcp Tokenize Credential Request GCP Jun 22, 2026
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