package passphrase import ( "encoding/json" "os" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) const ( state = `{"salt":"v1:fozI5u6B030=:v1:F+6ZduKKd8G0/V7L:PGMFeIzwobWRKmEAzUdaQHqC5mMRIQ=="}` brokenState = `{"salt":"fozI5u6B030=:v1:F+6ZduL:PGMFeIzwobWRKmEAzUdaQHqC5mMRIQ=="}` ) func resetPassphraseTestEnvVars() func() { clearCachedSecretsManagers() oldPassphrase := os.Getenv("PULUMI_CONFIG_PASSPHRASE") oldPassphraseFile := os.Getenv("PULUMI_CONFIG_PASSPHRASE_FILE") return func() { os.Setenv("PULUMI_CONFIG_PASSPHRASE", oldPassphrase) os.Setenv("PULUMI_CONFIG_PASSPHRASE_FILE", oldPassphraseFile) } } //nolint:paralleltest // mutates environment variables func TestPassphraseManagerIncorrectPassphraseReturnsErrorCrypter(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() os.Setenv("PULUMI_CONFIG_PASSPHRASE", "password123") os.Unsetenv("PULUMI_CONFIG_PASSPHRASE_FILE") manager, err := NewPromptingPassphraseSecretsManagerFromState([]byte(state)) require.NoError(t, err) // even if we pass the wrong provider, we should get a lockedPassphraseProvider state, err := json.Marshal(localSecretsManagerState{ Salt: "v1:fozI5u6B030=:v1:F+6ZduKKd8G0/V7L:PGMFeIzwobWRKmEAzUdaQHqC5mMRIQ==", }) require.NoError(t, err) assert.Equal(t, manager, &localSecretsManager{ state: state, crypter: &errorCrypter{}, }) } //nolint:paralleltest // mutates environment variables func TestPassphraseManagerIncorrectStateReturnsError(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() os.Setenv("PULUMI_CONFIG_PASSPHRASE", "password") os.Unsetenv("PULUMI_CONFIG_PASSPHRASE_FILE") _, err := NewPromptingPassphraseSecretsManagerFromState([]byte(brokenState)) assert.Error(t, err) } //nolint:paralleltest // mutates environment variables func TestPassphraseManagerCorrectPassphraseReturnsSecretsManager(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() os.Setenv("PULUMI_CONFIG_PASSPHRASE", "password") os.Unsetenv("PULUMI_CONFIG_PASSPHRASE_FILE") sm, err := NewPromptingPassphraseSecretsManagerFromState([]byte(state)) assert.NoError(t, err) assert.NotNil(t, sm) } //nolint:paralleltest // mutates environment variables func TestPassphraseManagerNoEnvironmentVariablesReturnsError(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() os.Unsetenv("PULUMI_CONFIG_PASSPHRASE") os.Unsetenv("PULUMI_CONFIG_PASSPHRASE_FILE") _, err := NewPromptingPassphraseSecretsManagerFromState([]byte(state)) assert.Error(t, err, strings.Contains(err.Error(), "unable to find either `PULUMI_CONFIG_PASSPHRASE` nor "+ "`PULUMI_CONFIG_PASSPHRASE_FILE`")) } //nolint:paralleltest // mutates environment variables func TestPassphraseManagerEmptyPassphraseIsValid(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() os.Setenv("PULUMI_CONFIG_PASSPHRASE", "") os.Unsetenv("PULUMI_CONFIG_PASSPHRASE_FILE") sm, err := NewPromptingPassphraseSecretsManagerFromState([]byte(state)) assert.NoError(t, err) assert.NotNil(t, sm) } //nolint:paralleltest // mutates environment variables func TestPassphraseManagerCorrectPassfileReturnsSecretsManager(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() tmpFile, err := os.CreateTemp("", "pulumi-secret-test") assert.NoError(t, err) defer os.Remove(tmpFile.Name()) _, err = tmpFile.WriteString("password") assert.NoError(t, err) os.Unsetenv("PULUMI_CONFIG_PASSPHRASE") os.Setenv("PULUMI_CONFIG_PASSPHRASE_FILE", tmpFile.Name()) sm, err := NewPromptingPassphraseSecretsManagerFromState([]byte(state)) assert.NoError(t, err) assert.NotNil(t, sm) } //nolint:paralleltest // mutates environment variables func TestPassphraseManagerEmptyPassfileReturnsError(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() os.Unsetenv("PULUMI_CONFIG_PASSPHRASE") os.Setenv("PULUMI_CONFIG_PASSPHRASE_FILE", "") _, err := NewPromptingPassphraseSecretsManagerFromState([]byte(state)) assert.Error(t, err, strings.Contains(err.Error(), "unable to find either `PULUMI_CONFIG_PASSPHRASE` nor "+ "`PULUMI_CONFIG_PASSPHRASE_FILE`")) }