CP-26533: allow config.cyberark.subdomain in agent YAML - #838
Conversation
The CyberArk tenant subdomain is not a credential, but the agent could only read it via the ARK_SUBDOMAIN environment variable, bypassing its own YAML config entirely. This forced every install -- including Conjur-JWT-only installs that need no other credentials -- to provision a Secret just to carry one non-sensitive value. It's a carry-over from before the Conjur JWT auth path existed, when the subdomain lived in the same Secret as the legacy username/password credentials because that Secret was the only config-delivery mechanism available at the time. The newer service_id/account/jwt_source fields were added to the proper YAML config struct; subdomain never was. Add config.cyberark.subdomain as a real config field. The environment variable remains a fallback for installs that still set it via Secret, so this is backward compatible. The chart's ARK_SUBDOMAIN Secret key becomes optional now that the config field can supply it instead.
398c158 to
93d4240
Compare
The four-case matrix (config only / env only / both / neither) is asserted against LoadClientConfigFromEnvironment, which returns an observable Subdomain. The ValidateAndCombineConfig tests can only assert the client type, so they cannot tell which source won.
Two sequential identical empty-checks become one first-non-empty expression, which is the precedence rule stated directly.
…test The prose quick-start (outside the auto-generated block) still told every install to create a Secret for the subdomain, undoing the point of this change. Also pin the subdomain-precedence test's actual resolved value, and add chart-test coverage for the new optional secretKeyRefs — nothing previously asserted on deployment.yaml at all.
wallrj-cyberark
left a comment
There was a problem hiding this comment.
No correctness bugs. The change is narrow and the generated files are in sync. Five low-severity points, four inline.
Not inline, because the file is not in this diff: hack/ark/test-e2e.sh still hard-requires ARK_SUBDOMAIN and writes it into the Secret. So the headline claim of this PR — that a Conjur-JWT-only install needs no Secret — is never exercised against a live cluster. The script also requires ARK_USERNAME/ARK_SECRET, so only the legacy path runs; that part is pre-existing, not yours. Worth a follow-up issue.
I added the test-ark and test-e2e labels and re-opened the PR to make the suites actually start. Note the green ark-test-e2e does not cover the no-Secret path, for the reason above.
What I checked, and how
- Traced every caller of the two changed signatures.
LoadClientConfigFromEnvironmentandNewCyberArkeach have exactly one non-test production caller, both updated. Nothing else in the tree readsARK_SUBDOMAINor builds acyberark.ClientConfigoutside tests. go test ./internal/cyberark/passes, including the four--machine-hubsubtests inTest_ValidateAndCombineConfig. The only failures inpkg/agentandpkg/clientare the pre-existingKUBEBUILDER_ASSETSskips.helm unittest ./deploy/charts/disco-agentpasses. I confirmed the newdeployment_test.yamlis not vacuous by flipping an expected value: it fails as it should.- Ran
make ark-generateon the PR head. Zero drift: the regeneratedREADME.mdandvalues.schema.jsonmatch what is committed, including alphabetical$defsplacement. pkg/agent/config.gouses plainyaml.Unmarshal, not strict. The new always-presentsubdomain: ""key will not break an older pinned agent image.- Checked the other two charts (
venafi-kubernetes-agent,discovery-agent). Neither renders cyberark config, so nothing was missed there. res.CyberArkis a value type, not a pointer, socfg.CyberArk.Subdomainat the call site cannot nil-deref.optional: trueon asecretKeyRefcovers a missing Secret as well as a missing key, so the "no Secret needed" claim is sound.
|
The I dispatched the same suite against In both runs the agent itself is healthy: it acquires its JWT and OAuth token and logs
|
…ning, rename, chart test - README: $ARK_SUBDOMAIN was only exported inside the skippable Secret section, so the Conjur-JWT-only walkthrough broke its own deploy command. Moved the export to its own step before either path forks. - LoadClientConfig now warns when both config.cyberark.subdomain and ARK_SUBDOMAIN are set, matching selectAuthenticator's existing dual-source convention for the service_id/username-password case. Threaded logr.Logger through NewCyberArk from the one caller that already has it. - Renamed LoadClientConfigFromEnvironment -> LoadClientConfig: the old name said the opposite of the contract once the parameter started winning over the environment variable. - Added a chart test setting a non-empty config.cyberark.subdomain; every existing case only covered the empty default.
|
All four review points are addressed in 12ee476. I have verified each one against ed4296b rather than taking the replies on trust, and I have no further findings. The One thing this PR does not close, which I raised earlier and is worth a follow-up issue rather than more work here: What I ran to verify the four fixes
|
|
Confirmed: |
|
Opened #839 to track adding a live e2e path for the Conjur-JWT-only, Secret-free install. Not touching |
wallrj-cyberark
left a comment
There was a problem hiding this comment.
Approved. All four points from my earlier review are fixed in 12ee476, and I verified each one rather than taking the replies on trust — details are in the comment above.
The failing test-e2e is the pre-existing master breakage, not this PR, and there are no required status checks on master, so it does not block the merge.
One non-blocking note on the test logger, for next time rather than for this PR.
| // capturingSink is a minimal logr.LogSink that records Info() messages, used | ||
| // to assert the dual-source warning actually fires rather than just trusting | ||
| // the code path was reached. | ||
| type capturingSink struct { |
There was a problem hiding this comment.
Non-blocking, and please do not change it in this PR — I am approving as is.
For next time: k8s.io/klog/v2/ktesting already does this, so the hand-rolled sink and its six methods are not needed. auth_select_test.go in this same package already uses ktesting.NewLogger.
One catch — buffering is off by default, so ktesting.DefaultConfig captures nothing. You need BufferLogs:
logger := ktesting.NewLogger(t, ktesting.NewConfig(ktesting.BufferLogs(true)))
cfg, err := cyberark.LoadClientConfig(logger, "from-config")
require.NoError(t, err)
underlier, ok := logger.GetSink().(ktesting.Underlier)
require.True(t, ok)
assert.Contains(t, underlier.GetBuffer().String(), "both config.cyberark.subdomain and ARK_SUBDOMAIN are set")GetBuffer().Data() gives you the structured entries if you would rather assert on fields than on text.
Summary
The CyberArk tenant subdomain is not a credential, but the agent could only read it via the
ARK_SUBDOMAINenvironment variable, bypassing its own YAML config entirely. This forced every install -- including Conjur-JWT-only installs that need no other credentials -- to provision a Secret just to carry one non-sensitive value.It's a carry-over from before the Conjur JWT auth path existed, when the subdomain lived in the same Secret as the legacy username/password credentials because that Secret was the only config-delivery mechanism available at the time. The newer
service_id/account/jwt_sourcefields were added to the proper YAML config struct; subdomain never was.Adds
config.cyberark.subdomainas a real config field. The environment variable remains a fallback for installs that still set it via Secret, so this is backward compatible. The chart'sARK_SUBDOMAINSecret key becomes optional now that the config field can supply it instead.Changes
pkg/agent/config.go: newCyberArkConfig.SubdomainYAML fieldinternal/cyberark/client.go:LoadClientConfigFromEnvironmenttakes an explicit subdomain, falling back toARK_SUBDOMAINwhen emptypkg/client/client_cyberark.go:NewCyberArkthreads the new subdomain param throughconfig.cyberark.subdomainvalue, rendered intoconfig.yaml,ARK_SUBDOMAINSecret key now optionalTest plan
make test-unitpasses cleanmake ark-verify(helm lint, kubeconform policy checks, chart unittest) passes cleanconfig.cyberark.subdomainset instead of the env var