diff --git a/Makefile b/Makefile index c26ad8dc1..5034707e8 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ build: go-version-check fmtcheck go install test: go-version-check fmtcheck - TF_ACC= go test $(TESTARGS) -timeout 10m $(TEST_PATH) + TF_ACC= VAULT_TOKEN= go test $(TESTARGS) -timeout 10m $(TEST_PATH) testacc: fmtcheck TF_ACC=1 go test $(TESTARGS) -timeout 30m $(TEST_PATH) diff --git a/internal/provider/auth.go b/internal/provider/auth.go index 1a50474c6..dbd55c288 100644 --- a/internal/provider/auth.go +++ b/internal/provider/auth.go @@ -211,6 +211,10 @@ func (l *AuthLoginCommon) copyParamsExcluding(excludes ...string) (map[string]in } func (l *AuthLoginCommon) login(client *api.Client, path string, params map[string]interface{}) (*api.Secret, error) { + if client.Token() != "" { + return nil, fmt.Errorf("vault login client has a token set") + } + return client.Logical().Write(path, params) } diff --git a/internal/provider/auth_aws_test.go b/internal/provider/auth_aws_test.go index 8c9da9f70..19a9594c0 100644 --- a/internal/provider/auth_aws_test.go +++ b/internal/provider/auth_aws_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "reflect" @@ -286,9 +287,29 @@ func TestAuthLoginAWS_Login(t *testing.T) { wantErr: true, expectErr: authLoginInitCheckError, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginAWS{ + AuthLoginCommon{ + authField: "baz", + mount: "foo", + params: map[string]interface{}{ + consts.FieldRole: "bob", + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_azure_test.go b/internal/provider/auth_azure_test.go index da2bc1949..85340ca5c 100644 --- a/internal/provider/auth_azure_test.go +++ b/internal/provider/auth_azure_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "testing" @@ -240,6 +241,27 @@ func TestAuthLoginAzure_Login(t *testing.T) { }, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginAzure{ + AuthLoginCommon: AuthLoginCommon{ + authField: consts.FieldAuthLoginAzure, + params: map[string]interface{}{ + consts.FieldRole: "alice", + consts.FieldJWT: "jwt1", + consts.FieldSubscriptionID: "sub1", + consts.FieldResourceGroupName: "res1", + consts.FieldVMSSName: "vmss1", + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-uninitialized", authLogin: &AuthLoginAzure{ @@ -258,6 +280,7 @@ func TestAuthLoginAzure_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_cert_test.go b/internal/provider/auth_cert_test.go index 166a9cd16..5f93d82e5 100644 --- a/internal/provider/auth_cert_test.go +++ b/internal/provider/auth_cert_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "os" @@ -294,6 +295,28 @@ func TestAuthLoginCert_Login(t *testing.T) { tls: true, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginCert{ + AuthLoginCommon{ + authField: "baz", + mount: "qux", + params: map[string]interface{}{ + consts.FieldName: "bob", + consts.FieldCertFile: certFile, + consts.FieldKeyFile: keyFile, + consts.FieldSkipTLSVerify: true, + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-uninitialized", authLogin: &AuthLoginCert{ @@ -312,6 +335,7 @@ func TestAuthLoginCert_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_gcp_test.go b/internal/provider/auth_gcp_test.go index c8ef27cff..0de961e16 100644 --- a/internal/provider/auth_gcp_test.go +++ b/internal/provider/auth_gcp_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "os" @@ -168,6 +169,42 @@ func TestAuthLoginGCP_Login(t *testing.T) { testutil.SkipTestEnvUnset(t, consts.EnvVarGoogleApplicationCreds, envVarGCPServiceAccount) }, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginGCP{ + AuthLoginCommon{ + authField: "baz", + mount: "qux", + params: map[string]interface{}{ + consts.FieldRole: "bob", + consts.FieldCredentials: os.Getenv(consts.EnvVarGoogleApplicationCreds), + consts.FieldServiceAccount: os.Getenv(envVarGCPServiceAccount), + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + excludeParams: []string{consts.FieldJWT}, + handlerFunc: handlerFunc, + }, + expectReqCount: 1, + expectReqPaths: []string{ + "/v1/auth/qux/login", + }, + expectReqParams: []map[string]interface{}{{ + consts.FieldRole: "bob", + }}, + want: &api.Secret{ + Auth: &api.SecretAuth{ + Metadata: map[string]string{ + consts.FieldRole: "bob", + }, + }, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "no-jwt", authLogin: &AuthLoginGCP{ @@ -201,6 +238,7 @@ func TestAuthLoginGCP_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_jwt_test.go b/internal/provider/auth_jwt_test.go index df933c241..19520b34e 100644 --- a/internal/provider/auth_jwt_test.go +++ b/internal/provider/auth_jwt_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "testing" @@ -157,6 +158,25 @@ func TestAuthLoginJWT_Login(t *testing.T) { }, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginJWT{ + AuthLoginCommon: AuthLoginCommon{ + authField: consts.FieldAuthLoginJWT, + params: map[string]interface{}{ + consts.FieldRole: "alice", + consts.FieldJWT: "jwt1", + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-uninitialized", authLogin: &AuthLoginJWT{ @@ -175,6 +195,7 @@ func TestAuthLoginJWT_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_kerberos_test.go b/internal/provider/auth_kerberos_test.go index 3243b6715..769d9cb03 100644 --- a/internal/provider/auth_kerberos_test.go +++ b/internal/provider/auth_kerberos_test.go @@ -6,6 +6,7 @@ package provider import ( "encoding/base64" "encoding/json" + "errors" "fmt" "net/http" "reflect" @@ -221,9 +222,43 @@ func TestAuthLoginKerberos_Login(t *testing.T) { }, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginKerberos{ + authHeaderFunc: getTestAuthHeaderFunc(&krbauth.LoginCfg{ + Username: "alice", + Service: "service1", + Realm: "realm1", + KeytabPath: "/etc/kerberos/keytab", + Krb5ConfPath: "/etc/kerberos/krb5.conf", + DisableFASTNegotiation: true, + RemoveInstanceName: false, + }), + AuthLoginCommon: AuthLoginCommon{ + authField: consts.FieldAuthLoginKerberos, + params: map[string]interface{}{ + consts.FieldUsername: "alice", + consts.FieldService: "service1", + consts.FieldRealm: "realm1", + consts.FieldKeytabPath: "/etc/kerberos/keytab", + consts.FieldKRB5ConfPath: "/etc/kerberos/krb5.conf", + consts.FieldDisableFastNegotiation: true, + consts.FieldRemoveInstanceName: false, + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_oci_test.go b/internal/provider/auth_oci_test.go index c7dc389a1..8a9d553f8 100644 --- a/internal/provider/auth_oci_test.go +++ b/internal/provider/auth_oci_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "testing" @@ -187,6 +188,25 @@ func TestAuthLoginOCI_Login(t *testing.T) { }, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginOCI{ + AuthLoginCommon: AuthLoginCommon{ + authField: consts.FieldAuthLoginOCI, + params: map[string]interface{}{ + consts.FieldRole: "alice", + consts.FieldAuthType: ociAuthTypeAPIKeys, + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-uninitialized", authLogin: &AuthLoginOCI{ @@ -205,6 +225,7 @@ func TestAuthLoginOCI_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_oidc_test.go b/internal/provider/auth_oidc_test.go index d70a2ee12..2986ecd91 100644 --- a/internal/provider/auth_oidc_test.go +++ b/internal/provider/auth_oidc_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "reflect" @@ -229,6 +230,25 @@ func TestAuthLoginOIDC_Login(t *testing.T) { } tests := []authLoginTest{ + { + name: "error-vault-token-set", + authLogin: &AuthLoginOIDC{ + AuthLoginCommon{ + authField: "baz", + mount: "foo", + params: map[string]interface{}{ + consts.FieldRole: "bob", + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-uninitialized", authLogin: &AuthLoginOIDC{ @@ -246,6 +266,7 @@ func TestAuthLoginOIDC_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_radius_test.go b/internal/provider/auth_radius_test.go index 784ea5f29..06b5f0936 100644 --- a/internal/provider/auth_radius_test.go +++ b/internal/provider/auth_radius_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "testing" @@ -157,6 +158,25 @@ func TestAuthLoginRadius_Login(t *testing.T) { }, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginRadius{ + AuthLoginCommon: AuthLoginCommon{ + authField: consts.FieldAuthLoginRadius, + params: map[string]interface{}{ + consts.FieldUsername: "alice", + consts.FieldPassword: "password1", + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-uninitialized", authLogin: &AuthLoginRadius{ @@ -175,6 +195,7 @@ func TestAuthLoginRadius_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_test.go b/internal/provider/auth_test.go index 55075172c..d02663e7b 100644 --- a/internal/provider/auth_test.go +++ b/internal/provider/auth_test.go @@ -35,6 +35,7 @@ type authLoginTest struct { skipFunc func(t *testing.T) tls bool preLoginFunc func(t *testing.T) + token string } type authLoginInitTest struct { @@ -120,6 +121,14 @@ func testAuthLogin(t *testing.T, tt authLoginTest) { t.Fatal(err) } + // clear the vault token to avoid issues where it is picked up from one of its + // default sources. + c.ClearToken() + + if tt.token != "" { + c.SetToken(tt.token) + } + got, err := tt.authLogin.Login(c) if (err != nil) != tt.wantErr { t.Errorf("Login() error = %v, wantErr %v", err, tt.wantErr) diff --git a/internal/provider/auth_token_file_test.go b/internal/provider/auth_token_file_test.go index 71730cf9c..8730b44e3 100644 --- a/internal/provider/auth_token_file_test.go +++ b/internal/provider/auth_token_file_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "net/http" "os" @@ -144,6 +145,38 @@ func TestAuthLoginTokenFile_Login(t *testing.T) { }, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginTokenFile{ + AuthLoginCommon{ + authField: "baz", + mount: consts.MountTypeNone, + params: map[string]interface{}{ + consts.FieldFilename: path.Join(tempDir, "basic"), + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + preLoginFunc: func(t *testing.T) { + t.Helper() + + filename := path.Join(tempDir, "basic") + t.Cleanup(func() { + if err := os.Remove(filename); err != nil { + t.Error(err) + } + }) + if err := os.WriteFile(filename, []byte("qux\n"), 0o600); err != nil { + t.Fatal(err) + } + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-invalid-file-mode", authLogin: &AuthLoginTokenFile{ @@ -223,6 +256,7 @@ func TestAuthLoginTokenFile_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/auth_userpass_test.go b/internal/provider/auth_userpass_test.go index ee6907f3f..370404753 100644 --- a/internal/provider/auth_userpass_test.go +++ b/internal/provider/auth_userpass_test.go @@ -5,6 +5,7 @@ package provider import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -225,6 +226,26 @@ func TestAuthLoginUserpass_Login(t *testing.T) { }, wantErr: false, }, + { + name: "error-vault-token-set", + authLogin: &AuthLoginUserpass{ + AuthLoginCommon{ + authField: "baz", + mount: "foo", + params: map[string]interface{}{ + consts.FieldUsername: "bob", + consts.FieldPassword: "baz", + }, + initialized: true, + }, + }, + handler: &testLoginHandler{ + handlerFunc: handlerFunc, + }, + token: "foo", + wantErr: true, + expectErr: errors.New("vault login client has a token set"), + }, { name: "error-no-username", authLogin: &AuthLoginUserpass{ @@ -263,6 +284,7 @@ func TestAuthLoginUserpass_Login(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() testAuthLogin(t, tt) }) } diff --git a/internal/provider/meta.go b/internal/provider/meta.go index d80e9459b..123ae94b7 100644 --- a/internal/provider/meta.go +++ b/internal/provider/meta.go @@ -237,6 +237,12 @@ func NewProviderMeta(d *schema.ResourceData) (interface{}, error) { return nil, err } + if clone.Token() != "" { + log.Printf("[WARN] A vault token was set from the runtime environment, "+ + "clearing it for auth_login method %q", authLogin.Method()) + clone.ClearToken() + } + if authLogin.Namespace() != "" { // the namespace configured on the auth_login takes precedence over the provider's // for authentication only.