OCPBUGS-71237: Generate session-secret for all auth types - #1204
Conversation
Extend the session-secret Secret (previously OIDC-only) to all authentication types including OpenShift/IntegratedOAuth. This provides shared encryption keys across console pods so cookies can be decrypted after pod restarts, enabling persistent sessions. Changes: - syncSessionSecret() now runs for all auth types, not just OIDC - Config builder sets session key file paths for OpenShift auth - Extract session key path constants to avoid duplication The deployment volume mount is already conditional on sessionSecret being non-nil, so no deployment changes are needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@jhadvig: This pull request references Jira Issue OCPBUGS-71237, which is invalid:
Comment The bug has been updated to refer to the pull request using the external bug tracker. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
|
Skipping CI for Draft Pull Request. |
WalkthroughThe console configuration builder now emits current and previous session authentication and encryption key paths for enabled authentication modes. Disabled authentication returns an empty session configuration. Session Secret synchronization now applies to all authentication types. Tests update structured and YAML expectations. ChangesSession key handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Mergeability Score: 🟡 Moderate · up to This change enables shared session keys across authentication modes, but malformed keys can invalidate existing console sessions and the companion console update must be deployed together because older images may not tolerate the new key paths. These issues should be fixed or explicitly coordinated before merge. Suggested reviewers: 🚥 Pre-merge checks | ✅ 14 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (14 passed)
✨ Finishing Touches 💡 2⚔️ Resolve merge conflicts 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jhadvig The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/console/operator/sync_v400.go`:
- Around line 124-126: Update the error return immediately after
syncSessionSecret in the operator synchronization flow to wrap the error with
meaningful session Secret synchronization context while preserving the original
cause via %w. Keep the existing statusHandler.FlushAndReturn handling unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 7a53bbeb-7bc9-492b-82cf-aa10b9880c50
📒 Files selected for processing (5)
pkg/console/operator/sync_v400.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder.gopkg/console/subresource/consoleserver/config_builder_test.gopkg/console/subresource/consoleserver/config_merger_test.go
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
openshift/console(manual) → reviewed against open PR#16911OCPBUGS-71237instead of the default branch
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: Follow Go coding standards and patterns documented in CONVENTIONS.md
Organize imports according to conventions documented in CONVENTIONS.md
Usegofmtto format Go code with standard formatting
Rungo vetchecks on all Go packagesFollow Go coding standards and patterns as documented in CONVENTIONS.md, including proper import organization
Organize Go code following the repository structure: main entry point in
cmd/console/main.go, API constants inpkg/api/, operator command setup inpkg/cmd/operator/, and version command inpkg/cmd/version/
**/*.go: Usegofmtfor formatting Go code
Follow standard Go naming conventions
Group imports in order: standard lib, 3rd party, kube/openshift, internal (marked with comments)
Use meaningful error messages with context in Go code
Set status conditions usingstatus.Handle*functions with type prefixes (*Degraded, *Progressing, *Available, *Upgradeable)
Use typed errors and wrap errors to preserve stack contextFlag MD5, SHA1, DES, RC4, 3DES, Blowfish, and ECB mode cryptographic usage. Also flag custom crypto implementations and non-constant-time comparison of secrets or tokens.
**/*.go: Do not use deprecated Go APIs such asioutil.ReadFile,ioutil.WriteFile,ioutil.ReadAll, ornet.DialinDialcallbacks; useos.ReadFile,os.WriteFile,io.ReadAll, andDialContextinstead.
When returning errors in Go, wrap them with%wand include meaningful context instead of returning the raw error or using%v.
Use specific error checks such asapierrors.IsNotFound(err)instead of matching error strings withstrings.Contains(err.Error(), ...).
Propagate the caller’scontext.Contextthrough operations and avoid replacing it withcontext.Background()inside request/controller code.
Usedeferto release acquired resources so cleanup happens on all return paths.
Avoid god functions: keep Go functions to roughly under 100 lines and split code with too many responsibilities into smaller...
Files:
pkg/console/operator/sync_v400.gopkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.gopkg/console/subresource/consoleserver/config_builder.go
⚙️ CodeRabbit configuration file
**/*.go: Review Go code following OpenShift operator patterns.
See CONVENTIONS.md for coding standards and patterns.Refer to the following skills based on CODE PATTERNS, not just file paths:
Refer to /controller-review when code contains:
- Controller struct types (e.g.,
type *Controller struct)func New*Controller(factory functionsfactory.New().WithFilteredEventsInformers(pattern.ToController(method callsSync(ctx context.Context, controllerContext factory.SyncContext)methodsoperatorConfig.Spec.ManagementStatechecksstatus.NewStatusHandlerorstatus.Handle*functionsRefer to /sync-handler-review when code contains:
- Main operator sync functions (e.g.,
sync_v400.gocontent)- Sequential resource syncing with early returns
- Incremental reconciliation loops
- Multiple
resourceapply.Apply*()calls in sequence- Dependency ordering of ConfigMaps → Secrets → Service Accounts → RBAC → Services → Deployments → Routes
- Feature gate conditional logic
Refer to /go-quality-review for all Go code to check:
- Deprecated imports:
ioutil.ReadFile,ioutil.WriteFile,ioutil.ReadAll- Deprecated patterns:
DialwithoutDialContext- Error handling: missing
%win fmt.Errorf- Code smells: deep nesting (4+ levels), functions >100 lines
- Magic values: unexplained numbers/strings
- Context propagation:
context.Background()instead of passed ctx- Missing godoc on exported functions
Files:
pkg/console/operator/sync_v400.gopkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.gopkg/console/subresource/consoleserver/config_builder.go
{pkg,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Use gofmt for code formatting on pkg and cmd directories
{pkg,cmd}/**/*.go: Format code usinggofmt -w ./pkg ./cmd
Rungo vetchecks on all Go packages in ./pkg and ./cmd
Files:
pkg/console/operator/sync_v400.gopkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.gopkg/console/subresource/consoleserver/config_builder.go
**/*sync*.go
📄 CodeRabbit inference engine (CONVENTIONS.md)
Implement sync loops (
sync_v400) incrementally: start from zero, create/update missing requirements, and return to continue on next loop
Files:
pkg/console/operator/sync_v400.go
**/operator/**/*.go
📄 CodeRabbit inference engine (Custom checks)
When deployment manifests, operator code, or controllers are added/modified, ensure they do not introduce scheduling constraints assuming standard HA topology. Check ControlPlaneTopology for SingleReplica/DualReplica/HighlyAvailableArbiter/External modes before applying constraints. Use required anti-affinity with maxUnavailable >= 1 (not maxUnavailable: 0). Cap replica counts to schedulable nodes. Exclude arbiter nodes on TNA. Avoid master nodeSelectors on HyperShift. Use library-go DeploymentController hooks (WithTopologyAwareReplicasHook, WithTopologyAwareSchedulingHook, WithControlPlaneNodeSelectorHook).
Files:
pkg/console/operator/sync_v400.go
**/sync_v400.go
📄 CodeRabbit inference engine (.claude/skills/sync-handler-review.md)
Incremental sync pattern: each sync loop should stop on the first error and resume from the next step on the next reconciliation instead of collecting and joining all errors.
Files:
pkg/console/operator/sync_v400.go
**/*.{py,js,ts,go,rs,java,rb,php,kt,swift,cs}
⚙️ CodeRabbit configuration file
**/*.{py,js,ts,go,rs,java,rb,php,kt,swift,cs}: Injection prevention (prodsec-skills):
- SQL: parameterized queries only; no string concatenation
- Command: no shell=True, os.system, or backtick exec with user input
- LDAP/XPath: escape special characters in filters
- Path traversal: canonicalize paths, reject ../
- Deserialization: no pickle/yaml.load()/eval on untrusted data
- Prototype pollution: no recursive merge of untrusted objects
- Validate at trust boundaries with allow-lists, not deny-lists
- Normalize Unicode and anchor regexes (^$); watch for ReDoS
Files:
pkg/console/operator/sync_v400.gopkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.gopkg/console/subresource/consoleserver/config_builder.go
**/*_test.go
📄 CodeRabbit inference engine (AGENTS.md)
Follow testing patterns and commands documented in TESTING.md
Follow testing patterns and commands as documented in TESTING.md, including running unit tests with 'make test-unit' and checks with 'make check'
**/*_test.go: Use table-driven tests for comprehensive coverage
Usehttptestfor HTTP handler testing in Go
Include proper cleanup functions in tests
Test both success and failure pathsIn Go tests, do not ignore returned errors; check
errand fail the test witht.Fatalfort.Errorfas appropriate.
Files:
pkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.go
⚙️ CodeRabbit configuration file
**/*_test.go: Review test code for quality and patterns.Refer to /unit-test-review when test is in pkg//*_test.go:**
- Table-driven test structure with test cases
- Use of
go-test/deepfor struct comparisons- Test naming conventions (TestFunctionName)
- Error handling with
wantErrpattern- Edge case coverage (nil, empty, boundary values)
- Proper assertions with helpful error messages
- Test isolation (no shared mutable state)
Refer to /e2e-test-review when test contains:
framework.MustNewClientset(t, nil)or similar e2e framework usagewait.Pollorwait.PollImmediatepatternsretry.RetryOnConflictfor updates- Cleanup via
deferfunctions- Console/operator CR manipulations
- Test assertions on cluster state
Suggest to use /e2e-test-review when:
- PR adds new feature requiring e2e coverage
- Test file is empty or skeleton
- Comments indicate "TODO: add test"
Review for common issues:
- Missing cleanup (defer statements)
- Using
time.Sleepinstead ofwait.Poll- Missing context timeouts
- Vague error messages in assertions
- Tests without table-driven structure when testing multiple cases
- Ignoring errors with
_- Tests without assertions
Files:
pkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.go
pkg/console/subresource/**/*.go
📄 CodeRabbit inference engine (ARCHITECTURE.md)
Use
pkg/console/subresource/packages for resource builders, with separate packages for each resource type (authentication, configmap, deployment, oauthclient, route, secret, etc.)
Files:
pkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.gopkg/console/subresource/consoleserver/config_builder.go
pkg/**/*_test.go
📄 CodeRabbit inference engine (.claude/skills/unit-test-review.md)
pkg/**/*_test.go: Most unit tests should use the table-driven test pattern, including atests := []struct{...}table andt.Run(tt.name, ...)subtests for scenarios with multiple cases.
Test function names and subtest case names should be descriptive of the behavior or scenario being tested (for example,TestGetNodeComputeEnvironmentsor"Custom hostname and TLS secret set").
Usegithub.com/go-test/deep(deep.Equal) for struct comparisons instead of==or manual field-by-field checks.
Cover both success and failure paths in unit tests, including edge cases such as empty inputs, boundary values, missing fields, duplicates, and large inputs.
Structure tests using Arrange-Act-Assert so setup, execution, and verification are clearly separated.
When testing error-returning functions, assert error presence correctly and, when relevant, validate the error message substring instead of ignoring the error or discarding it with_.
Prefer dependency injection via interfaces for testability, and keep tests isolated so they do not depend on execution order or shared mutable state.
Extract repeated setup into helper functions when common test fixtures are reused across multiple tests.
Write specific, informative assertions that explain what failed instead of vague or silent failures.
Inline simple test data, but move complex fixtures to helper functions ortestdata/files.
Avoid tests that rely on execution order, share global mutable state, use hardcoded sleeps, omit assertions, or verify implementation details instead of behavior.
Files:
pkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder_test.go
🪛 ast-grep (0.45.0)
pkg/console/subresource/consoleserver/config_builder.go
[warning] 25-25: A credential is hard-coded as a string literal. Secrets stored in source code, such as passwords, API keys, and tokens, can be leaked through version control or binaries and used by internal or external malicious actors. Rotate the exposed secret and load it at runtime from a secure secret vault, a Hardware Security Module (HSM), or an environment variable if permitted by your company policy (e.g. password := os.Getenv("APP_PASSWORD")).
Context: sessionAuthKeyFilePath = "/var/session-secret/sessionAuthenticationKey"
Note: [CWE-798] Use of Hard-coded Credentials.
(hardcoded-credentials-string-literal-go)
🔇 Additional comments (4)
pkg/console/subresource/consoleserver/config_builder.go (1)
24-27: LGTM!Also applies to: 203-204, 224-225, 459-472
pkg/console/subresource/consoleserver/config_builder_test.go (1)
74-77: LGTM!Also applies to: 110-113, 157-160, 211-214, 365-368, 404-407, 443-446, 506-509, 569-572, 612-615, 655-658, 697-700, 753-756, 821-824, 888-891, 948-951, 1005-1008, 1049-1052, 1094-1097, 1151-1153, 1236-1238, 1263-1265, 1292-1294, 1322-1324, 1376-1378, 1422-1424, 1459-1461, 1497-1499, 1584-1586, 1632-1634, 1704-1706, 1780-1782, 1836-1838, 1874-1876
pkg/console/subresource/configmap/configmap_test.go (1)
126-128: LGTM!Also applies to: 194-196, 222-224, 280-282, 310-312, 365-367, 402-404, 453-455, 496-498, 547-549, 653-655, 704-706, 776-778, 827-829, 902-904, 972-974, 1045-1047, 1159-1161, 1231-1233, 1307-1309, 1546-1548, 1559-1561
pkg/console/subresource/consoleserver/config_merger_test.go (1)
64-66: LGTM!
| sessionSecret, err = co.syncSessionSecret(ctx, updatedOperatorConfig, controllerContext.Recorder()) | ||
| if err != nil { | ||
| return statusHandler.FlushAndReturn(err) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Wrap the session Secret synchronization error with context.
Line 126 returns the raw error. Add the failed operation name and preserve the cause with %w. This improves diagnosis because this operation now runs for every authentication type.
Proposed fix
- return statusHandler.FlushAndReturn(err)
+ return statusHandler.FlushAndReturn(fmt.Errorf("sync session Secret: %w", err))As per coding guidelines, “When returning errors in Go, wrap them with %w and include meaningful context instead of returning the raw error or using %v.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| sessionSecret, err = co.syncSessionSecret(ctx, updatedOperatorConfig, controllerContext.Recorder()) | |
| if err != nil { | |
| return statusHandler.FlushAndReturn(err) | |
| sessionSecret, err = co.syncSessionSecret(ctx, updatedOperatorConfig, controllerContext.Recorder()) | |
| if err != nil { | |
| return statusHandler.FlushAndReturn(fmt.Errorf("sync session Secret: %w", err)) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/console/operator/sync_v400.go` around lines 124 - 126, Update the error
return immediately after syncSessionSecret in the operator synchronization flow
to wrap the error with meaningful session Secret synchronization context while
preserving the original cause via %w. Keep the existing
statusHandler.FlushAndReturn handling unchanged.
Source: Coding guidelines
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Test ResultsAll scenarios verified on a live cluster (GCP) with both console-operator and console PRs deployed together.
What this PR doesExtends the Companion console PR: openshift/console#16911 /verified by @jhadvig |
|
@jhadvig: This PR has been marked as verified by DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
|
/retest |
CI e2e failures explanationThe 4 e2e job failures are expected and not caused by bugs in this PR. Root cause: The e2e jobs build the operator from this PR but use the stock console image from the nightly. This PR sets session key file paths in the console config for OpenShift auth (previously OIDC-only). The stock console binary treats missing key files as a fatal error and crashes during bootstrap before the The fix for this is in the companion console PR (#16911), which makes missing key files non-fatal for OpenShift auth (logs a warning and falls back to random keys). Once that console image lands in the nightly, these e2e jobs will pass. Merge order: Console PR #16911 must merge first (it's fully backward compatible), then this operator PR can be retested and merged. When deployed together (as verified in the test results above), both PRs work correctly — the cluster installs cleanly and sessions persist across pod restarts. |
On key regeneration, copy current keys to previous* fields in the session-secret Secret before generating new ones. Pass previous key file paths in the console config so the console can decrypt cookies encrypted with old keys during the rotation window. - session_secret.go: preserve previous keys on rotation - config_builder.go: emit previous key file paths for all auth types - types.go: add Previous* fields to Session struct Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
PR needs rebase. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
@jhadvig: The following tests failed, say
Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
|
@jhadvig: This pull request references Jira Issue OCPBUGS-71237, which is invalid:
Comment DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
pkg/console/subresource/consoleserver/config_builder.go (1)
207-210: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a Godoc comment for
AuthConfig.
AuthConfigis exported. Add a comment that states that it configures authentication and session key file paths.Proposed change
+// AuthConfig configures console authentication and session key file paths. func (b *ConsoleServerCLIConfigBuilder) AuthConfig(authnConfig *configv1.Authentication, apiServerURL string) *ConsoleServerCLIConfigBuilder {As per coding guidelines, “Document exported Go functions with a Godoc comment that explains what the function does.” As per path instructions, check “Missing godoc on exported functions.”
Also applies to: 230-233
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/console/subresource/consoleserver/config_builder.go` around lines 207 - 210, Add a Godoc comment immediately before the exported AuthConfig type, stating that it configures authentication and session key file paths. Apply the same documentation requirement to the additional AuthConfig declaration or occurrence referenced by the review, without changing its behavior.Sources: Coding guidelines, Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/console/subresource/secret/session_secret.go`:
- Around line 41-54: Update the key-rotation logic around sessionEncryptionKey
and sessionAuthenticationKey so an existing previous key is overwritten only
when the current key has the expected AES-256 or SHA-256 length; do not copy
malformed non-empty keys into the previous-key fields. Preserve generation of
replacement keys and add regression coverage for both fields, including valid
and invalid current-key cases.
---
Nitpick comments:
In `@pkg/console/subresource/consoleserver/config_builder.go`:
- Around line 207-210: Add a Godoc comment immediately before the exported
AuthConfig type, stating that it configures authentication and session key file
paths. Apply the same documentation requirement to the additional AuthConfig
declaration or occurrence referenced by the review, without changing its
behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 4f824988-71e1-43ff-b8e3-8152ffdfd891
📒 Files selected for processing (6)
pkg/console/subresource/configmap/configmap_test.gopkg/console/subresource/consoleserver/config_builder.gopkg/console/subresource/consoleserver/config_builder_test.gopkg/console/subresource/consoleserver/config_merger_test.gopkg/console/subresource/consoleserver/types.gopkg/console/subresource/secret/session_secret.go
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
openshift/console(manual) → reviewed against open PR#16911OCPBUGS-71237instead of the default branch
🚧 Files skipped from review as they are similar to previous changes (3)
- pkg/console/subresource/consoleserver/config_merger_test.go
- pkg/console/subresource/configmap/configmap_test.go
- pkg/console/subresource/consoleserver/config_builder_test.go
📜 Review details
⚠️ CI failures not shown inline (3)
Commit Status: ci/prow/okd-scos-images: ci/prow/okd-scos-images
Conclusion: failure
Job failed. BaseSHA:080a8a9d3310799313d897c9cd61ad9ef2f8c7c8
Commit Status: ci/prow/images: ci/prow/images
Conclusion: failure
Job failed. BaseSHA:080a8a9d3310799313d897c9cd61ad9ef2f8c7c8
Commit Status: ci/prow/verify: ci/prow/verify
Conclusion: failure
Job failed. BaseSHA:080a8a9d3310799313d897c9cd61ad9ef2f8c7c8
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: Follow Go coding standards and patterns documented in CONVENTIONS.md
Organize imports according to conventions documented in CONVENTIONS.md
Usegofmtto format Go code with standard formatting
Rungo vetchecks on all Go packagesFollow Go coding standards and patterns as documented in CONVENTIONS.md, including proper import organization
Organize Go code following the repository structure: main entry point in
cmd/console/main.go, API constants inpkg/api/, operator command setup inpkg/cmd/operator/, and version command inpkg/cmd/version/
**/*.go: Usegofmtfor formatting Go code
Follow standard Go naming conventions
Group imports in order: standard lib, 3rd party, kube/openshift, internal (marked with comments)
Use meaningful error messages with context in Go code
Set status conditions usingstatus.Handle*functions with type prefixes (*Degraded, *Progressing, *Available, *Upgradeable)
Use typed errors and wrap errors to preserve stack contextFlag MD5, SHA1, DES, RC4, 3DES, Blowfish, and ECB mode cryptographic usage. Also flag custom crypto implementations and non-constant-time comparison of secrets or tokens.
**/*.go: Do not use deprecated Go APIs such asioutil.ReadFile,ioutil.WriteFile,ioutil.ReadAll, ornet.DialinDialcallbacks; useos.ReadFile,os.WriteFile,io.ReadAll, andDialContextinstead.
When returning errors in Go, wrap them with%wand include meaningful context instead of returning the raw error or using%v.
Use specific error checks such asapierrors.IsNotFound(err)instead of matching error strings withstrings.Contains(err.Error(), ...).
Propagate the caller’scontext.Contextthrough operations and avoid replacing it withcontext.Background()inside request/controller code.
Usedeferto release acquired resources so cleanup happens on all return paths.
Avoid god functions: keep Go functions to roughly under 100 lines and split code with too many responsibilities into smaller...
Files:
pkg/console/subresource/secret/session_secret.gopkg/console/subresource/consoleserver/types.gopkg/console/subresource/consoleserver/config_builder.go
⚙️ CodeRabbit configuration file
**/*.go: Review Go code following OpenShift operator patterns.
See CONVENTIONS.md for coding standards and patterns.Refer to the following skills based on CODE PATTERNS, not just file paths:
Refer to /controller-review when code contains:
- Controller struct types (e.g.,
type *Controller struct)func New*Controller(factory functionsfactory.New().WithFilteredEventsInformers(pattern.ToController(method callsSync(ctx context.Context, controllerContext factory.SyncContext)methodsoperatorConfig.Spec.ManagementStatechecksstatus.NewStatusHandlerorstatus.Handle*functionsRefer to /sync-handler-review when code contains:
- Main operator sync functions (e.g.,
sync_v400.gocontent)- Sequential resource syncing with early returns
- Incremental reconciliation loops
- Multiple
resourceapply.Apply*()calls in sequence- Dependency ordering of ConfigMaps → Secrets → Service Accounts → RBAC → Services → Deployments → Routes
- Feature gate conditional logic
Refer to /go-quality-review for all Go code to check:
- Deprecated imports:
ioutil.ReadFile,ioutil.WriteFile,ioutil.ReadAll- Deprecated patterns:
DialwithoutDialContext- Error handling: missing
%win fmt.Errorf- Code smells: deep nesting (4+ levels), functions >100 lines
- Magic values: unexplained numbers/strings
- Context propagation:
context.Background()instead of passed ctx- Missing godoc on exported functions
Files:
pkg/console/subresource/secret/session_secret.gopkg/console/subresource/consoleserver/types.gopkg/console/subresource/consoleserver/config_builder.go
{pkg,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Use gofmt for code formatting on pkg and cmd directories
{pkg,cmd}/**/*.go: Format code usinggofmt -w ./pkg ./cmd
Rungo vetchecks on all Go packages in ./pkg and ./cmd
Files:
pkg/console/subresource/secret/session_secret.gopkg/console/subresource/consoleserver/types.gopkg/console/subresource/consoleserver/config_builder.go
pkg/console/subresource/**/*.go
📄 CodeRabbit inference engine (ARCHITECTURE.md)
Use
pkg/console/subresource/packages for resource builders, with separate packages for each resource type (authentication, configmap, deployment, oauthclient, route, secret, etc.)
Files:
pkg/console/subresource/secret/session_secret.gopkg/console/subresource/consoleserver/types.gopkg/console/subresource/consoleserver/config_builder.go
**/*.{py,js,ts,go,rs,java,rb,php,kt,swift,cs}
⚙️ CodeRabbit configuration file
**/*.{py,js,ts,go,rs,java,rb,php,kt,swift,cs}: Injection prevention (prodsec-skills):
- SQL: parameterized queries only; no string concatenation
- Command: no shell=True, os.system, or backtick exec with user input
- LDAP/XPath: escape special characters in filters
- Path traversal: canonicalize paths, reject ../
- Deserialization: no pickle/yaml.load()/eval on untrusted data
- Prototype pollution: no recursive merge of untrusted objects
- Validate at trust boundaries with allow-lists, not deny-lists
- Normalize Unicode and anchor regexes (^$); watch for ReDoS
Files:
pkg/console/subresource/secret/session_secret.gopkg/console/subresource/consoleserver/types.gopkg/console/subresource/consoleserver/config_builder.go
🪛 ast-grep (0.45.1)
pkg/console/subresource/consoleserver/config_builder.go
[warning] 25-25: A credential is hard-coded as a string literal. Secrets stored in source code, such as passwords, API keys, and tokens, can be leaked through version control or binaries and used by internal or external malicious actors. Rotate the exposed secret and load it at runtime from a secure secret vault, a Hardware Security Module (HSM), or an environment variable if permitted by your company policy (e.g. password := os.Getenv("APP_PASSWORD")).
Context: sessionAuthKeyFilePath = "/var/session-secret/sessionAuthenticationKey"
Note: [CWE-798] Use of Hard-coded Credentials.
(hardcoded-credentials-string-literal-go)
[warning] 27-27: A credential is hard-coded as a string literal. Secrets stored in source code, such as passwords, API keys, and tokens, can be leaked through version control or binaries and used by internal or external malicious actors. Rotate the exposed secret and load it at runtime from a secure secret vault, a Hardware Security Module (HSM), or an environment variable if permitted by your company policy (e.g. password := os.Getenv("APP_PASSWORD")).
Context: previousSessionAuthKeyFilePath = "/var/session-secret/previousSessionAuthenticationKey"
Note: [CWE-798] Use of Hard-coded Credentials.
(hardcoded-credentials-string-literal-go)
🔇 Additional comments (4)
pkg/console/subresource/consoleserver/config_builder.go (3)
24-29: LGTM!
53-93: LGTM!
467-491: 🩺 Stability & AvailabilityVerify the companion console-image dependency before merge.
session()emits previous-key paths for every enabled authentication mode. The PR notes that stock console images treat missing key files as fatal. Ensure the companion console change is deployed before this configuration can reach an older console image, then rerun the failed e2e jobs with both changes.pkg/console/subresource/consoleserver/types.go (1)
103-106: 🗄️ Data Integrity & IntegrationVerify the companion console contract before merging.
These fields add previous-key paths to the console configuration. The previous-key files are absent until the first rotation. Confirm that the companion console accepts both YAML fields and treats missing previous-key files as non-fatal. The supplied PR context reports that the stock console crashes on missing key files.
The downstream builder emits these paths for enabled authentication.
| // Preserve the current key as the previous key for graceful rotation, | ||
| // so that existing sessions can still be decrypted during the transition. | ||
| if len(secret.Data["sessionEncryptionKey"]) > 0 { | ||
| secret.Data["previousSessionEncryptionKey"] = secret.Data["sessionEncryptionKey"] | ||
| } | ||
| secret.Data["sessionEncryptionKey"] = []byte(randomString(aes256KeyLenBytes)) | ||
| changed = true | ||
| } | ||
|
|
||
| if len(secret.Data["sessionAuthenticationKey"]) != sha256KeyLenBytes { | ||
| // Preserve the current key as the previous key for graceful rotation. | ||
| if len(secret.Data["sessionAuthenticationKey"]) > 0 { | ||
| secret.Data["previousSessionAuthenticationKey"] = secret.Data["sessionAuthenticationKey"] | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- target file ---'
cat -n pkg/console/subresource/secret/session_secret.go
printf '%s\n' '--- related symbols and tests ---'
rg -n -C 4 'previousSessionEncryptionKey|previousSessionAuthenticationKey|sessionEncryptionKey|sessionAuthenticationKey|session\(\)' \
pkg test 2>/dev/null || true
printf '%s\n' '--- downstream console references ---'
printf '%s\n' 'Inspecting the checked-out branch of openshift/console (PR `#16911` head).'Repository: openshift/console-operator
Length of output: 50382
🏁 Script executed:
#!/bin/bash
set -eu
rg -n -C 5 'previousSessionEncryptionKey|previousSessionAuthenticationKey|sessionEncryptionKey|sessionAuthenticationKey|PreviousSession|SessionEncryption|SessionAuthentication' \
pkg 2>/dev/null || trueRepository: openshift/console
Length of output: 155
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- session config definitions and consumers ---'
fd -t f -e go -e ts -e js . pkg | \
xargs rg -n -C 4 'CookieEncryptionKeyFile|PreviousCookieEncryptionKeyFile|cookieEncryptionKeyFile|previousCookieEncryptionKeyFile|Session struct|sessionKey' 2>/dev/null | head -n 500
printf '%s\n' '--- canonical subresource types ---'
fd -t f 'types.go' pkg/console/subresourceRepository: openshift/console
Length of output: 2584
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- session secret tests and callers ---'
fd -t f -e go . pkg | \
xargs rg -l 'ResetSessionSecretKeysIfNeeded|DefaultSessionSecret|session_secret' 2>/dev/null | sort
printf '%s\n' '--- secret application/callers ---'
rg -n -C 5 'DefaultSessionSecret|ResetSessionSecretKeysIfNeeded|SessionSecretName' pkg cmd | head -n 300
printf '%s\n' '--- session secret history summary ---'
git log --oneline --all -- pkg/console/subresource/secret/session_secret.go | head -n 20Repository: openshift/console-operator
Length of output: 5380
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
terms = (
"CookieEncryptionKeyFile",
"PreviousCookieEncryptionKeyFile",
"cookieEncryptionKeyFile",
"previousCookieEncryptionKeyFile",
"cookieAuthenticationKeyFile",
"previousCookieAuthenticationKeyFile",
)
for p in Path("pkg").rglob("*"):
if p.is_file() and p.suffix in {".go", ".ts", ".js", ".yaml", ".yml"}:
try:
text = p.read_text(errors="ignore")
except OSError:
continue
if any(t in text for t in terms):
print(p)
PYRepository: openshift/console
Length of output: 181
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- all session configuration references ---'
rg -n -C 5 'PreviousCookie|CookieAuthentication|CookieEncryption|previousCookie|cookieAuthentication|cookieEncryption|securecookie|gorilla|Session' \
--glob '!vendor/**' --glob '!**/*_test.go' . | head -n 800
printf '%s\n' '--- serverconfig type context ---'
cat -n pkg/serverconfig/types.go | sed -n '85,115p'Repository: openshift/console
Length of output: 50373
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- rotation commit summary and patch ---'
git show --stat --oneline c51e1f2b
git show --format=fuller --no-ext-diff --unified=40 c51e1f2b -- \
pkg/console/subresource/secret/session_secret.go \
pkg/console/operator/sync_v400.go \
2>/dev/null | head -n 500
printf '%s\n' '--- current branch ancestry around target ---'
git log --oneline --decorate -8 -- pkg/console/subresource/secret/session_secret.goRepository: openshift/console-operator
Length of output: 4493
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
terms = (
"CookieAuthenticationKeyFile",
"CookieEncryptionKeyFile",
"PreviousCookieAuthenticationKeyFile",
"PreviousCookieEncryptionKeyFile",
"cookieAuthenticationKeyFile",
"cookieEncryptionKeyFile",
"previousCookieAuthenticationKeyFile",
"previousCookieEncryptionKeyFile",
)
for p in Path(".").rglob("*"):
if p.is_file() and ".git" not in p.parts and p.suffix in {".go", ".ts", ".tsx", ".js", ".yaml", ".yml"}:
try:
text = p.read_text(errors="ignore")
except OSError:
continue
hits = [i + 1 for i, line in enumerate(text.splitlines()) if any(t in line for t in terms)]
if hits:
print(f"{p}: {hits[:20]}")
PYRepository: openshift/console
Length of output: 265
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- consumers of serverconfig.Session ---'
rg -n -C 6 'serverconfig\.Session|config\.Session|Session\.(Cookie|Previous)|cookie.*Key|previous.*Key' \
--glob '*.go' --glob '!vendor/**' . | head -n 1000
printf '%s\n' '--- session/auth package files ---'
fd -t f . pkg/auth pkg/serverconfig 2>/dev/null | sort | head -n 300Repository: openshift/console
Length of output: 24155
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
p = Path("pkg/console/subresource/secret/session_secret.go")
text = p.read_text()
# Read-only behavioral probe for the two map transformations implemented in
# ResetSessionSecretKeysIfNeeded. The inputs model malformed current material
# and an already-valid previous key.
cases = [
("sessionEncryptionKey", "previousSessionEncryptionKey", 32, b"bad", b"P" * 32),
("sessionAuthenticationKey", "previousSessionAuthenticationKey", 64, b"bad", b"P" * 64),
]
for current_name, previous_name, required_len, current, previous in cases:
data = {current_name: current, previous_name: previous}
if len(data[current_name]) != required_len:
if len(data[current_name]) > 0:
data[previous_name] = data[current_name]
data[current_name] = b"R" * required_len
print(current_name, {
"previous_preserved": data[previous_name] == previous,
"previous_value": data[previous_name].decode(),
"new_current_length": len(data[current_name]),
})
# Confirm the source contains the unconditional non-empty current-to-previous
# assignment for both key names.
for previous_name in ("previousSessionEncryptionKey", "previousSessionAuthenticationKey"):
needle = f'secret.Data["{previous_name}"] = secret.Data["{previous_name.replace("previous", "")}"]'
print(previous_name, "assignment_present=", needle in text)
PYRepository: openshift/console-operator
Length of output: 486
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- server configuration flow ---'
rg -n -C 5 'serverconfig|ServerConfig|Session' pkg cmd --glob '*.go' | head -n 1200
printf '%s\n' '--- key-file handling outside exact field names ---'
rg -n -C 5 'cookie|session.*file|key.*file|ReadFile|os\.ReadFile|os\.Open' pkg cmd --glob '*.go' | head -n 1200Repository: openshift/console
Length of output: 50374
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
p = Path("pkg/console/subresource/secret/session_secret.go")
text = p.read_text()
cases = [
("sessionEncryptionKey", "previousSessionEncryptionKey", 32, b"bad", b"P" * 32),
("sessionAuthenticationKey", "previousSessionAuthenticationKey", 64, b"bad", b"P" * 64),
]
for current_name, previous_name, required_len, current, previous in cases:
data = {current_name: current, previous_name: previous}
if len(data[current_name]) != required_len:
if len(data[current_name]) > 0:
data[previous_name] = data[current_name]
data[current_name] = b"R" * required_len
print(current_name, {
"previous_preserved": data[previous_name] == previous,
"previous_value_length": len(data[previous_name]),
"new_current_length": len(data[current_name]),
})
for current_name, previous_name in (
("sessionEncryptionKey", "previousSessionEncryptionKey"),
("sessionAuthenticationKey", "previousSessionAuthenticationKey"),
):
needle = f'secret.Data["{previous_name}"] = secret.Data["{current_name}"]'
print(previous_name, "assignment_present=", needle in text)
PYRepository: openshift/console-operator
Length of output: 490
Preserve the previous key when the current key is invalid.
A malformed non-empty current key overwrites an existing previousSessionEncryptionKey or previousSessionAuthenticationKey. The console consumer on the branch of open PR #16911 loads these files as fallback cookie keys. Copy the current key only when it has the expected length. Add regression tests for both fields.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/console/subresource/secret/session_secret.go` around lines 41 - 54,
Update the key-rotation logic around sessionEncryptionKey and
sessionAuthenticationKey so an existing previous key is overwritten only when
the current key has the expected AES-256 or SHA-256 length; do not copy
malformed non-empty keys into the previous-key fields. Preserve generation of
replacement keys and add regression coverage for both fields, including valid
and invalid current-key cases.
Analysis / Root cause:
Console sessions are lost on pod restart because encryption keys are generated randomly per process, making cookies non-portable across pods. The
session-secretSecret infrastructure already exists for OIDC auth but was not enabled for OpenShift/IntegratedOAuth auth.Jira: https://redhat.atlassian.net/browse/OCPBUGS-71237
Companion PR: openshift/console#16911
Solution description:
Extend the existing
session-secretSecret management to all authentication types:syncSessionSecret()now runs for all auth types, not just OIDCsessionAuthKeyFilePathandsessionEncKeyFilePathconstantssessionSecret != nilUpgrade safety: On upgrade,
syncSessionSecret()creates the Secret before the ConfigMap and Deployment are synced.Rollback safety: If downgraded, the orphaned Secret is harmless. The downgraded operator reverts to per-pod random keys.
Test cases:
Additional info:
🤖 Generated with Claude Code
Summary by CodeRabbit