diff --git a/builtin/credential/okta/backend_test.go b/builtin/credential/okta/backend_test.go index 4dcdc95ac9..4552452401 100644 --- a/builtin/credential/okta/backend_test.go +++ b/builtin/credential/okta/backend_test.go @@ -11,12 +11,12 @@ import ( "testing" "time" - log "github.com/hashicorp/go-hclog" - "github.com/hashicorp/vault/helper/testhelpers" - logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" - "github.com/hashicorp/vault/sdk/helper/logging" + stepwise "github.com/hashicorp/vault-testing-stepwise" + dockerEnvironment "github.com/hashicorp/vault-testing-stepwise/environments/docker" + "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/sdk/helper/policyutil" - "github.com/hashicorp/vault/sdk/logical" + thstepwise "github.com/hashicorp/vault/sdk/helper/testhelpers/stepwise" + thutils "github.com/hashicorp/vault/sdk/helper/testhelpers/utils" "github.com/okta/okta-sdk-golang/v5/okta" "github.com/stretchr/testify/require" ) @@ -24,51 +24,63 @@ import ( // To run this test, set the following env variables: // VAULT_ACC=1 // OKTA_ORG=dev-219337 +// OKTA_PREVIEW=1 to use the okta preview URL (optional) // OKTA_API_TOKEN= // OKTA_USERNAME=test3@example.com // OKTA_PASSWORD= // +// Using free integrater accounts to test incurs rate limits; so you will need +// to set the following to skip creating/deleting test groups +// SKIP_GROUPS_CREATE_DELETE= (optional) +// // You will need to install the Okta client app on your mobile device and // setup MFA in order to use the Okta web UI. This test does not exercise // MFA however (which is an enterprise feature), and therefore the test // user in OKTA_USERNAME should not be configured with it. Currently // test3@example.com is not a member of testgroup, which is the group with // the profile that requires MFA. + +const ( + envOktaOrg = "OKTA_ORG" + envOktaUsername = "OKTA_USERNAME" + envOktaPassword = "OKTA_PASSWORD" + envOktaAPIToken = "OKTA_API_TOKEN" + envOktaPreview = "OKTA_PREVIEW" + envSkipGroupsCreateDelete = "SKIP_GROUPS_CREATE_DELETE" +) + func TestBackend_Config(t *testing.T) { - if os.Getenv("VAULT_ACC") == "" { - t.SkipNow() + // Ensure required environment variables are set. + requiredEnvs := []string{ + "VAULT_ACC", + envOktaOrg, + envOktaUsername, + envOktaPassword, + envOktaAPIToken, } + thutils.SkipUnlessEnvVarsSet(t, requiredEnvs) - // Ensure each cred is populated. - credNames := []string{ - "OKTA_USERNAME", - "OKTA_PASSWORD", - "OKTA_API_TOKEN", + defaultLeaseTTL := time.Hour * 12 + maxLeaseTTL := time.Hour * 24 + + username := os.Getenv(envOktaUsername) + password := os.Getenv(envOktaPassword) + token := os.Getenv(envOktaAPIToken) + + if os.Getenv(envSkipGroupsCreateDelete) != "" { + t.Logf("Skipping creation/deletion of Okta test groups") + } else { + groupIDs := createOktaGroups(t, username, token, os.Getenv(envOktaOrg)) + defer deleteOktaGroups(t, token, os.Getenv(envOktaOrg), groupIDs) } - testhelpers.SkipUnlessEnvVarsSet(t, credNames) - - defaultLeaseTTLVal := time.Hour * 12 - maxLeaseTTLVal := time.Hour * 24 - b, err := Factory(context.Background(), &logical.BackendConfig{ - Logger: logging.NewVaultLogger(log.Trace), - System: &logical.StaticSystemView{ - DefaultLeaseTTLVal: defaultLeaseTTLVal, - MaxLeaseTTLVal: maxLeaseTTLVal, - }, - }) - if err != nil { - t.Fatalf("Unable to create backend: %s", err) - } - - username := os.Getenv("OKTA_USERNAME") - password := os.Getenv("OKTA_PASSWORD") - token := os.Getenv("OKTA_API_TOKEN") - groupIDs := createOktaGroups(t, username, token, os.Getenv("OKTA_ORG")) - defer deleteOktaGroups(t, token, os.Getenv("OKTA_ORG"), groupIDs) configData := map[string]interface{}{ - "org_name": os.Getenv("OKTA_ORG"), - "base_url": "oktapreview.com", + "org_name": os.Getenv(envOktaOrg), + "base_url": defaultBaseURL, + } + + if os.Getenv(envOktaPreview) != "" { + configData["base_url"] = previewBaseURL } updatedDuration := time.Hour * 1 @@ -77,43 +89,63 @@ func TestBackend_Config(t *testing.T) { "token_ttl": "1h", } - logicaltest.Test(t, logicaltest.TestCase{ - AcceptanceTest: true, - PreCheck: func() { testAccPreCheck(t) }, - CredentialBackend: b, - Steps: []logicaltest.TestStep{ - testConfigCreate(t, configData), + envOptions := &stepwise.MountOptions{ + RegistryName: "okta-auth", + PluginType: api.PluginTypeCredential, + PluginName: "okta", + MountPathPrefix: "okta-auth", + MountConfigInput: api.MountConfigInput{ + DefaultLeaseTTL: fmt.Sprintf("%d", int(defaultLeaseTTL.Seconds())), + MaxLeaseTTL: fmt.Sprintf("%d", int(maxLeaseTTL.Seconds())), + }, + } + stepwise.Run(t, stepwise.Case{ + Precheck: func() { testAccPreCheck(t) }, + Environment: dockerEnvironment.NewEnvironment("okta", envOptions), + Steps: []stepwise.Step{ + testConfigCreate(configData), // 2. Login with bad password, expect failure (E0000004=okta auth failure). - testLoginWrite(t, username, "wrong", "E0000004", 0, nil), + testLoginWrite(username, "wrong", "E0000004", 0, nil), // 3. Make our user belong to two groups and have one user-specific policy. - testAccUserGroups(t, username, "local_grouP,lOcal_group2", []string{"user_policy"}), + testAccUserGroups(username, "local_grouP,lOcal_group2", []string{"user_policy"}), // 4. Create the group local_group, assign it a single policy. - testAccGroups(t, "local_groUp", "loCal_group_policy"), + testAccGroups("local_groUp", "loCal_group_policy"), // 5. Login with good password, expect user to have their user-specific // policy and the policy of the one valid group they belong to. - testLoginWrite(t, username, password, "", defaultLeaseTTLVal, []string{"local_group_policy", "user_policy"}), + testLoginWrite(username, password, "", defaultLeaseTTL, []string{"local_group_policy", "user_policy"}), // 6. Create the group everyone, assign it two policies. This is a // magic group name in okta that always exists and which every // user automatically belongs to. - testAccGroups(t, "everyoNe", "everyone_grouP_policy,eveRy_group_policy2"), + testAccGroups("everyoNe", "everyone_grouP_policy,eveRy_group_policy2"), // 7. Login as before, expect same result - testLoginWrite(t, username, password, "", defaultLeaseTTLVal, []string{"local_group_policy", "user_policy"}), + testLoginWrite(username, password, "", defaultLeaseTTL, []string{"local_group_policy", "user_policy"}), // 8. Add API token so we can lookup groups - testConfigUpdate(t, configDataToken), - testConfigRead(t, token, configData), + testConfigUpdate(configDataToken), + testConfigRead(token, configData), // 10. Login should now lookup okta groups; since all okta users are // in the "everyone" group, that should be returned; since we // defined policies attached to the everyone group, we should now // see those policies attached to returned vault token. - testLoginWrite(t, username, password, "", updatedDuration, []string{"everyone_group_policy", "every_group_policy2", "local_group_policy", "user_policy"}), - testAccGroups(t, "locAl_group2", "testgroup_group_policy"), - testLoginWrite(t, username, password, "", updatedDuration, []string{"everyone_group_policy", "every_group_policy2", "local_group_policy", "testgroup_group_policy", "user_policy"}), + testLoginWrite(username, password, "", updatedDuration, + []string{"everyone_group_policy", "every_group_policy2", "local_group_policy", "user_policy"}), + testAccGroups("locAl_group2", "testgroup_group_policy"), + testLoginWrite(username, password, "", updatedDuration, + []string{"everyone_group_policy", "every_group_policy2", "local_group_policy", "testgroup_group_policy", "user_policy"}), + testAccLogin(username, password, + []string{"default", "everyone_group_policy", "every_group_policy2", "local_group_policy", "testgroup_group_policy", "user_policy"}), }, }) } func createOktaGroups(t *testing.T, username string, token string, org string) []string { - orgURL := "https://" + org + "." + previewBaseURL + t.Helper() + orgURL := "https://" + org + "." + if os.Getenv(envOktaPreview) != "" { + orgURL += previewBaseURL + } else { + orgURL += defaultBaseURL + } + cfg, err := okta.NewConfiguration(okta.WithOrgUrl(orgURL), okta.WithToken(token)) require.Nil(t, err) client := okta.NewAPIClient(cfg) @@ -156,6 +188,7 @@ func createOktaGroups(t *testing.T, username string, token string, org string) [ } func deleteOktaGroups(t *testing.T, token string, org string, groupIDs []string) { + t.Helper() orgURL := "https://" + org + "." + previewBaseURL cfg, err := okta.NewConfiguration(okta.WithOrgUrl(orgURL), okta.WithToken(token)) require.Nil(t, err) @@ -167,21 +200,27 @@ func deleteOktaGroups(t *testing.T, token string, org string, groupIDs []string) } } -func testLoginWrite(t *testing.T, username, password, reason string, expectedTTL time.Duration, policies []string) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.UpdateOperation, +func testLoginWrite(username, password, reason string, expectedTTL time.Duration, policies []string) stepwise.Step { + return stepwise.Step{ + Operation: stepwise.UpdateOperation, Path: "login/" + username, - ErrorOk: true, Data: map[string]interface{}{ "password": password, }, - Check: func(resp *logical.Response) error { - if resp.IsError() { - if reason == "" || !strings.Contains(resp.Error().Error(), reason) { - return resp.Error() + Assert: func(resp *api.Secret, err error) error { + if reason != "" { + if !strings.Contains(err.Error(), reason) { + return fmt.Errorf("expected error containing %q, got no error", reason) } - } else if reason != "" { - return fmt.Errorf("expected error containing %q, got no error", reason) + return nil + } + + if err != nil { + return err + } + + if resp == nil { + return fmt.Errorf("expected non-nil response") } if resp.Auth != nil { @@ -189,8 +228,8 @@ func testLoginWrite(t *testing.T, username, password, reason string, expectedTTL return fmt.Errorf("policy mismatch expected %v but got %v", policies, resp.Auth.Policies) } - actualTTL := resp.Auth.LeaseOptions.TTL - if actualTTL != expectedTTL { + actualTTL := resp.Auth.LeaseDuration + if time.Duration(actualTTL)*time.Second != expectedTTL { return fmt.Errorf("TTL mismatch expected %v but got %v", expectedTTL, actualTTL) } } @@ -200,29 +239,33 @@ func testLoginWrite(t *testing.T, username, password, reason string, expectedTTL } } -func testConfigCreate(t *testing.T, d map[string]interface{}) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.CreateOperation, +func testConfigCreate(d map[string]interface{}) stepwise.Step { + return stepwise.Step{ + Operation: stepwise.WriteOperation, Path: "config", Data: d, } } -func testConfigUpdate(t *testing.T, d map[string]interface{}) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.UpdateOperation, +func testConfigUpdate(d map[string]interface{}) stepwise.Step { + return stepwise.Step{ + Operation: stepwise.UpdateOperation, Path: "config", Data: d, } } -func testConfigRead(t *testing.T, token string, d map[string]interface{}) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.ReadOperation, +func testConfigRead(token string, d map[string]interface{}) stepwise.Step { + return stepwise.Step{ + Operation: stepwise.ReadOperation, Path: "config", - Check: func(resp *logical.Response) error { - if resp.IsError() { - return resp.Error() + Assert: func(resp *api.Secret, err error) error { + if err != nil { + return err + } + + if resp.Data["error"] != nil { + return fmt.Errorf("error reading config: %v", resp.Data["error"]) } if resp.Data["org_name"] != d["org_name"] { @@ -245,26 +288,31 @@ func testConfigRead(t *testing.T, token string, d map[string]interface{}) logica } func testAccPreCheck(t *testing.T) { - if v := os.Getenv("OKTA_USERNAME"); v == "" { - t.Fatal("OKTA_USERNAME must be set for acceptance tests") + t.Helper() + if v := os.Getenv(envOktaUsername); v == "" { + t.Fatalf("%s must be set for acceptance tests", envOktaUsername) } - if v := os.Getenv("OKTA_PASSWORD"); v == "" { - t.Fatal("OKTA_PASSWORD must be set for acceptance tests") + if v := os.Getenv(envOktaPassword); v == "" { + t.Fatalf("%s must be set for acceptance tests", envOktaPassword) } - if v := os.Getenv("OKTA_ORG"); v == "" { - t.Fatal("OKTA_ORG must be set for acceptance tests") + if v := os.Getenv(envOktaOrg); v == "" { + t.Fatalf("%s must be set for acceptance tests", envOktaOrg) } - if v := os.Getenv("OKTA_API_TOKEN"); v == "" { - t.Fatal("OKTA_API_TOKEN must be set for acceptance tests") + if v := os.Getenv(envOktaAPIToken); v == "" { + t.Fatalf("%s must be set for acceptance tests", envOktaAPIToken) + } + + if v := os.Getenv(envSkipGroupsCreateDelete); v == "" { + t.Fatalf("%s must be set for acceptance tests", envSkipGroupsCreateDelete) } } -func testAccUserGroups(t *testing.T, user string, groups interface{}, policies interface{}) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.UpdateOperation, +func testAccUserGroups(user string, groups interface{}, policies interface{}) stepwise.Step { + return stepwise.Step{ + Operation: stepwise.UpdateOperation, Path: "users/" + user, Data: map[string]interface{}{ "groups": groups, @@ -273,10 +321,9 @@ func testAccUserGroups(t *testing.T, user string, groups interface{}, policies i } } -func testAccGroups(t *testing.T, group string, policies interface{}) logicaltest.TestStep { - t.Logf("[testAccGroups] - Registering group %s, policy %s", group, policies) - return logicaltest.TestStep{ - Operation: logical.UpdateOperation, +func testAccGroups(group string, policies interface{}) stepwise.Step { + return stepwise.Step{ + Operation: stepwise.UpdateOperation, Path: "groups/" + group, Data: map[string]interface{}{ "policies": policies, @@ -284,15 +331,14 @@ func testAccGroups(t *testing.T, group string, policies interface{}) logicaltest } } -func testAccLogin(t *testing.T, user, password string, keys []string) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.UpdateOperation, +func testAccLogin(user, password string, keys []string) stepwise.Step { + return stepwise.Step{ + Operation: stepwise.UpdateOperation, Path: "login/" + user, Data: map[string]interface{}{ "password": password, }, Unauthenticated: true, - - Check: logicaltest.TestCheckAuth(keys), + Assert: thstepwise.NewAssertAuthPoliciesFunc(keys), } } diff --git a/command/agent/alicloud_end_to_end_test.go b/command/agent/alicloud_end_to_end_test.go index dc37a6a8ed..6e613c5f9f 100644 --- a/command/agent/alicloud_end_to_end_test.go +++ b/command/agent/alicloud_end_to_end_test.go @@ -22,8 +22,8 @@ import ( agentalicloud "github.com/hashicorp/vault/command/agentproxyshared/auth/alicloud" "github.com/hashicorp/vault/command/agentproxyshared/sink" "github.com/hashicorp/vault/command/agentproxyshared/sink/file" - "github.com/hashicorp/vault/helper/testhelpers" vaulthttp "github.com/hashicorp/vault/http" + thutils "github.com/hashicorp/vault/sdk/helper/testhelpers/utils" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/vault" ) @@ -45,7 +45,7 @@ func TestAliCloudEndToEnd(t *testing.T) { envVarAlicloudSecretKey, envVarAlicloudRoleArn, } - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) coreConfig := &vault.CoreConfig{ CredentialBackends: map[string]logical.Factory{ diff --git a/command/agent/aws_end_to_end_test.go b/command/agent/aws_end_to_end_test.go index b6d453cbdd..fec55c41a7 100644 --- a/command/agent/aws_end_to_end_test.go +++ b/command/agent/aws_end_to_end_test.go @@ -22,9 +22,9 @@ import ( agentaws "github.com/hashicorp/vault/command/agentproxyshared/auth/aws" "github.com/hashicorp/vault/command/agentproxyshared/sink" "github.com/hashicorp/vault/command/agentproxyshared/sink/file" - "github.com/hashicorp/vault/helper/testhelpers" vaulthttp "github.com/hashicorp/vault/http" "github.com/hashicorp/vault/sdk/helper/logging" + thutils "github.com/hashicorp/vault/sdk/helper/testhelpers/utils" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/vault" ) @@ -57,7 +57,7 @@ func TestAWSEndToEnd(t *testing.T) { envVarAwsTestSecretKey, envVarAwsTestRoleArn, } - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) logger := logging.NewVaultLogger(hclog.Trace) coreConfig := &vault.CoreConfig{ diff --git a/command/agent/oci_end_to_end_test.go b/command/agent/oci_end_to_end_test.go index e963264e10..82e12e7cb1 100644 --- a/command/agent/oci_end_to_end_test.go +++ b/command/agent/oci_end_to_end_test.go @@ -17,9 +17,9 @@ import ( agentoci "github.com/hashicorp/vault/command/agentproxyshared/auth/oci" "github.com/hashicorp/vault/command/agentproxyshared/sink" "github.com/hashicorp/vault/command/agentproxyshared/sink/file" - "github.com/hashicorp/vault/helper/testhelpers" vaulthttp "github.com/hashicorp/vault/http" "github.com/hashicorp/vault/sdk/helper/logging" + thutils "github.com/hashicorp/vault/sdk/helper/testhelpers/utils" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/vault" ) @@ -55,7 +55,7 @@ func TestOCIEndToEnd(t *testing.T) { envVarOCITestPrivateKeyPath, envVAROCITestOCIDList, } - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) logger := logging.NewVaultLogger(hclog.Trace) coreConfig := &vault.CoreConfig{ diff --git a/go.mod b/go.mod index 8497ece17c..0a29394851 100644 --- a/go.mod +++ b/go.mod @@ -164,7 +164,7 @@ require ( github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.16.0 github.com/hashicorp/vault-plugin-secrets-openldap v0.17.0 github.com/hashicorp/vault-plugin-secrets-terraform v0.13.0 - github.com/hashicorp/vault-testing-stepwise v0.3.2 + github.com/hashicorp/vault-testing-stepwise v0.3.3 github.com/hashicorp/vault/api v1.22.0 github.com/hashicorp/vault/api/auth/approle v0.1.0 github.com/hashicorp/vault/api/auth/userpass v0.1.0 diff --git a/go.sum b/go.sum index c8604fa285..7171d57bec 100644 --- a/go.sum +++ b/go.sum @@ -1597,8 +1597,8 @@ github.com/hashicorp/vault-plugin-secrets-openldap v0.17.0 h1:GpgYcuBL66zzFLkf14 github.com/hashicorp/vault-plugin-secrets-openldap v0.17.0/go.mod h1:UPWSw0hYY37sC4MeeoG9G8jN88DYi3L4MeJjRauhaBI= github.com/hashicorp/vault-plugin-secrets-terraform v0.13.0 h1:Rhahoi3L1dnZjNqlbUh1f59DMdmfdhsfBvaaX1vjejY= github.com/hashicorp/vault-plugin-secrets-terraform v0.13.0/go.mod h1:N1fdq0KpTbK/S4Yc4I04JqJ64+mkya4SZ+ychIYd3E4= -github.com/hashicorp/vault-testing-stepwise v0.3.2 h1:FCe0yrbK/hHiHqzu7utLcvCTTKjghWHyXwOQ2lxfoQM= -github.com/hashicorp/vault-testing-stepwise v0.3.2/go.mod h1:aI3k4Nu6TjBKxatj8plXKn8LhA9qb2TeeJyz2psHXEw= +github.com/hashicorp/vault-testing-stepwise v0.3.3 h1:/PQhXpJln7UQf3NJmG61ucAxsvttd+a0kb5NKW01iIA= +github.com/hashicorp/vault-testing-stepwise v0.3.3/go.mod h1:QzyV6ePJn+zQNouFkrAvR26gJlnZl/mBqhWrgfmwvJA= github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77 h1:Y/+BtwxmRak3Us9jrByARvYW6uNeqZlEpMylIdXVIjY= github.com/hashicorp/vault/vault/hcp_link/proto v0.0.0-20230201201504-b741fa893d77/go.mod h1:a2crHoMWwY6aiL8GWT8hYj7vKD64uX0EdRPbnsHF5wU= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw= diff --git a/helper/testhelpers/logical/testing.go b/helper/testhelpers/logical/testing.go index d6278b5211..e1c27fb7a7 100644 --- a/helper/testhelpers/logical/testing.go +++ b/helper/testhelpers/logical/testing.go @@ -433,6 +433,11 @@ func TestCheckMulti(fs ...TestCheckFunc) TestCheckFunc { // TestCheckAuth is a helper to check that a request generated an // auth token with the proper policies. +// +// Deprecated: As we externalize plugins, we move to use +// github.com/hashicorp/vault-testing-stepwise as the vault plugin unit test +// framework. We use NewAssertAuthPoliciesFunc in sdk/helper/testhelpers/stepwise +// instead of this function. func TestCheckAuth(policies []string) TestCheckFunc { return func(resp *logical.Response) error { if resp == nil || resp.Auth == nil { diff --git a/helper/testhelpers/testhelpers.go b/helper/testhelpers/testhelpers.go index 9d708d54d0..9a8b688f77 100644 --- a/helper/testhelpers/testhelpers.go +++ b/helper/testhelpers/testhelpers.go @@ -12,7 +12,6 @@ import ( "io" "math/rand" "os" - "strings" "testing" "time" @@ -957,16 +956,6 @@ func SetupLoginMFATOTP(t testing.TB, client *api.Client, methodName string, wait return entityClient, entityID, methodID } -func SkipUnlessEnvVarsSet(t testing.TB, envVars []string) { - t.Helper() - - for _, i := range envVars { - if os.Getenv(i) == "" { - t.Skipf("%s must be set for this test to run", strings.Join(envVars, " ")) - } - } -} - // WaitForNodesExcludingSelectedStandbys is variation on WaitForActiveNodeAndStandbys. // It waits for the active node before waiting for standby nodes, however // it will not wait for cores with indexes that match those specified as arguments. diff --git a/plugins/database/redshift/redshift_test.go b/plugins/database/redshift/redshift_test.go index 09e4c00f05..630afe51df 100644 --- a/plugins/database/redshift/redshift_test.go +++ b/plugins/database/redshift/redshift_test.go @@ -14,10 +14,10 @@ import ( "time" "github.com/hashicorp/go-uuid" - "github.com/hashicorp/vault/helper/testhelpers" dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5" dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing" "github.com/hashicorp/vault/sdk/helper/dbtxn" + thutils "github.com/hashicorp/vault/sdk/helper/testhelpers/utils" "github.com/stretchr/testify/require" ) @@ -81,7 +81,7 @@ func TestRedshift_Initialize(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, _, _, _, err := redshiftEnv() if err != nil { @@ -122,7 +122,7 @@ func TestRedshift_NewUser(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, url, _, _, err := redshiftEnv() if err != nil { @@ -175,7 +175,7 @@ func TestRedshift_NewUser_NoCreationStatement_ShouldError(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, _, _, _, err := redshiftEnv() if err != nil { @@ -221,7 +221,7 @@ func TestRedshift_UpdateUser_Expiration(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, url, _, _, err := redshiftEnv() if err != nil { @@ -284,7 +284,7 @@ func TestRedshift_UpdateUser_Password(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, url, _, _, err := redshiftEnv() if err != nil { @@ -341,7 +341,7 @@ func TestRedshift_DeleteUser(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, url, _, _, err := redshiftEnv() if err != nil { @@ -409,7 +409,7 @@ func TestRedshift_DefaultUsernameTemplate(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, url, _, _, err := redshiftEnv() if err != nil { @@ -460,7 +460,7 @@ func TestRedshift_CustomUsernameTemplate(t *testing.T) { } // Ensure each cred is populated. - testhelpers.SkipUnlessEnvVarsSet(t, credNames) + thutils.SkipUnlessEnvVarsSet(t, credNames) connURL, url, _, _, err := redshiftEnv() if err != nil { diff --git a/sdk/helper/testhelpers/stepwise/funcs.go b/sdk/helper/testhelpers/stepwise/funcs.go new file mode 100644 index 0000000000..5640dcfed2 --- /dev/null +++ b/sdk/helper/testhelpers/stepwise/funcs.go @@ -0,0 +1,37 @@ +// Copyright IBM Corp. 2016, 2025 +// SPDX-License-Identifier: MPL-2.0 + +package stepwise + +import ( + "fmt" + "reflect" + "sort" + + "github.com/hashicorp/vault/api" +) + +// NewAssertAuthPoliciesFunc returns a function that checks that the auth's +// policies in the response matches the expected policies. +func NewAssertAuthPoliciesFunc(policies []string) func(resp *api.Secret, err error) error { + return func(resp *api.Secret, err error) error { + if err != nil { + return err + } + + if resp == nil || resp.Auth == nil { + return fmt.Errorf("no auth in response") + } + expected := make([]string, len(policies)) + copy(expected, policies) + sort.Strings(expected) + ret := make([]string, len(resp.Auth.Policies)) + copy(ret, resp.Auth.Policies) + sort.Strings(ret) + if !reflect.DeepEqual(ret, expected) { + return fmt.Errorf("invalid policies: expected %#v, got %#v", expected, ret) + } + + return nil + } +} diff --git a/sdk/helper/testhelpers/utils/utils.go b/sdk/helper/testhelpers/utils/utils.go new file mode 100644 index 0000000000..b0b64bcb52 --- /dev/null +++ b/sdk/helper/testhelpers/utils/utils.go @@ -0,0 +1,22 @@ +// Copyright IBM Corp. 2016, 2025 +// SPDX-License-Identifier: MPL-2.0 + +package utils + +import ( + "os" + "strings" + "testing" +) + +// SkipUnlessEnvVarsSet skips the test unless all of the given environment +// variables are set +func SkipUnlessEnvVarsSet(t testing.TB, envVars []string) { + t.Helper() + + for _, i := range envVars { + if os.Getenv(i) == "" { + t.Skipf("%s must be set for this test to run", strings.Join(envVars, " ")) + } + } +}