Conversation
| } | ||
|
|
||
| func (b *BuilderHub) GetConfigWithSecrets(ctx context.Context, builderName string) ([]byte, error) { | ||
| _, err := b.dataAccessor.GetActiveConfigForBuilder(ctx, builderName) |
There was a problem hiding this comment.
@metachris Could you confirm if this was intentional or not? The config was set but never returned as part of responses along with the secrets - now that's fixed. I'd be happy to revert the changes for this bug fix if we think that config should be deprecated in favor of secrets.
There was a problem hiding this comment.
It is kind of intentional but prob long overdue to remove/change. @bakhtin config in postgres is empty, right? all the data is in secrets
| @@ -1,22 +1,24 @@ | |||
| // Package secrets contains logic for adapter to aws secrets manager | |||
| // Package secrets implements secrets storage backends | |||
There was a problem hiding this comment.
rename this file something like aws_secrets_*? seems it's only for aws secrets now?
There was a problem hiding this comment.
I need to make some changes to the file for consistency and git thinks that I've created a new file entirely if I rename it, too, so wanted to avoid renaming for now. (I agree about renaming).
cmd/httpserver/main.go
Outdated
| Name: "secret-prefix", | ||
| Value: "", | ||
| Usage: "AWS Secret name", | ||
| Usage: "AWS Secret name prefix (use with --aws-secrets)", |
There was a problem hiding this comment.
is --aws-secrets new? couldn't find another reference to it in this PR
There was a problem hiding this comment.
No, this is a leftover from the local work in progress - removing!
adapters/secrets/hashicorp_vault.go
Outdated
|
|
||
| type VaultConfig struct { | ||
| Address string // Vault server address (e.g., http://localhost:8200) | ||
| Token string // Vault token for authentication |
There was a problem hiding this comment.
Please also support https://pkg.go.dev/github.com/hashicorp/vault/api/auth/kubernetes as an auth method in addition to plain token, as that's how pods authenticate in our Vault
There was a problem hiding this comment.
Added! Please let me know if you have any suggestions.
There was a problem hiding this comment.
Pull request overview
Integrates HashiCorp Vault as an additional secrets storage backend for BuilderHub, updates secret-access APIs to be context-aware, and fixes config+secrets responses by merging stored builder config with secrets.
Changes:
- Add a Vault-backed secrets adapter and wire Vault configuration/selection into the HTTP server CLI.
- Fix “config never returned after set” by merging builder config with secret JSON in both builder and admin “full config” endpoints.
- Update local docker-compose and CI integration tests to run with Vault enabled.
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/ci/integration-test.sh | Stops previous compose stack and tweaks hurl invocation for CI/integration runs. |
| scripts/ci/e2e-test.hurl | Extends E2E assertions to ensure non-secret config is preserved alongside secrets. |
| ports/admin_handler.go | Updates secrets API to be context-aware and returns merged config+secrets for “full” config endpoint. |
| cmd/httpserver/main.go | Adds Vault CLI flags/env vars and selects secrets backend (mock/vault/aws). |
| adapters/secrets/hashicorp_vault.go | New Vault KV v2 secrets backend implementation. |
| adapters/secrets/service.go | Refactors AWS Secrets Manager adapter (naming + context-aware API) and aligns missing-secret error. |
| application/service.go | Introduces MergeJSON and updates config-with-secrets flow to return merged payload. |
| domain/inmemory_secret.go | Updates mock secrets service to accept context. |
| docker/docker-compose.yaml | Adds Vault dev container and configures builder-hub to use Vault in local compose. |
| docker/mock-proxy/Dockerfile | Adjusts COPY to match new build context. |
| .github/workflows/release.yaml | Updates proxy image build context/Dockerfile path for releases. |
| Makefile | Adds a docker-compose restart helper target. |
| go.mod / go.sum | Adds Vault client dependencies and updates module requirements. |
Comments suppressed due to low confidence (1)
scripts/ci/integration-test.sh:36
- The script disables
set -earound thehurlrun, but then checks$?only afterset -ehas been re-enabled. That means the failure check is reading the exit status ofset -e(almost always 0), so integration test failures won’t be detected and the script can report success incorrectly. Capture thehurlexit code immediately (or use anif ! hurl ...; then ... fipattern) before re-enablingset -e.
hurl --test scripts/ci/e2e-test.hurl -v
set -e
# Cleanup after tests
if [ $? -ne 0 ]; then
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cmd/httpserver/main.go
Outdated
| } else if vaultEnabled && vaultToken != "" { | ||
| log.Info("using HashiCorp Vault for secrets", | ||
| "address", vaultAddress, | ||
| "secret_path", vaultSecretPath, | ||
| "mount_path", vaultMountPath) |
There was a problem hiding this comment.
When --vault-enabled is set but --vault-token is empty, this branch is skipped and the code silently falls through to another backend (AWS or in-memory). That contradicts the flag’s "overrides" semantics and makes misconfiguration easy to miss. Consider failing fast (return an error) when vault-enabled is true but required Vault settings (at least token) are missing.
cmd/httpserver/main.go
Outdated
| } else { | ||
| log.Warn("no secrets backend configured - using mock in-memory storage", | ||
| "vault-enabled", vaultEnabled, | ||
| "secret-prefix-length", len(cCtx.String("secret-prefix"))) | ||
| sm = domain.NewMockSecretService() |
There was a problem hiding this comment.
Falling back to the in-memory secrets service when no backend is configured is a high-risk default: it can cause secrets written via the admin API to be lost on restart and may mask production misconfiguration. Prefer returning an error unless --mock-secrets is explicitly enabled (or at least gate this fallback behind a clearly-dev-only flag/env).
| // Verify connection by attempting a read (404 is fine — path may not exist yet) | ||
| ctx := context.Background() | ||
| _, verifyErr := client.Secrets.KvV2Read(ctx, cfg.SecretPrefix, vault.WithMountPath(cfg.MountPath)) | ||
| if verifyErr != nil && !isVault404(verifyErr) { | ||
| return nil, fmt.Errorf("failed to verify Vault connection: %w", verifyErr) | ||
| } |
There was a problem hiding this comment.
NewHashicorpVaultService verifies connectivity using context.Background() with no timeout. If Vault is unreachable or DNS hangs, startup can block indefinitely. Use a context with timeout/deadline for the verification call (and consider making verification optional).
| func MergeJSON(base, override json.RawMessage) (json.RawMessage, error) { | ||
| result := make(map[string]json.RawMessage) | ||
| if err := json.Unmarshal(base, &result); err != nil { | ||
| return nil, fmt.Errorf("failed to unmarshal base: %w", err) | ||
| } |
There was a problem hiding this comment.
MergeJSON is new core behavior used to serve builder configs (config + secrets), but there are no unit tests covering merge behavior or error cases (invalid JSON, key collisions, etc.). Add focused tests (e.g., in application/service_test.go) to lock in the intended semantics.
scripts/ci/e2e-test.hurl
Outdated
| @@ -40,6 +40,9 @@ HTTP 200 | |||
| # [Admin API] Create an empty builder configuration | |||
There was a problem hiding this comment.
This step is labeled as creating an "empty" builder configuration, but the payload now includes foo.bar. Update the comment to reflect that this request sets non-empty config data (or revert to an empty object if that was the intent).
| # [Admin API] Create an empty builder configuration | |
| # [Admin API] Create an initial builder configuration with test data |
| config, err := s.builderService.GetActiveConfigForBuilder(r.Context(), builderName) | ||
| if err != nil { | ||
| s.log.Error("failed to get config with secrets", "error", err) | ||
| s.log.Error("failed to get config for builder", "error", err) | ||
| w.WriteHeader(http.StatusInternalServerError) | ||
| return |
There was a problem hiding this comment.
GetFullConfigForBuilder treats any error from GetActiveConfigForBuilder as a 500. For consistency with GetActiveConfigForBuilder (which maps domain.ErrNotFound to 404), consider handling domain.ErrNotFound here as well so missing builders/configs return 404 rather than 500.
cmd/httpserver/main.go
Outdated
| Name: "secret-prefix", | ||
| Value: "", | ||
| Usage: "AWS Secret name", | ||
| Usage: "AWS Secret name prefix (use with --aws-secrets)", |
There was a problem hiding this comment.
The flag help text mentions --aws-secrets, but no such CLI flag exists in this binary. Update the Usage string to reference the actual flag/env var (--secret-prefix / AWS_BUILDER_CONFIGS_SECRET_PREFIX) to avoid confusing operators.
| Usage: "AWS Secret name prefix (use with --aws-secrets)", | |
| Usage: "AWS Secret name prefix for configs (env: AWS_BUILDER_CONFIGS_SECRET_PREFIX)", |
📝 Summary
✅ I have run these commands
make lintmake testgo mod tidy