| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package aws |
| |
| import ( |
| "context" |
| "strings" |
| "testing" |
| |
| "github.com/hashicorp/vault/sdk/logical" |
| "github.com/stretchr/testify/require" |
| ) |
| |
| func TestNormalizeDisplayName_NormRequired(t *testing.T) { |
| invalidNames := map[string]string{ |
| "^#$test name\nshould be normalized)(*": "___test_name_should_be_normalized___", |
| "^#$test name1 should be normalized)(*": "___test_name1_should_be_normalized___", |
| "^#$test name should be normalized)(*": "___test_name__should_be_normalized___", |
| "^#$test name__should be normalized)(*": "___test_name__should_be_normalized___", |
| } |
| |
| for k, v := range invalidNames { |
| normalizedName := normalizeDisplayName(k) |
| if normalizedName != v { |
| t.Fatalf( |
| "normalizeDisplayName does not normalize AWS name correctly: %s should resolve to %s", |
| k, |
| normalizedName) |
| } |
| } |
| } |
| |
| func TestNormalizeDisplayName_NormNotRequired(t *testing.T) { |
| validNames := []string{ |
| "test_name_should_normalize_to_itself@example.com", |
| "test1_name_should_normalize_to_itself@example.com", |
| "UPPERlower0123456789-_,.@example.com", |
| } |
| |
| for _, n := range validNames { |
| normalizedName := normalizeDisplayName(n) |
| if normalizedName != n { |
| t.Fatalf( |
| "normalizeDisplayName erroneously normalizes valid names: expected %s but normalized to %s", |
| n, |
| normalizedName) |
| } |
| } |
| } |
| |
| func TestGenUsername(t *testing.T) { |
| type testCase struct { |
| name string |
| policy string |
| userType string |
| UsernameTemplate string |
| expectedError string |
| expectedRegex string |
| expectedLength int |
| } |
| |
| tests := map[string]testCase{ |
| "Truncated to 64. No warnings expected": { |
| name: "name1", |
| policy: "policy1", |
| userType: "iam_user", |
| UsernameTemplate: defaultUserNameTemplate, |
| expectedError: "", |
| expectedRegex: `^vault-name1-policy1-[0-9]+-[a-zA-Z0-9]+`, |
| expectedLength: 64, |
| }, |
| "Truncated to 32. No warnings expected": { |
| name: "name1", |
| policy: "policy1", |
| userType: "sts", |
| UsernameTemplate: defaultUserNameTemplate, |
| expectedError: "", |
| expectedRegex: `^vault-[0-9]+-[a-zA-Z0-9]+`, |
| expectedLength: 32, |
| }, |
| "Too long. Error expected — IAM": { |
| name: "this---is---a---very---long---name", |
| policy: "long------policy------name", |
| userType: "assume_role", |
| UsernameTemplate: `{{ if (eq .Type "IAM") }}{{ printf "%s-%s-%s-%s" (.DisplayName) (.PolicyName) (unix_time) (random 20) }}{{ end }}`, |
| expectedError: "the username generated by the template exceeds the IAM username length limits of 64 chars", |
| expectedRegex: "", |
| expectedLength: 64, |
| }, |
| "Too long. Error expected — STS": { |
| name: "this---is---a---very---long---name", |
| policy: "long------policy------name", |
| userType: "sts", |
| UsernameTemplate: `{{ if (eq .Type "STS") }}{{ printf "%s-%s-%s-%s" (.DisplayName) (.PolicyName) (unix_time) (random 20) }}{{ end }}`, |
| expectedError: "the username generated by the template exceeds the STS username length limits of 32 chars", |
| expectedRegex: "", |
| expectedLength: 32, |
| }, |
| } |
| |
| for testDescription, testCase := range tests { |
| t.Run(testDescription, func(t *testing.T) { |
| testUsername, err := genUsername(testCase.name, testCase.policy, testCase.userType, testCase.UsernameTemplate) |
| if err != nil && !strings.Contains(err.Error(), testCase.expectedError) { |
| t.Fatalf("expected an error %s; instead received %s", testCase.expectedError, err) |
| } |
| |
| if err == nil { |
| require.Regexp(t, testCase.expectedRegex, testUsername) |
| |
| if len(testUsername) > testCase.expectedLength { |
| t.Fatalf("expected username to be of length %d, got %d", testCase.expectedLength, len(testUsername)) |
| } |
| } |
| }) |
| } |
| } |
| |
| func TestReadConfig_DefaultTemplate(t *testing.T) { |
| config := logical.TestBackendConfig() |
| config.StorageView = &logical.InmemStorage{} |
| b := Backend(config) |
| if err := b.Setup(context.Background(), config); err != nil { |
| t.Fatal(err) |
| } |
| |
| testTemplate := "" |
| configData := map[string]interface{}{ |
| "connection_uri": "test_uri", |
| "username": "guest", |
| "password": "guest", |
| "username_template": testTemplate, |
| } |
| configReq := &logical.Request{ |
| Operation: logical.UpdateOperation, |
| Path: "config/root", |
| Storage: config.StorageView, |
| Data: configData, |
| } |
| resp, err := b.HandleRequest(context.Background(), configReq) |
| if err != nil || (resp != nil && resp.IsError()) { |
| t.Fatalf("bad: resp: %#v\nerr:%s", resp, err) |
| } |
| if resp != nil { |
| t.Fatal("expected a nil response") |
| } |
| |
| configResult, err := readConfig(context.Background(), config.StorageView) |
| if err != nil { |
| t.Fatalf("expected err to be nil; got %s", err) |
| } |
| |
| // No template provided, config set to defaultUsernameTemplate |
| if configResult.UsernameTemplate != defaultUserNameTemplate { |
| t.Fatalf( |
| "expected template %s; got %s", |
| defaultUserNameTemplate, |
| configResult.UsernameTemplate, |
| ) |
| } |
| } |
| |
| func TestReadConfig_CustomTemplate(t *testing.T) { |
| config := logical.TestBackendConfig() |
| config.StorageView = &logical.InmemStorage{} |
| b := Backend(config) |
| if err := b.Setup(context.Background(), config); err != nil { |
| t.Fatal(err) |
| } |
| |
| testTemplate := "`foo-{{ .DisplayName }}`" |
| configData := map[string]interface{}{ |
| "connection_uri": "test_uri", |
| "username": "guest", |
| "password": "guest", |
| "username_template": testTemplate, |
| } |
| configReq := &logical.Request{ |
| Operation: logical.UpdateOperation, |
| Path: "config/root", |
| Storage: config.StorageView, |
| Data: configData, |
| } |
| resp, err := b.HandleRequest(context.Background(), configReq) |
| if err != nil || (resp != nil && resp.IsError()) { |
| t.Fatalf("bad: resp: %#v\nerr:%s", resp, err) |
| } |
| if resp != nil { |
| t.Fatal("expected a nil response") |
| } |
| |
| configResult, err := readConfig(context.Background(), config.StorageView) |
| if err != nil { |
| t.Fatalf("expected err to be nil; got %s", err) |
| } |
| |
| if configResult.UsernameTemplate != testTemplate { |
| t.Fatalf( |
| "expected template %s; got %s", |
| testTemplate, |
| configResult.UsernameTemplate, |
| ) |
| } |
| } |