Add shared resolved credential forwarding
This commit is contained in:
@@ -216,7 +216,10 @@ downstream model-profile concepts.
|
||||
|
||||
## Stage 2: Add shared resolved-credential forwarding
|
||||
|
||||
Status: Not started.
|
||||
Status: Complete (2026-09-25).
|
||||
|
||||
Verification: `go test ./internal/adapters/subprocess`,
|
||||
`go test -race ./internal/adapters/subprocess`, and `git diff --check` passed.
|
||||
|
||||
Preparation: `internal/adapters/subprocess/run.go`, its environment/redaction
|
||||
helpers and tests; `internal/adapters/notarius/subprocess.go`;
|
||||
|
||||
29
internal/adapters/subprocess/credentials.go
Normal file
29
internal/adapters/subprocess/credentials.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package subprocess
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
||||
)
|
||||
|
||||
// CredentialEnvironment returns captured secret values and names for a child
|
||||
// invocation. References must already have been resolved by ConfigKit.
|
||||
func CredentialEnvironment(credentials []configkit.Secret) (map[string]string, []string, error) {
|
||||
if len(credentials) == 0 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
overrides := make(map[string]string, len(credentials))
|
||||
names := make([]string, 0, len(credentials))
|
||||
for _, credential := range credentials {
|
||||
name := credential.EnvName()
|
||||
value := credential.Value()
|
||||
if !credential.IsResolved() || value == "" {
|
||||
return nil, nil, fmt.Errorf("credential %q must be resolved and nonempty", name)
|
||||
}
|
||||
if _, exists := overrides[name]; !exists {
|
||||
names = append(names, name)
|
||||
overrides[name] = value
|
||||
}
|
||||
}
|
||||
return overrides, names, nil
|
||||
}
|
||||
51
internal/adapters/subprocess/credentials_test.go
Normal file
51
internal/adapters/subprocess/credentials_test.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package subprocess
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
||||
)
|
||||
|
||||
func TestCredentialEnvironmentUsesCapturedReferences(t *testing.T) {
|
||||
t.Setenv("CUSTOM_ALPHA_KEY", "alpha-value")
|
||||
t.Setenv("SECOND_PROVIDER_TOKEN", "second-value")
|
||||
t.Setenv("UNSELECTED_SECRET", "unselected-value")
|
||||
type configuration struct {
|
||||
Credentials []configkit.Secret `yaml:"credentials"`
|
||||
}
|
||||
loaded, err := configkit.Load[configuration](configkit.Bytes("credentials.yml", []byte("credentials: [CUSTOM_ALPHA_KEY, SECOND_PROVIDER_TOKEN, CUSTOM_ALPHA_KEY]\n")))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Setenv("CUSTOM_ALPHA_KEY", "later-value")
|
||||
overrides, names, err := CredentialEnvironment(loaded.Config.Credentials)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(overrides, map[string]string{"CUSTOM_ALPHA_KEY": "alpha-value", "SECOND_PROVIDER_TOKEN": "second-value"}) ||
|
||||
!reflect.DeepEqual(names, []string{"CUSTOM_ALPHA_KEY", "SECOND_PROVIDER_TOKEN"}) {
|
||||
t.Fatalf("credential selection = %#v, %#v", overrides, names)
|
||||
}
|
||||
overrides["CUSTOM_ALPHA_KEY"] = "modified"
|
||||
names[0] = "modified"
|
||||
again, againNames, err := CredentialEnvironment(loaded.Config.Credentials)
|
||||
if err != nil || again["CUSTOM_ALPHA_KEY"] != "alpha-value" || againNames[0] != "CUSTOM_ALPHA_KEY" {
|
||||
t.Fatalf("credential conversion retained mutable result: %#v, %#v, %v", again, againNames, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCredentialEnvironmentHandlesEmptyAndUnresolvedReferences(t *testing.T) {
|
||||
for _, credentials := range [][]configkit.Secret{nil, {}} {
|
||||
overrides, names, err := CredentialEnvironment(credentials)
|
||||
if err != nil || len(overrides) != 0 || len(names) != 0 {
|
||||
t.Fatalf("empty credentials = %#v, %#v, %v", overrides, names, err)
|
||||
}
|
||||
}
|
||||
for _, credentials := range [][]configkit.Secret{{configkit.SecretEnv("UNRESOLVED_KEY")}, {{}}} {
|
||||
overrides, names, err := CredentialEnvironment(credentials)
|
||||
if err == nil || overrides != nil || names != nil {
|
||||
t.Fatalf("unresolved credentials = %#v, %#v, %v", overrides, names, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user