Skip to content

fix: resolve default/profile client credential conflict from env vars#44

Open
piotrek-janus wants to merge 2 commits into
masterfrom
fix/profile-default-client-env-conflict
Open

fix: resolve default/profile client credential conflict from env vars#44
piotrek-janus wants to merge 2 commits into
masterfrom
fix/profile-default-client-env-conflict

Conversation

@piotrek-janus

Copy link
Copy Markdown
Contributor

Problem

When both the default client and a profile client were configured through environment variables, the profile silently used the default client's credentials instead of its own. Reported in practice when CLIENT_* (default) and PROFILES_<NAME>_CLIENT_* (profile) were all set via env.

Root cause

Two coupled defects in internal/cac/config/config.go:

  1. Profile client env vars were never read. viper's AutomaticEnv/BindEnv values do not merge into nested maps (profiles.<name>.client.*) that originate from a config file during Unmarshal, so PROFILES_<NAME>_CLIENT_* was ignored — the profile had no client of its own.
  2. Pointer aliasing on fallback. A profile without its own client fell back to the default client by sharing the same *Configuration pointer in SetImplicitValues, so it inherited the default's env-set credentials and was mutation-aliased to it.

Fix

  • For each known profile, bind every default config key to its env variable and, when set, promote it into viper's explicit override layer (v.Set), which is deep-merged on Unmarshal.
  • Deep-copy the default sub-configs (client/logging/storage) on fallback in SetImplicitValues instead of sharing pointers.
  • Use an isolated viper.New() instance instead of the global viper.GetViper() singleton, so repeated InitConfig calls don't leak explicit overrides into each other. Nothing else in the repo uses the global instance.

Tests

Added two tests (and a fixture testdata/profile_env_conflict.yaml) that previously failed and now pass:

  • profile client from env does not collide with default client from env — both clients set via env; profile must use its own credentials.
  • profile without client is not aliased to the default client — fallback must produce an independent copy, not a shared pointer.

go build ./..., go vet, and the full go test ./... suite pass.

When both the default client and a profile client are configured through
environment variables, the profile silently uses the default client's
credentials instead of its own. Two coupled defects cause this:

- profile client env vars (PROFILES_<NAME>_CLIENT_*) are never read, so
  the profile has no client of its own
- a profile without its own client falls back to the default client by
  sharing the same pointer, so it inherits the default's credentials and
  is aliased to it

Add two failing tests (and a fixture) that assert the correct behavior to
document the bug.
Two coupled defects caused a profile to silently use the default client's
credentials when both were configured via environment variables:

- profile client env vars (PROFILES_<NAME>_CLIENT_*) were never read, so a
  profile had no client of its own
- a profile without its own client fell back to the default client by sharing
  the same pointer, aliasing the two configs

Fixes:

- bind each default config key per profile and promote any set profile env
  var into viper's explicit override layer, which is deep-merged on Unmarshal
  (AutomaticEnv/BindEnv values otherwise do not merge into nested maps that
  originate from a config file)
- deep-copy the default sub-configs on fallback in SetImplicitValues so
  profiles never share or mutate the default's objects
- use an isolated viper instance instead of the global singleton so repeated
  InitConfig calls do not leak explicit overrides into each other

The previously failing tests now pass.
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