Repository navigation
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
21c2723 to
5587ef6
Compare
| } | ||
|
|
||
| if extractedStemcell.Manifest().SupportsFeature(agentpassword.Feature) { | ||
| c.ui.PrintLinef("Warning: agent password verifiers require cryptographically random passwords; hardcoded or predictable passwords remain vulnerable to offline guessing.") |
There was a problem hiding this comment.
Codex agent here. Removed the unconditional warning. Random passwords remain a requirement recorded in the commit messages; warning on every run did not establish whether a password was generated securely. The separate warning now applies only when standard CPI settings cannot be identified and are left unchanged.
There was a problem hiding this comment.
This seems like a lot of code to replace a string with a hashed string - can this be simplified?
There was a problem hiding this comment.
Codex agent here. Simplified agentpassword/password.go to a 50-line URL verifier helper. Manifest handling now sits beside deployment preparation and uses one shared helper for scalar and overriding URL settings. Removed CPI-specific property traversal and preserved missing CPI defaults rather than rejecting the manifest.
There was a problem hiding this comment.
Codex agent here. Removed the cloning in f74f37b82 after tracing ownership. The parsers recursively allocate fresh maps/lists, including for YAML aliases, while the CLI client URL remains a separate string. The manifest SHA is captured before transformation, and errors abort before CPI installation. The helper now updates these owned agent settings in place and returns only (bool, error). The full ownership rationale is in the commit message. CLI packages compile; existing assertions were adjusted but tests have not been rerun.
| if err != nil { | ||
| return bosherr.WrapError(err, "Hashing CPI agent HTTP password") | ||
| } | ||
| for i := range deploymentManifest.ResourcePools { |
There was a problem hiding this comment.
Are these resource_pools used for the cli to communicate with the agent, or by the agent on the stemcell? As far as I know, only part of the cloud_provider need to change: https://github.com/cloudfoundry/bosh-deployment/blob/951af8e335bd22648d1d65ddb5c35fc03c0ecce6/bosh.yml#L1-L6
There was a problem hiding this comment.
Codex agent here. These are settings delivered to the agent: the VM manager passes resourcePool.Env to CreateVM, and Settings.GetMbusURL prefers env.bosh.mbus.urls over the base mbus. The standard bosh-deployment manifest only supplies the TLS certificate there, so it remains unchanged. We still transform explicit URL overrides so they cannot leave a plaintext password in metadata. The client cloud_provider.mbus stays unchanged.
There was a problem hiding this comment.
Inspecting a settings.json on a live create-env'd vm, and there's no resource_pool - I think the only thing we want to rewrite here is the installationManifest.Mbus
There was a problem hiding this comment.
Codex agent: we only care about the create-env case here
There was a problem hiding this comment.
Codex agent here. This is specifically the create-env path. installationManifest.Mbus is passed unchanged to both the agent client and blob client; hashing it would make those clients send the verifier as their Basic Auth password and fail authentication. The metadata-side field is installationManifest.Properties["agent"]["mbus"]. There is no resource_pool key in settings.json because resource_pools is a manifest wrapper: its env is passed to CreateVM. For the standard manifest, only properties.agent.mbus changes. The environment helper does nothing unless URLs explicitly override that agent setting; it leaves the certificate unchanged.
5587ef6 to
4463e98
Compare
| // hash.Hash.Write consumes all input and never returns an error. | ||
| _, _ = mac.Write([]byte(password)) | ||
| key := mac.Sum(nil) | ||
| verifier := prefix + base64.RawStdEncoding.EncodeToString(salt) + "$" + base64.RawStdEncoding.EncodeToString(key) |
There was a problem hiding this comment.
Codex agent here. Updated verifier serialization to fmt.Sprintf.
| return bosherr.WrapError(err, "Hashing CPI agent HTTP password") | ||
| } | ||
| if !explicitMbus { | ||
| c.ui.PrintLinef("Warning: no explicit agent mbus URL found in supported CPI properties; CPI defaults and other credential locations are unchanged. Explicit env.bosh.mbus.urls overrides are still hashed.") |
There was a problem hiding this comment.
Please remove this conditional and warning
There was a problem hiding this comment.
Codex agent here. Removed the conditional and warning. Missing explicit agent.mbus settings remain a no-op, and explicit env.bosh.mbus.urls overrides are still processed.
| "testing" | ||
| ) | ||
|
|
||
| func TestHashURL(t *testing.T) { |
There was a problem hiding this comment.
Please rewrite these as ginkgo/gomega tests like the rest in the codebase
There was a problem hiding this comment.
Codex agent here. Converted to Ginkgo v2/Gomega in 3217cee. The affected test packages compile; the suites have not been executed.
| "github.com/cloudfoundry/bosh-utils/property" | ||
| ) | ||
|
|
||
| func TestHashAgentPropertiesInPlace(t *testing.T) { |
There was a problem hiding this comment.
Please rewrite these as ginkgo/gomega tests like the rest in the codebase
There was a problem hiding this comment.
Codex agent here. Converted to Ginkgo v2/Gomega in 3217cee. The affected test packages compile; the suites have not been executed.
| "gopkg.in/yaml.v2" | ||
| ) | ||
|
|
||
| func TestAgentFeaturesRoundTrip(t *testing.T) { |
There was a problem hiding this comment.
Please rewrite these as ginkgo/gomega tests like the rest in the codebase
There was a problem hiding this comment.
Codex agent here. Converted to Ginkgo v2/Gomega in 3217cee. The affected test packages compile; the suites have not been executed.
| if err != nil { | ||
| return bosherr.WrapError(err, "Hashing CPI agent HTTP password") | ||
| } | ||
| for i := range deploymentManifest.ResourcePools { |
There was a problem hiding this comment.
Codex agent review — P2: Only transform the resource pool selected for the create-env job. GetStemcell fetches the stemcell for deploymentManifest.JobName(), and deployment/vm/manager.go passes only deploymentManifest.ResourcePool(jobName).Env to CreateVM. This loop additionally validates unused pools against that selected stemcell capability. An unused pool with an invalid/empty HTTPS credential or a differently shaped mbus override now aborts a deployment that previously ignored that env. Please resolve the selected pool and hash only its Env.
| if u.User == nil { | ||
| return "", fmt.Errorf("HTTPS agent mbus URL requires credentials") | ||
| } | ||
| password, present := u.User.Password() |
There was a problem hiding this comment.
Codex agent review — P2: Reject usernames containing a colon before emitting a verifier. For example, https://user%3Aextra:password@host:6868 parses successfully here, but the verifier branch in requestNotAuthorized uses request.BasicAuth(), which splits decoded credentials at the first colon. It reads username user, while the configured username is user:extra, so the original credentials always receive 401. The previous whole-header comparison accepted that same configuration. A sanitized validation error here would prevent creating an unreachable agent; cover this boundary in the Ginkgo specs.
|
Linting is failing, you need to run goimports most likely |
|
Codex agent here. Fixed the two goimports failures and pushed the correction. Used the repository-pinned formatter on every changed Go file in the CLI and agent PRs; its formatting check now reports no files. |
create-env passes cloud_provider.properties.agent.mbus to the CPI. The CPI writes it into IaaS VM metadata, so the Director agent's Basic Auth password ends up readable by anyone with metadata access. When the stemcell's stemcell.MF lists the http-password-hmac-sha256 agent feature, replace the password in agent.mbus, and in any resource pool env.bosh.mbus.urls, with a salted HMAC-SHA256 verifier from bosh-agent's agentpassword package before installing the CPI. The CLI keeps using the plaintext cloud_provider.mbus to talk to the agent, so only the copy that reaches the VM is hashed. Hashing happens after the "no changes" check, and that check uses a manifest SHA computed before hashing, so the random salt does not force a redeploy. Compatibility: - New CLI, stemcell without the feature: nothing is hashed. - Old CLI, stemcell with the feature: plaintext still works, because the agent accepts both forms. ai-assisted=yes TNZ-129825 Co-Authored-By: Chris Selzo <chris.selzo@broadcom.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ce38d11 to
d40661e
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The required tagged bosh-agent release is unavailable, and the pinned draft API has already changed upstream.
1 open finding
What changed in this PR
Hardens create-env by replacing agent passwords in VM metadata with feature-gated HMAC-SHA256 verifiers.
Changes:
- Adds stemcell agent-feature detection.
- Hashes CPI and resource-pool HTTPS mbus passwords while retaining plaintext client credentials.
- Adds tests and vendors the bosh-agent hashing package.
| File | Description |
|---|---|
cmd/agent_password.go |
Implements metadata password hashing. |
cmd/agent_password_test.go |
Tests hashing helpers and errors. |
cmd/create_env_test.go |
Tests feature-gated create-env behavior. |
cmd/deployment_preparer.go |
Applies hashing after change detection. |
stemcell/stemcell.go |
Exposes advertised agent features. |
stemcell/agent_features_test.go |
Tests feature parsing and preservation. |
go.mod |
Adds the bosh-agent pseudo-version dependency. |
go.sum |
Updates dependency checksums. |
vendor/modules.txt |
Registers the vendored package. |
vendor/github.com/cloudfoundry/bosh-agent/v2/agentpassword/agentpassword.go |
Vendors verifier generation logic. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| code.cloudfoundry.org/workpool v0.0.0-20250911194158-1489753f182e | ||
| github.com/cheggaaa/pb/v3 v3.2.1 | ||
| github.com/cloudfoundry/bosh-agent/v2 v2.898.0 | ||
| github.com/cloudfoundry/bosh-agent/v2 v2.900.1-0.20261009041322-881bed56c8e2 |
Update the agent dependency and tracked vendor copy together with the parser references in the command specs. This brings the shared password-length validation into create-env. The pseudo-version is for draft integration only; before merge, replace it with the tagged agent release containing these changes and regenerate checksums and vendor metadata.
|
Codex agent here. Re the dependency review comment: Updated the draft dependency to 50adbab21, regenerated go.sum/vendor, and changed the specs to ParseHashedPassword in 25cd17c. The affected specs compile. The tagged-release prerequisite remains outstanding before merge; this draft pin is only for reviewing integration, so I am leaving this thread open. |
Use Ginkgo table entries so each metadata case reports separately. Detection and preservation during repacking are distinct behaviors and get separate specs. Clarify that absent capabilities return false; create-env then retains its existing plaintext credential behavior.
|
Codex agent here. Feature specs now use separate Ginkgo tables for detection and serialization. Absent capabilities return false, so create-env skips hashing and keeps the original password. The specs compile. Posting here while the review is pending. |
|
@codex security review |
|
To use Codex here, create a Codex account and connect to github. |

Why
create-envputscloud_provider.properties.agent.mbus, which holds the agent's Basic Auth password, into IaaS VM metadata via the CPI.What
stemcell.MFhasagent_featurescontaininghttp-password-hmac-sha256, the CLI replaces the password in two places with a salted HMAC-SHA256 verifier from bosh-agent'sagentpasswordpackage:cloud_provider.properties.agent.mbusenv.bosh.mbus.urlscloud_provider.mbusfor its own connection to the agent; only the copy sent to the VM is hashed.Dependency
github.com/cloudfoundry/bosh-agent/v2/agentpassword.go.modcurrently points at thebosh upload-stemcellpanics if authentication with UAA fails #487 commit as a pseudo-version. Do not merge until it is bumped to a tagged bosh-agent release that containsbosh upload-stemcellpanics if authentication with UAA fails #487.Release ordering
Tests
New tests:
cmd/agent_password_test.go: the two hashing helpers, including absent paths and wrong-type errors.cmd/create_env_test.go: with the feature, the CPI installer receives the hashedagent.mbuswhile the agent client gets the plaintext mbus URL; without the feature, nothing changes.Note: unset any
BOSH_*environment variables (e.g.BOSH_ALL_PROXY) before runningcmdtests locally. Unrelated curl/session specs fail when they are set.Related
🤖 Generated with Claude Code