diff --git a/.golangci.yml b/.golangci.yml index d0643633741..fbbc8d7f13c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -20,6 +20,7 @@ linters: - depguard - errcheck - errorlint + - forbidigo - gofmt - goimports - gosec @@ -33,6 +34,15 @@ linters: - unconvert - unparam - whitespace +linters-settings: + forbidigo: + # Forbid using os.Getenv and os.LookupEnv with COSIGN_ variables in favor of + # pkg/cosign/env package + # Reference: https://github.com/sigstore/cosign/issues/2236 + forbid: + - 'os\.Getenv.*' + - 'os\.LookupEnv.*' + exclude_godoc_examples: false output: uniq-by-line: false issues: @@ -41,6 +51,14 @@ issues: linters: - errcheck - gosec + # We want to allow using os.Getenv and os.Setenv in tests because it + # might be easier (and needed in some cases) + - forbidigo + # pkg/cosign/env implements working with environment variables in cosign + # and is based on os.Getenv and os.LookupEnv + - path: pkg/cosign/env + linters: + - forbidigo max-issues-per-linter: 0 max-same-issues: 0 run: diff --git a/cmd/cosign/cli/env.go b/cmd/cosign/cli/env.go index 099fab3c003..c1c58daa353 100644 --- a/cmd/cosign/cli/env.go +++ b/cmd/cosign/cli/env.go @@ -18,41 +18,129 @@ package cli import ( "fmt" "os" + "sort" "strings" "github.com/spf13/cobra" + + "github.com/sigstore/cosign/cmd/cosign/cli/options" + "github.com/sigstore/cosign/pkg/cosign/env" ) func Env() *cobra.Command { - return &cobra.Command{ + o := &options.EnvOptions{} + + cmd := &cobra.Command{ Use: "env", Short: "Prints Cosign environment variables", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - for _, e := range getEnv() { - fmt.Println(e) - } + envVars := env.EnvironmentVariables() + printEnv(envVars, getEnv(), getEnviron(), o.ShowDescriptions, o.ShowSensitiveValues) + return nil }, } + + o.AddFlags(cmd) + return cmd +} + +// NB: the purpose of those types and functions is to make it possible to swap function for testing purposes +type envGetter func(env.Variable) string +type environGetter func() []string + +func getEnv() envGetter { + return env.Getenv +} +func getEnviron() environGetter { + return os.Environ } -func getEnv() []string { - out := []string{} - for _, e := range os.Environ() { +// NB: printEnv intentionally takes map of env vars to make it easier to unit test it +func printEnv(envVars map[env.Variable]env.VariableOpts, + envGet envGetter, + environGet environGetter, + showDescription, showSensitive bool) { + // Sort keys to print them in a predictable order + keys := sortEnvKeys(envVars) + + // Print known/registered environment variables + for _, e := range keys { + opts := envVars[e] + + // Get value of environment variable + val := envGet(e) + + // If showDescription is set, print description for that variable + if showDescription { + fmt.Printf("# %s %s\n", e.String(), opts.Description) + fmt.Printf("# Expects: %s\n", opts.Expects) + } + + // If variable is sensitive, and we don't want to show sensitive values, + // print environment variable name and some asterisk symbols. + // If sensitive variable isn't set or doesn't have any value, we'll just + // print like non-sensitive variable + if opts.Sensitive && !showSensitive && val != "" { + fmt.Printf("%s=******\n", e.String()) + } else { + fmt.Printf("%s=%s\n", e.String(), val) + } + } + + // Print not registered environment variables + nonRegEnv := map[string]string{} + for _, e := range environGet() { // Prefixes to look for. err on the side of showing too much rather // than too little. We'll only output things that have values set. for _, prefix := range []string{ + // We want to print eventually non-registered cosign variables (even if this shouldn't happen) "COSIGN_", // Can modify Sigstore/TUF client behavior - https://github.com/sigstore/sigstore/blob/35d6a82c15183f7fe7a07eca45e17e378aa32126/pkg/tuf/client.go#L52 "SIGSTORE_", "TUF_", } { if strings.HasPrefix(e, prefix) { - out = append(out, e) - continue + // os.Environ returns key=value pairs, so we split by = + envSplit := strings.Split(e, "=") + key := envSplit[0] + + // Skip registered environment variables (those are already printed above) + if _, ok := envVars[env.Variable(key)]; ok { + continue + } + + val := "" + if len(envSplit) == 2 { + val = envSplit[1] + } + + nonRegEnv[key] = val } } } - return out + if len(nonRegEnv) > 0 && showDescription { + fmt.Println("# Environment variables below are not registered with cosign,\n# but might still influence cosign's behavior.") + } + for key, val := range nonRegEnv { + if !showSensitive && val != "" { + fmt.Printf("%s=******\n", key) + } else { + fmt.Printf("%s=%s\n", key, val) + } + } +} + +func sortEnvKeys(envVars map[env.Variable]env.VariableOpts) []env.Variable { + keys := []env.Variable{} + for k := range envVars { + keys = append(keys, k) + } + + sort.Slice(keys, func(i, j int) bool { + return strings.Compare(keys[i].String(), keys[j].String()) < 0 + }) + + return keys } diff --git a/cmd/cosign/cli/env_test.go b/cmd/cosign/cli/env_test.go index 57d7f10a083..0f2864ad12e 100644 --- a/cmd/cosign/cli/env_test.go +++ b/cmd/cosign/cli/env_test.go @@ -16,22 +16,289 @@ package cli import ( + "fmt" + "io" "os" "testing" - "github.com/google/go-cmp/cmp" + "github.com/sigstore/cosign/pkg/cosign/env" ) -func TestGetEnv(t *testing.T) { - os.Setenv("COSIGN_EXPERIMENTAL", "foo") - os.Setenv("TUF_ROOT", "bar") - got := getEnv() - want := []string{ - "COSIGN_EXPERIMENTAL=foo", - "TUF_ROOT=bar", +const ( + VariableTest1 env.Variable = "COSIGN_TEST1" + VariableTest2 env.Variable = "COSIGN_TEST2" + VariableTest3 env.Variable = "COSIGN_TEST3" + + expectedWithoutDescription = `COSIGN_TEST1=abcd +COSIGN_TEST2= +` + expectedWithDescription = `# COSIGN_TEST1 is the first test variable +# Expects: test1 value +COSIGN_TEST1=abcd +# COSIGN_TEST2 is the second test variable +# Expects: test2 value +COSIGN_TEST2= +` + + expectedWithHiddenSensitive = `# COSIGN_TEST1 is the first test variable +# Expects: test1 value +COSIGN_TEST1=abcd +# COSIGN_TEST2 is the second test variable +# Expects: test2 value +COSIGN_TEST2=****** +` + + expectedWithSensitive = `# COSIGN_TEST1 is the first test variable +# Expects: test1 value +COSIGN_TEST1=abcd +# COSIGN_TEST2 is the second test variable +# Expects: test2 value +COSIGN_TEST2=1234 +` + + expectedSensitiveWithoutDescription = `COSIGN_TEST1=abcd +COSIGN_TEST2=1234 +` + + expectedWithNonRegisteredEnv = `# COSIGN_TEST1 is the first test variable +# Expects: test1 value +COSIGN_TEST1=abcd +# COSIGN_TEST2 is the second test variable +# Expects: test2 value +COSIGN_TEST2= +# Environment variables below are not registered with cosign, +# but might still influence cosign's behavior. +COSIGN_TEST3=****** +` + + expectedWithNonRegisteredEnvSensitive = `# COSIGN_TEST1 is the first test variable +# Expects: test1 value +COSIGN_TEST1=abcd +# COSIGN_TEST2 is the second test variable +# Expects: test2 value +COSIGN_TEST2= +# Environment variables below are not registered with cosign, +# but might still influence cosign's behavior. +COSIGN_TEST3=abcd +` + + expectedWithNonRegisteredEnvNoDesc = `COSIGN_TEST1=abcd +COSIGN_TEST2= +COSIGN_TEST3=****** +` + + expectedWithNonRegisteredEnvNoDescSensitive = `COSIGN_TEST1=abcd +COSIGN_TEST2= +COSIGN_TEST3=abcd +` + + expectedWithNonRegisteredEnvNoDescEmpty = `COSIGN_TEST1=abcd +COSIGN_TEST2= +COSIGN_TEST3= +` +) + +var ( + testingEnvVars = map[string]string{} +) + +func tGetEnv() envGetter { + return func(key env.Variable) string { + return testingEnvVars[key.String()] } +} +func tGetEnviron() environGetter { + return func() []string { + var s []string + + for k, v := range testingEnvVars { + s = append(s, fmt.Sprintf("%s=%s", k, v)) + } + + return s + } +} + +func TestPrintEnv(t *testing.T) { + variables := map[env.Variable]env.VariableOpts{ + VariableTest1: { + Description: "is the first test variable", + Expects: "test1 value", + Sensitive: false, + }, + VariableTest2: { + Description: "is the second test variable", + Expects: "test2 value", + Sensitive: true, + }, + } + + tests := []struct { + name string + environmentVariables map[string]string + registeredVariables map[env.Variable]env.VariableOpts + showDescriptions bool + showSensitiveValues bool + expectedOutput string + }{ + { + name: "no descriptions and sensitive variables", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + }, + registeredVariables: variables, + showDescriptions: false, + showSensitiveValues: false, + expectedOutput: expectedWithoutDescription, + }, + { + name: "descriptions but sensitive variable is unset", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + }, + registeredVariables: variables, + showDescriptions: true, + showSensitiveValues: false, + expectedOutput: expectedWithDescription, + }, + { + name: "sensitive variable is non-empty but show sensitive variables is disabled", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "1234", + }, + registeredVariables: variables, + showDescriptions: true, + showSensitiveValues: false, + expectedOutput: expectedWithHiddenSensitive, + }, + { + name: "sensitive variable is empty", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + }, + registeredVariables: variables, + showDescriptions: true, + showSensitiveValues: true, + expectedOutput: expectedWithDescription, + }, + { + name: "sensitive variable is non-empty and show sensitive variables is enabled", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "1234", + }, + registeredVariables: variables, + showDescriptions: true, + showSensitiveValues: true, + expectedOutput: expectedWithSensitive, + }, + { + name: "sensitive variable is non-empty but show descriptions is disabled", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "1234", + }, + registeredVariables: variables, + showDescriptions: false, + showSensitiveValues: true, + expectedOutput: expectedSensitiveWithoutDescription, + }, + { + name: "print unregistered variable with description", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + "COSIGN_TEST3": "abcd", + }, + registeredVariables: variables, + showDescriptions: true, + showSensitiveValues: false, + expectedOutput: expectedWithNonRegisteredEnv, + }, + { + name: "print unregistered variable with description (sensitive enabled)", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + "COSIGN_TEST3": "abcd", + }, + registeredVariables: variables, + showDescriptions: true, + showSensitiveValues: true, + expectedOutput: expectedWithNonRegisteredEnvSensitive, + }, + { + name: "print unregistered variable without description", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + "COSIGN_TEST3": "abcd", + }, + registeredVariables: variables, + showDescriptions: false, + showSensitiveValues: false, + expectedOutput: expectedWithNonRegisteredEnvNoDesc, + }, + { + name: "print unregistered variable without description (sensitive enabled)", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + "COSIGN_TEST3": "abcd", + }, + registeredVariables: variables, + showDescriptions: false, + showSensitiveValues: true, + expectedOutput: expectedWithNonRegisteredEnvNoDescSensitive, + }, + { + name: "print empty unregistered variable", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + "COSIGN_TEST3": "", + }, + registeredVariables: variables, + showDescriptions: false, + showSensitiveValues: false, + expectedOutput: expectedWithNonRegisteredEnvNoDescEmpty, + }, + { + name: "print empty unregistered variable (sensitive enabled)", + environmentVariables: map[string]string{ + "COSIGN_TEST1": "abcd", + "COSIGN_TEST2": "", + "COSIGN_TEST3": "", + }, + registeredVariables: variables, + showDescriptions: false, + showSensitiveValues: false, + expectedOutput: expectedWithNonRegisteredEnvNoDescEmpty, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Set needed environment variables + testingEnvVars = tt.environmentVariables + + orgStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + printEnv(tt.registeredVariables, tGetEnv(), tGetEnviron(), tt.showDescriptions, tt.showSensitiveValues) + + w.Close() + out, _ := io.ReadAll(r) + os.Stdout = orgStdout - if diff := cmp.Diff(got, want); diff != "" { - t.Error(diff) + if tt.expectedOutput != string(out) { + t.Errorf("Expected to get %q\n, but got %q", tt.expectedOutput, string(out)) + } + }) } } diff --git a/cmd/cosign/cli/fulcio/fulcioverifier/ctl/verify.go b/cmd/cosign/cli/fulcio/fulcioverifier/ctl/verify.go index 38287ab3e0d..0189e0e7c90 100644 --- a/cmd/cosign/cli/fulcio/fulcioverifier/ctl/verify.go +++ b/cmd/cosign/cli/fulcio/fulcioverifier/ctl/verify.go @@ -28,6 +28,7 @@ import ( ctx509 "github.com/google/certificate-transparency-go/x509" "github.com/google/certificate-transparency-go/x509util" "github.com/sigstore/cosign/cmd/cosign/cli/fulcio/fulcioverifier/ctutil" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/tuf" @@ -36,10 +37,6 @@ import ( // This is the CT log public key target name var ctPublicKeyStr = `ctfe.pub` -// Setting this env variable will over ride what is used to validate -// the SCT coming back from Fulcio. -const altCTLogPublicKeyLocation = "SIGSTORE_CT_LOG_PUBLIC_KEY_FILE" - // logIDMetadata holds information for mapping a key ID hash (log ID) to associated data. type logIDMetadata struct { pubKey crypto.PublicKey @@ -74,7 +71,7 @@ func ContainsSCT(cert []byte) (bool, error) { func VerifySCT(ctx context.Context, certPEM, chainPEM, rawSCT []byte) error { // fetch SCT verification key pubKeys := make(map[[sha256.Size]byte]logIDMetadata) - rootEnv := os.Getenv(altCTLogPublicKeyLocation) + rootEnv := env.Getenv(env.VariableSigstoreCTLogPublicKeyFile) if rootEnv == "" { tufClient, err := tuf.NewFromEnv(ctx) if err != nil { diff --git a/cmd/cosign/cli/generate/generate_key_pair.go b/cmd/cosign/cli/generate/generate_key_pair.go index 72365713076..80a0fbe2c10 100644 --- a/cmd/cosign/cli/generate/generate_key_pair.go +++ b/cmd/cosign/cli/generate/generate_key_pair.go @@ -24,6 +24,7 @@ import ( "os" "strings" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/cosign/pkg/cosign/git" "github.com/sigstore/cosign/pkg/cosign/git/github" "github.com/sigstore/cosign/pkg/cosign/git/gitlab" @@ -123,7 +124,7 @@ func GetPass(confirm bool) ([]byte, error) { } func readPasswordFn(confirm bool) func() ([]byte, error) { - pw, ok := os.LookupEnv("COSIGN_PASSWORD") + pw, ok := env.LookupEnv(env.VariablePassword) switch { case ok: return func() ([]byte, error) { diff --git a/cmd/cosign/cli/importkeypair/import_key_pair.go b/cmd/cosign/cli/importkeypair/import_key_pair.go index cdcb0a01e3a..3dbcad8a69c 100644 --- a/cmd/cosign/cli/importkeypair/import_key_pair.go +++ b/cmd/cosign/cli/importkeypair/import_key_pair.go @@ -23,6 +23,7 @@ import ( icos "github.com/sigstore/cosign/internal/pkg/cosign" "github.com/sigstore/cosign/pkg/cosign" + "github.com/sigstore/cosign/pkg/cosign/env" ) var ( @@ -74,7 +75,7 @@ func GetPass(confirm bool) ([]byte, error) { } func readPasswordFn(confirm bool) func() ([]byte, error) { - pw, ok := os.LookupEnv("COSIGN_PASSWORD") + pw, ok := env.LookupEnv(env.VariablePassword) switch { case ok: return func() ([]byte, error) { diff --git a/cmd/cosign/cli/options/env.go b/cmd/cosign/cli/options/env.go new file mode 100644 index 00000000000..71ebdcb83b0 --- /dev/null +++ b/cmd/cosign/cli/options/env.go @@ -0,0 +1,37 @@ +// +// Copyright 2022 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package options + +import ( + "github.com/spf13/cobra" +) + +// EnvOptions is the top level wrapper for the env command. +type EnvOptions struct { + ShowDescriptions bool + ShowSensitiveValues bool +} + +var _ Interface = (*EnvOptions)(nil) + +// AddFlags implements Interface +func (o *EnvOptions) AddFlags(cmd *cobra.Command) { + cmd.Flags().BoolVar(&o.ShowDescriptions, "show-descriptions", true, + "show descriptions for environment variables") + + cmd.Flags().BoolVar(&o.ShowSensitiveValues, "show-sensitive-values", false, + "show values of sensitive environment variables") +} diff --git a/cmd/cosign/cli/options/experimental.go b/cmd/cosign/cli/options/experimental.go index 5d6bbcaf497..190d54417fb 100644 --- a/cmd/cosign/cli/options/experimental.go +++ b/cmd/cosign/cli/options/experimental.go @@ -15,16 +15,13 @@ package options import ( - "os" "strconv" -) -const ( - ExperimentalEnv = "COSIGN_EXPERIMENTAL" + "github.com/sigstore/cosign/pkg/cosign/env" ) func EnableExperimental() bool { - if b, err := strconv.ParseBool(os.Getenv(ExperimentalEnv)); err == nil { + if b, err := strconv.ParseBool(env.Getenv(env.VariableExperimental)); err == nil { return b } return false diff --git a/cmd/cosign/cli/pkcs11cli/commands.go b/cmd/cosign/cli/pkcs11cli/commands.go index 60f859fda8e..0e26f697d1b 100644 --- a/cmd/cosign/cli/pkcs11cli/commands.go +++ b/cmd/cosign/cli/pkcs11cli/commands.go @@ -28,6 +28,7 @@ import ( "syscall" "github.com/miekg/pkcs11" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/cosign/pkg/cosign/pkcs11key" "golang.org/x/term" ) @@ -106,7 +107,7 @@ func GetKeysInfo(_ context.Context, modulePath string, slotID uint, pin string) // If pin was not given, check COSIGN_PKCS11_PIN environment variable. if pin == "" { - pin = os.Getenv("COSIGN_PKCS11_PIN") + pin = env.Getenv(env.VariablePKCS11Pin) // If COSIGN_PKCS11_PIN was not set, check if CKF_LOGIN_REQUIRED is set in Token Info. // If it is, ask the user for the PIN, otherwise, do not. diff --git a/doc/cosign_env.md b/doc/cosign_env.md index 55f16b5b070..57fee6a2102 100644 --- a/doc/cosign_env.md +++ b/doc/cosign_env.md @@ -9,7 +9,9 @@ cosign env [flags] ### Options ``` - -h, --help help for env + -h, --help help for env + --show-descriptions show descriptions for environment variables (default true) + --show-sensitive-values show values of sensitive environment variables ``` ### Options inherited from parent commands diff --git a/internal/pkg/cosign/fulcio/fulcioroots/fulcioroots.go b/internal/pkg/cosign/fulcio/fulcioroots/fulcioroots.go index 4403c529a90..ab9e9bd1e23 100644 --- a/internal/pkg/cosign/fulcio/fulcioroots/fulcioroots.go +++ b/internal/pkg/cosign/fulcio/fulcioroots/fulcioroots.go @@ -22,6 +22,7 @@ import ( "os" "sync" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/fulcioroots" ) @@ -33,8 +34,6 @@ var ( singletonRootErr error ) -const altRoot = "SIGSTORE_ROOT_FILE" - // Get returns the Fulcio root certificate. // // If the SIGSTORE_ROOT_FILE environment variable is set, the root config found @@ -62,7 +61,7 @@ func initRoots() (*x509.CertPool, *x509.CertPool, error) { // intermediatePool should be nil if no intermediates are found var intermediatePool *x509.CertPool - rootEnv := os.Getenv(altRoot) + rootEnv := env.Getenv(env.VariableSigstoreRootFile) if rootEnv != "" { raw, err := os.ReadFile(rootEnv) if err != nil { diff --git a/pkg/blob/load.go b/pkg/blob/load.go index 26db1367848..543af56fac1 100644 --- a/pkg/blob/load.go +++ b/pkg/blob/load.go @@ -53,7 +53,10 @@ func LoadFileOrURL(fileRef string) ([]byte, error) { } case "env://": envVar := parts[1] - value, found := os.LookupEnv(envVar) + // Most of Cosign should use `env.LookupEnv` (see #2236) to restrict us to known environment variables + // (usually `$COSIGN_*`). However, in this case, `envVar` is user-provided and not one of the allow-listed + // env vars. + value, found := os.LookupEnv(envVar) //nolint:forbidigo if !found { return nil, fmt.Errorf("loading URL: env var $%s not found", envVar) } diff --git a/pkg/cosign/env/env.go b/pkg/cosign/env/env.go new file mode 100644 index 00000000000..3b08d508bb9 --- /dev/null +++ b/pkg/cosign/env/env.go @@ -0,0 +1,199 @@ +// +// Copyright 2022 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package env + +import ( + "fmt" + "os" + "strings" +) + +// Variable is a type representing an environment variable +type Variable string + +// VariableOpts closely describes a Variable +type VariableOpts struct { + // Description contains description for the environment variable + Description string + // Expects describes what value is expected by the environment variable + Expects string + // Sensitive is used for environment variables with sensitive values + // (e.g. passwords, credentials, etc.) + Sensitive bool + // External is used for environment variables coming from external projects + // and dependencies (e.g. GITHUB_TOKEN, SIGSTORE_, TUF_) + External bool +} + +func (v Variable) String() string { + return string(v) +} + +const ( + // Cosign environment variables + VariableExperimental Variable = "COSIGN_EXPERIMENTAL" + VariableDockerMediaTypes Variable = "COSIGN_DOCKER_MEDIA_TYPES" + VariablePassword Variable = "COSIGN_PASSWORD" + VariablePKCS11Pin Variable = "COSIGN_PKCS11_PIN" + VariablePKCS11ModulePath Variable = "COSIGN_PKCS11_MODULE_PATH" + VariableRepository Variable = "COSIGN_REPOSITORY" + + // Sigstore environment variables + VariableSigstoreCTLogPublicKeyFile Variable = "SIGSTORE_CT_LOG_PUBLIC_KEY_FILE" + VariableSigstoreRootFile Variable = "SIGSTORE_ROOT_FILE" + VariableSigstoreTrustRekorPublicKey Variable = "SIGSTORE_TRUST_REKOR_API_PUBLIC_KEY" + VariableSigstoreRekorPublicKey Variable = "SIGSTORE_REKOR_PUBLIC_KEY" + + // Other external environment variables + VariableGitHubToken Variable = "GITHUB_TOKEN" //nolint:gosec + VariableGitHubRequestToken Variable = "ACTIONS_ID_TOKEN_REQUEST_TOKEN" + VariableGitHubRequestURL Variable = "ACTIONS_ID_TOKEN_REQUEST_URL" + VariableSPIFFEEndpointSocket Variable = "SPIFFE_ENDPOINT_SOCKET" + VariableGoogleServiceAccountName Variable = "GOOGLE_SERVICE_ACCOUNT_NAME" + VariableGitLabHost Variable = "GITLAB_HOST" + VariableGitLabToken Variable = "GITLAB_TOKEN" +) + +var ( + // NB: this is intentionally private to avoid anyone changing this from + // code. There's a getter function used to get this slice if needed. + environmentVariables = map[Variable]VariableOpts{ + VariableExperimental: { + Description: "enables experimental cosign features", + Expects: "1 if experimental features should be enabled (0 by default)", + Sensitive: false, + }, + VariableDockerMediaTypes: { + Description: "to be used with registries that do not support OCI media types", + Expects: "1 to fallback to legacy OCI media types equivalents (0 by default)", + Sensitive: false, + }, + VariablePassword: { + Description: "overrides password inputs with this value", + Expects: "string with a password (asks on stdin by default)", + Sensitive: true, + }, + VariablePKCS11Pin: { + Description: "to be used if PKCS11 PIN is not provided", + Expects: "string with a PIN", + Sensitive: true, + }, + VariablePKCS11ModulePath: { + Description: "is PKCS11 module-path", + Expects: "string with a module-path", + Sensitive: false, + }, + VariableRepository: { + Description: "can be used to store signatures in an alternate location", + Expects: "string with a repository", + Sensitive: false, + }, + + VariableSigstoreCTLogPublicKeyFile: { + Description: "overrides what is used to validate the SCT coming back from Fulcio", + Expects: "path to the public key file", + Sensitive: false, + External: true, + }, + VariableSigstoreRootFile: { + Description: "overrides the public good instance root CA", + Expects: "path to the root CA", + Sensitive: false, + External: true, + }, + VariableSigstoreTrustRekorPublicKey: { + Description: "if specified, will fetch the Rekor Public Key from the specified Rekor server and add it to RekorPubKeys. This env var is only for testing!", + Expects: "any string to trigger this behavior", + Sensitive: false, + External: true, + }, + VariableSigstoreRekorPublicKey: { + Description: "if specified, you can specify an oob Public Key that Rekor uses", + Expects: "path to the public key", + Sensitive: false, + External: true, + }, + + VariableGitHubToken: { + Description: "is a token used to authenticate with GitHub", + Expects: "token generated on GitHub", + Sensitive: true, + External: true, + }, + VariableGitHubRequestToken: { + Description: "is bearer token for the request to the OIDC provider", + Expects: "string with a bearer token", + Sensitive: true, + External: true, + }, + VariableGitHubRequestURL: { + Description: "is the URL for GitHub's OIDC provider", + Expects: "string with the URL for the OIDC provider", + Sensitive: false, + External: true, + }, + VariableSPIFFEEndpointSocket: { + Description: "allows you to specify non-default SPIFFE socket to use.", + Expects: "string with SPIFFE socket path", + Sensitive: false, + External: true, + }, + VariableGoogleServiceAccountName: { + Description: "is a service account name to be used with the Google provider", + Expects: "string with the service account's name", + Sensitive: false, + External: true, + }, + VariableGitLabHost: { + Description: "is URL of the GitLab instance", + Expects: "string with the URL of GitLab instance", + Sensitive: false, + External: true, + }, + VariableGitLabToken: { + Description: "is a token used to authenticate with GitLab", + Expects: "string with a token", + Sensitive: true, + External: true, + }, + } +) + +func EnvironmentVariables() map[Variable]VariableOpts { + return environmentVariables +} + +func mustRegisterEnv(name Variable) { + opts, ok := environmentVariables[name] + if !ok { + panic(fmt.Sprintf("environment variable %q is not registered in pkg/cosign/env", name.String())) + } + if !opts.External && !strings.HasPrefix(name.String(), "COSIGN_") { + panic(fmt.Sprintf("cosign environment variable %q must start with COSIGN_ prefix", name.String())) + } +} + +func Getenv(name Variable) string { + mustRegisterEnv(name) + + return os.Getenv(name.String()) +} + +func LookupEnv(name Variable) (string, bool) { + mustRegisterEnv(name) + + return os.LookupEnv(name.String()) +} diff --git a/pkg/cosign/env/env_test.go b/pkg/cosign/env/env_test.go new file mode 100644 index 00000000000..97a681cecbe --- /dev/null +++ b/pkg/cosign/env/env_test.go @@ -0,0 +1,100 @@ +// +// Copyright 2022 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package env + +import ( + "os" + "testing" +) + +func TestMustRegisterEnv(t *testing.T) { + // Calling this should NOT panic + mustRegisterEnv(VariableExperimental) +} + +func TestMustRegisterEnvWithNonRegisteredEnv(t *testing.T) { + // This test must panic because non-registered variable is not registered with cosign. + // We fail if the test doesn't panic. + defer func() { + if r := recover(); r == nil { + t.Errorf("expected to panic, but panic did not happen") + } + }() + mustRegisterEnv(Variable("non-registered")) +} + +func TestMustRegisterEnvWithInvalidCosignEnvVar(t *testing.T) { + // This test must panic because registered non-external variable doesn't start with COSIGN_. + // We fail if the test doesn't panic. + saveEnvs := environmentVariables + defer func() { + if r := recover(); r == nil { + t.Errorf("expected to panic, but panic did not happen") + } + environmentVariables = saveEnvs + }() + v := Variable("TEST") + environmentVariables = map[Variable]VariableOpts{ + v: { + External: false, + }, + } + mustRegisterEnv(v) +} + +func TestGetenv(t *testing.T) { + os.Setenv("COSIGN_EXPERIMENTAL", "1") + if val := Getenv(VariableExperimental); val != "1" { + t.Errorf("expected to get \"1\", but got %q", val) + } +} + +func TestGetenvUnset(t *testing.T) { + os.Unsetenv("COSIGN_EXPERIMENTAL") + if val := Getenv(VariableExperimental); val != "" { + t.Errorf("expected to get \"\", but got %q", val) + } +} + +func TestLookupEnv(t *testing.T) { + os.Setenv("COSIGN_EXPERIMENTAL", "1") + val, f := LookupEnv(VariableExperimental) + if !f { + t.Errorf("expected to find %q, but it's not set", "COSIGN_EXPERIMENTAL") + } + if val != "1" { + t.Errorf("expected to get value \"1\", but got %q", val) + } +} + +func TestLookupEnvEmpty(t *testing.T) { + os.Setenv("COSIGN_EXPERIMENTAL", "") + val, f := LookupEnv(VariableExperimental) + if !f { + t.Errorf("expected to find %q, but it's not set", "COSIGN_EXPERIMENTAL") + } + if val != "" { + t.Errorf("expected to get value \"\", but got %q", val) + } +} + +func TestLookupEnvUnset(t *testing.T) { + os.Unsetenv("COSIGN_EXPERIMENTAL") + val, f := LookupEnv(VariableExperimental) + if f { + t.Errorf("expected to not find %q, but it's set to %q", "COSIGN_EXPERIMENTAL", val) + } +} diff --git a/pkg/cosign/git/github/github.go b/pkg/cosign/git/github/github.go index 6e41603d543..74c2459f644 100644 --- a/pkg/cosign/git/github/github.go +++ b/pkg/cosign/git/github/github.go @@ -30,6 +30,7 @@ import ( "golang.org/x/oauth2" "github.com/sigstore/cosign/pkg/cosign" + "github.com/sigstore/cosign/pkg/cosign/env" ) const ( @@ -44,13 +45,13 @@ func New() *Gh { func (g *Gh) PutSecret(ctx context.Context, ref string, pf cosign.PassFunc) error { var httpClient *http.Client - if token, ok := os.LookupEnv("GITHUB_TOKEN"); ok { + if token, ok := env.LookupEnv(env.VariableGitHubToken); ok { ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: token}, ) httpClient = oauth2.NewClient(ctx, ts) } else { - return errors.New("could not find \"GITHUB_TOKEN\" environment variable") + return fmt.Errorf("could not find %q environment variable", env.VariableGitHubRequestToken.String()) } client := github.NewClient(httpClient) diff --git a/pkg/cosign/git/gitlab/gitlab.go b/pkg/cosign/git/gitlab/gitlab.go index d06b21785a7..7a9bd739c6f 100644 --- a/pkg/cosign/git/gitlab/gitlab.go +++ b/pkg/cosign/git/gitlab/gitlab.go @@ -17,12 +17,12 @@ package gitlab import ( "context" - "errors" "fmt" "io" "os" "github.com/sigstore/cosign/pkg/cosign" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/xanzy/go-gitlab" ) @@ -42,14 +42,14 @@ func (g *Gl) PutSecret(ctx context.Context, ref string, pf cosign.PassFunc) erro return fmt.Errorf("generating key pair: %w", err) } - token, tokenExists := os.LookupEnv("GITLAB_TOKEN") + token, tokenExists := env.LookupEnv(env.VariableGitLabToken) if !tokenExists { - return errors.New("could not find \"GITLAB_TOKEN\"") + return fmt.Errorf("could not find %q", env.VariableGitLabToken.String()) } var client *gitlab.Client - if url, baseURLExists := os.LookupEnv("GITLAB_HOST"); baseURLExists { + if url, baseURLExists := env.LookupEnv(env.VariableGitLabHost); baseURLExists { client, err = gitlab.NewClient(token, gitlab.WithBaseURL(url)) if err != nil { return fmt.Errorf("could not create GitLab client: %w", err) @@ -125,15 +125,15 @@ func (g *Gl) PutSecret(ctx context.Context, ref string, pf cosign.PassFunc) erro } func (g *Gl) GetSecret(ctx context.Context, ref string, key string) (string, error) { - token, tokenExists := os.LookupEnv("GITLAB_TOKEN") + token, tokenExists := env.LookupEnv(env.VariableGitLabToken) var varPubKeyValue string if !tokenExists { - return varPubKeyValue, errors.New("could not find \"GITLAB_TOKEN\"") + return varPubKeyValue, fmt.Errorf("could not find %q", env.VariableGitLabToken.String()) } var client *gitlab.Client var err error - if url, baseURLExists := os.LookupEnv("GITLAB_HOST"); baseURLExists { + if url, baseURLExists := env.LookupEnv(env.VariableGitLabHost); baseURLExists { client, err = gitlab.NewClient(token, gitlab.WithBaseURL(url)) if err != nil { return varPubKeyValue, fmt.Errorf("could not create GitLab client): %w", err) diff --git a/pkg/cosign/pkcs11key/pkcs11key.go b/pkg/cosign/pkcs11key/pkcs11key.go index f1c7adf33e3..57beda91ed9 100644 --- a/pkg/cosign/pkcs11key/pkcs11key.go +++ b/pkg/cosign/pkcs11key/pkcs11key.go @@ -34,6 +34,7 @@ import ( "github.com/ThalesIgnite/crypto11" "github.com/miekg/pkcs11" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/sigstore/pkg/signature" "golang.org/x/term" ) @@ -80,7 +81,7 @@ func GetKeyWithURIConfig(config *Pkcs11UriConfig, askForPinIfNeeded bool) (*Key, // If no PIN was specified, and if askForPinIfNeeded is true, check to see if COSIGN_PKCS11_PIN env var is set. if conf.Pin == "" && askForPinIfNeeded { - conf.Pin = os.Getenv("COSIGN_PKCS11_PIN") + conf.Pin = env.Getenv(env.VariablePKCS11Pin) // If COSIGN_PKCS11_PIN not set, check to see if CKF_LOGIN_REQUIRED is set in Token Info. // If it is, and if askForPinIfNeeded is true, ask the user for the PIN, otherwise, do not. diff --git a/pkg/cosign/pkcs11key/util.go b/pkg/cosign/pkcs11key/util.go index 43c513fa689..62d54812ec3 100644 --- a/pkg/cosign/pkcs11key/util.go +++ b/pkg/cosign/pkcs11key/util.go @@ -18,9 +18,10 @@ import ( "errors" "fmt" "net/url" - "os" "strconv" "strings" + + "github.com/sigstore/cosign/pkg/cosign/env" ) const ( @@ -164,7 +165,7 @@ func (conf *Pkcs11UriConfig) Parse(uriString string) error { // module-path should be specified and should point to the absolute path of the PKCS11 module. // If it is not, COSIGN_PKCS11_MODULE_PATH environment variable must be set. if modulePath == "" { - modulePath = os.Getenv("COSIGN_PKCS11_MODULE_PATH") + modulePath = env.Getenv(env.VariablePKCS11ModulePath) if modulePath == "" { return errors.New("invalid uri: module-path or COSIGN_PKCS11_MODULE_PATH must be set to the absolute path of the PKCS11 module") } diff --git a/pkg/cosign/tlog.go b/pkg/cosign/tlog.go index 94929d77d32..1a33fce1e54 100644 --- a/pkg/cosign/tlog.go +++ b/pkg/cosign/tlog.go @@ -35,6 +35,7 @@ import ( "github.com/transparency-dev/merkle/rfc6962" "github.com/sigstore/cosign/pkg/cosign/bundle" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/rekor/pkg/generated/client" "github.com/sigstore/rekor/pkg/generated/client/entries" "github.com/sigstore/rekor/pkg/generated/client/index" @@ -56,19 +57,6 @@ type RekorPubKey struct { Status tuf.StatusKind } -const ( - // If specified, you can specify an oob Public Key that Rekor uses using - // this ENV variable. - altRekorPublicKey = "SIGSTORE_REKOR_PUBLIC_KEY" - // Add Rekor API Public Key - // If specified, will fetch the Rekor Public Key from the specified Rekor - // server and add it to RekorPubKeys. This ENV var is only for testing - // purposes, as users should distribute keys out of band. - // TODO(vaikas): Implement storing state like Rekor does so that if tree - // state ever changes, it will make lots of noise. - addRekorPublicKeyFromRekor = "SIGSTORE_TRUST_REKOR_API_PUBLIC_KEY" -) - const treeIDHexStringLen = 16 const uuidHexStringLen = 64 const entryIDHexStringLen = treeIDHexStringLen + uuidHexStringLen @@ -110,7 +98,7 @@ func intotoEntry(ctx context.Context, signature, pubKey []byte) (models.Proposed // TODO: Rename SIGSTORE_TRUST_REKOR_API_PUBLIC_KEY to be test-only or remove. func GetRekorPubs(ctx context.Context, rekorClient *client.Rekor) (map[string]RekorPubKey, error) { publicKeys := make(map[string]RekorPubKey) - altRekorPub := os.Getenv(altRekorPublicKey) + altRekorPub := env.Getenv(env.VariableSigstoreRekorPublicKey) if altRekorPub != "" { raw, err := os.ReadFile(altRekorPub) @@ -150,9 +138,9 @@ func GetRekorPubs(ctx context.Context, rekorClient *client.Rekor) (map[string]Re // If we have a Rekor client and we've been told to fetch the Public Key from Rekor, // additionally fetch it here. - addRekorPublic := os.Getenv(addRekorPublicKeyFromRekor) + addRekorPublic := env.Getenv(env.VariableSigstoreTrustRekorPublicKey) if addRekorPublic != "" && rekorClient != nil { - fmt.Fprintf(os.Stderr, "**Warning ('%s' is only for testing)** Fetching public key from Rekor API directly\n", addRekorPublicKeyFromRekor) + fmt.Fprintf(os.Stderr, "**Warning ('%s' is only for testing)** Fetching public key from Rekor API directly\n", env.VariableSigstoreTrustRekorPublicKey.String()) pubOK, err := rekorClient.Pubkey.GetPublicKey(nil) if err != nil { return nil, fmt.Errorf("unable to fetch rekor public key from rekor: %w", err) diff --git a/pkg/oci/empty/empty_test.go b/pkg/oci/empty/empty_test.go index a73a28d031d..45a274d93bc 100644 --- a/pkg/oci/empty/empty_test.go +++ b/pkg/oci/empty/empty_test.go @@ -21,7 +21,7 @@ import ( "github.com/google/go-containerregistry/pkg/v1/types" - "github.com/sigstore/cosign/pkg/oci" + "github.com/sigstore/cosign/pkg/cosign/env" ) func TestEmptyImage(t *testing.T) { @@ -48,7 +48,7 @@ func TestEmptyImage(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - if err := os.Setenv(oci.DockerMediaTypesEnv, test.value); err != nil { + if err := os.Setenv(env.VariableDockerMediaTypes.String(), test.value); err != nil { t.Fatalf("Setenv() = %v", err) } diff --git a/pkg/oci/mediatypes.go b/pkg/oci/mediatypes.go index d228a82ceec..4f2139c68f8 100644 --- a/pkg/oci/mediatypes.go +++ b/pkg/oci/mediatypes.go @@ -16,16 +16,13 @@ package oci import ( - "os" "strconv" -) -const ( - DockerMediaTypesEnv = "COSIGN_DOCKER_MEDIA_TYPES" + "github.com/sigstore/cosign/pkg/cosign/env" ) func DockerMediaTypes() bool { - if b, err := strconv.ParseBool(os.Getenv(DockerMediaTypesEnv)); err == nil { + if b, err := strconv.ParseBool(env.Getenv(env.VariableDockerMediaTypes)); err == nil { return b } return false diff --git a/pkg/oci/remote/options.go b/pkg/oci/remote/options.go index ed0747c28f9..4719c17aacb 100644 --- a/pkg/oci/remote/options.go +++ b/pkg/oci/remote/options.go @@ -17,11 +17,11 @@ package remote import ( "fmt" - "os" "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/sigstore/cosign/pkg/cosign/env" ) const ( @@ -125,7 +125,7 @@ func WithTargetRepository(repo name.Repository) Option { // `os.Getenv(RepoOverrideEnvKey)`, or the empty value if not set. // Returns an error if the value is set but cannot be parsed. func GetEnvTargetRepository() (name.Repository, error) { - if ro := os.Getenv(RepoOverrideEnvKey); ro != "" { + if ro := env.Getenv(env.VariableRepository); ro != "" { repo, err := name.NewRepository(ro) if err != nil { return name.Repository{}, fmt.Errorf("parsing $"+RepoOverrideEnvKey+": %w", err) diff --git a/pkg/providers/github/github.go b/pkg/providers/github/github.go index db207af4356..d48cc33c54b 100644 --- a/pkg/providers/github/github.go +++ b/pkg/providers/github/github.go @@ -19,8 +19,8 @@ import ( "context" "encoding/json" "net/http" - "os" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/cosign/pkg/providers" ) @@ -32,17 +32,12 @@ type githubActions struct{} var _ providers.Interface = (*githubActions)(nil) -const ( - RequestTokenEnvKey = "ACTIONS_ID_TOKEN_REQUEST_TOKEN" - RequestURLEnvKey = "ACTIONS_ID_TOKEN_REQUEST_URL" -) - // Enabled implements providers.Interface func (ga *githubActions) Enabled(ctx context.Context) bool { - if os.Getenv(RequestTokenEnvKey) == "" { + if env.Getenv(env.VariableGitHubRequestToken) == "" { return false } - if os.Getenv(RequestURLEnvKey) == "" { + if env.Getenv(env.VariableGitHubRequestURL) == "" { return false } return true @@ -50,14 +45,14 @@ func (ga *githubActions) Enabled(ctx context.Context) bool { // Provide implements providers.Interface func (ga *githubActions) Provide(ctx context.Context, audience string) (string, error) { - url := os.Getenv(RequestURLEnvKey) + "&audience=" + audience + url := env.Getenv(env.VariableGitHubRequestURL) + "&audience=" + audience req, err := http.NewRequest("GET", url, nil) if err != nil { return "", err } - req.Header.Add("Authorization", "bearer "+os.Getenv(RequestTokenEnvKey)) + req.Header.Add("Authorization", "bearer "+env.Getenv(env.VariableGitHubRequestToken)) resp, err := http.DefaultClient.Do(req) if err != nil { return "", err diff --git a/pkg/providers/google/google.go b/pkg/providers/google/google.go index f7638d1977c..d23b8e9f5a1 100644 --- a/pkg/providers/google/google.go +++ b/pkg/providers/google/google.go @@ -23,6 +23,7 @@ import ( "google.golang.org/api/idtoken" "google.golang.org/api/impersonate" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/cosign/pkg/providers" ) @@ -76,12 +77,12 @@ var _ providers.Interface = (*googleImpersonate)(nil) // Enabled implements providers.Interface func (gi *googleImpersonate) Enabled(ctx context.Context) bool { // The "impersonate" method requires a target service account to impersonate. - return os.Getenv("GOOGLE_SERVICE_ACCOUNT_NAME") != "" + return env.Getenv(env.VariableGoogleServiceAccountName) != "" } // Provide implements providers.Interface func (gi *googleImpersonate) Provide(ctx context.Context, audience string) (string, error) { - target := os.Getenv("GOOGLE_SERVICE_ACCOUNT_NAME") + target := env.Getenv(env.VariableGoogleServiceAccountName) ts, err := impersonate.IDTokenSource(ctx, impersonate.IDTokenConfig{ Audience: audience, TargetPrincipal: target, diff --git a/pkg/providers/spiffe/spiffe.go b/pkg/providers/spiffe/spiffe.go index b8b63382cbb..37c550541d1 100644 --- a/pkg/providers/spiffe/spiffe.go +++ b/pkg/providers/spiffe/spiffe.go @@ -21,6 +21,7 @@ import ( "github.com/spiffe/go-spiffe/v2/svid/jwtsvid" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/cosign/pkg/providers" "github.com/spiffe/go-spiffe/v2/workloadapi" ) @@ -38,14 +39,12 @@ const ( // token from the spiffe by default. // nolint defaultSocketPath = "/tmp/spire-agent/public/api.sock" - // This allows you to specify non-default Spiffe socket to use. - socketEnv = "SPIFFE_ENDPOINT_SOCKET" ) // getSocketPath gets which Spiffe socket to use. Either default // or the one specified by environment variable. func getSocketPath() string { - if env := os.Getenv(socketEnv); env != "" { + if env := env.Getenv(env.VariableSPIFFEEndpointSocket); env != "" { return env } return defaultSocketPath diff --git a/pkg/providers/spiffe/spiffe_test.go b/pkg/providers/spiffe/spiffe_test.go index 28a26e0f07b..fbc758d60f4 100644 --- a/pkg/providers/spiffe/spiffe_test.go +++ b/pkg/providers/spiffe/spiffe_test.go @@ -26,7 +26,7 @@ func TestGetSocketPath(t *testing.T) { if got := getSocketPath(); got != defaultSocketPath { t.Errorf("Expected %s got %s", defaultSocketPath, got) } - os.Setenv(socketEnv, nonDefault) + os.Setenv("SPIFFE_ENDPOINT_SOCKET", nonDefault) if got := getSocketPath(); got != nonDefault { t.Errorf("Expected %s got %s", nonDefault, got) } diff --git a/test/e2e_test.go b/test/e2e_test.go index 48aced25951..de2f0ef95d3 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -58,6 +58,7 @@ import ( "github.com/sigstore/cosign/cmd/cosign/cli/upload" cliverify "github.com/sigstore/cosign/cmd/cosign/cli/verify" "github.com/sigstore/cosign/pkg/cosign" + "github.com/sigstore/cosign/pkg/cosign/env" "github.com/sigstore/cosign/pkg/cosign/kubernetes" cremote "github.com/sigstore/cosign/pkg/cosign/remote" "github.com/sigstore/cosign/pkg/oci/mutate" @@ -434,7 +435,7 @@ func TestAttestationReplace(t *testing.T) { func TestRekorBundle(t *testing.T) { // turn on the tlog - defer setenv(t, options.ExperimentalEnv, "1")() + defer setenv(t, env.VariableExperimental.String(), "1")() repo, stop := reg(t) defer stop() @@ -682,7 +683,7 @@ func TestSignBlobBundle(t *testing.T) { must(cliverify.VerifyBlobCmd(ctx, ko1, "" /*certRef*/, "" /*certEmail*/, "" /*certIdentity*/, "" /*certOidcIssuer*/, "" /*certChain*/, "" /*sigRef*/, bp, "" /*certGithubWorkflowTrigger*/, "" /*certGithubWorkflowSha*/, "" /*certGithubWorkflowName*/, "" /*certGithubWorkflowRepository*/, "" /*certGithubWorkflowRef*/, false), t) // Now we turn on the tlog and sign again - defer setenv(t, options.ExperimentalEnv, "1")() + defer setenv(t, env.VariableExperimental.String(), "1")() if _, err := sign.SignBlobCmd(ro, ko, options.RegistryOptions{}, bp, true, "", ""); err != nil { t.Fatal(err) } @@ -1146,7 +1147,7 @@ func TestTlog(t *testing.T) { must(verify(pubKeyPath, imgName, true, nil, ""), t) // Now we turn on the tlog! - defer setenv(t, options.ExperimentalEnv, "1")() + defer setenv(t, env.VariableExperimental.String(), "1")() // Verify shouldn't work since we haven't put anything in it yet. mustErr(verify(pubKeyPath, imgName, true, nil, ""), t) @@ -1184,7 +1185,7 @@ func TestNoTlog(t *testing.T) { must(verify(pubKeyPath, imgName, true, nil, ""), t) // Now we turn on the tlog! - defer setenv(t, options.ExperimentalEnv, "1")() + defer setenv(t, env.VariableExperimental.String(), "1")() // Verify shouldn't work since we haven't put anything in it yet. mustErr(verify(pubKeyPath, imgName, true, nil, ""), t) @@ -1349,7 +1350,7 @@ func TestInvalidBundle(t *testing.T) { // Sign image1 and store the entry in rekor // (we're just using it for its bundle) - defer setenv(t, options.ExperimentalEnv, "1")() + defer setenv(t, env.VariableExperimental.String(), "1")() remoteOpts := ociremote.WithRemoteOptions(registryClientOpts(ctx)...) ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc, RekorURL: rekorURL} regOpts := options.RegistryOptions{} @@ -1375,7 +1376,7 @@ func TestInvalidBundle(t *testing.T) { // Now, we move on to image2 // Sign image2 and DO NOT store the entry in rekor - defer setenv(t, options.ExperimentalEnv, "0")() + defer setenv(t, env.VariableExperimental.String(), "0")() img2 := path.Join(regName, "unrelated") imgRef2, _, cleanup := mkimage(t, img2) defer cleanup()