github.com/opentofu/opentofu@v1.7.1/internal/encryption/keyprovider/aws_kms/config_test.go (about) 1 package aws_kms 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 "time" 8 9 "github.com/aws/aws-sdk-go-v2/aws" 10 "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" 11 "github.com/aws/aws-sdk-go-v2/service/kms/types" 12 "github.com/davecgh/go-spew/spew" 13 awsbase "github.com/hashicorp/aws-sdk-go-base/v2" 14 "github.com/hashicorp/hcl/v2" 15 "github.com/hashicorp/hcl/v2/hclsyntax" 16 "github.com/opentofu/opentofu/internal/gohcl" 17 "github.com/opentofu/opentofu/internal/httpclient" 18 "github.com/opentofu/opentofu/version" 19 ) 20 21 func TestConfig_asAWSBase(t *testing.T) { 22 testCases := []struct { 23 name string 24 input string 25 expected awsbase.Config 26 }{ 27 { 28 name: "minconfig", 29 input: ` 30 kms_key_id = "my-kms-key-id" 31 key_spec = "AES_256" 32 region = "magic-mountain"`, 33 expected: awsbase.Config{ 34 Region: "magic-mountain", 35 CallerDocumentationURL: "https://opentofu.org/docs/language/settings/backends/s3", 36 CallerName: "KMS Key Provider", 37 MaxRetries: 5, 38 UserAgent: awsbase.UserAgentProducts{ 39 {Name: "APN", Version: "1.0"}, 40 {Name: httpclient.DefaultApplicationName, Version: version.String()}, 41 }, 42 }, 43 }, 44 { 45 name: "maxconfig", 46 input: ` 47 kms_key_id = "my-kms-key-id" 48 key_spec = "AES_256" 49 50 access_key = "my-access-key" 51 endpoints { 52 iam = "endpoint-iam" 53 sts = "endpoint-sts" 54 } 55 max_retries = 42 56 profile = "my-profile" 57 region = "my-region" 58 secret_key = "my-secret-key" 59 skip_credentials_validation = true 60 skip_requesting_account_id = true 61 sts_region = "my-sts-region" 62 token = "my-token" 63 http_proxy = "my-http-proxy" 64 https_proxy = "my-https-proxy" 65 no_proxy = "my-noproxy" 66 insecure = true 67 use_dualstack_endpoint = true 68 use_fips_endpoint = true 69 custom_ca_bundle = "my-custom-ca-bundle" 70 ec2_metadata_service_endpoint = "my-emde" 71 ec2_metadata_service_endpoint_mode = "my-emde-mode" 72 skip_metadata_api_check = false 73 shared_credentials_files = ["my-scredf"] 74 shared_config_files = ["my-sconff"] 75 assume_role = { 76 role_arn = "ar_arn" 77 duration = "4h" 78 external_id = "ar_extid" 79 policy = "ar_policy" 80 policy_arns = ["arn:aws:iam::123456789012:policy/AR"] 81 session_name = "ar_session_name" 82 tags = { 83 foo = "bar" 84 } 85 transitive_tag_keys = ["ar_tags"] 86 } 87 assume_role_with_web_identity = { 88 role_arn = "wi_arn" 89 duration = "5h" 90 policy = "wi_policy" 91 policy_arns = ["arn:aws:iam::123456789012:policy/WI"] 92 session_name = "wi_session_name" 93 web_identity_token = "wi_token" 94 //web_identity_token_file = "wi_token_file" 95 } 96 allowed_account_ids = ["account"] 97 //forbidden_account_ids = ? 98 retry_mode = "adaptive" 99 `, 100 expected: awsbase.Config{ 101 CallerDocumentationURL: "https://opentofu.org/docs/language/settings/backends/s3", 102 CallerName: "KMS Key Provider", 103 UserAgent: awsbase.UserAgentProducts{ 104 {Name: "APN", Version: "1.0"}, 105 {Name: httpclient.DefaultApplicationName, Version: version.String()}, 106 }, 107 108 AccessKey: "my-access-key", 109 IamEndpoint: "https://endpoint-iam", 110 MaxRetries: 42, 111 Profile: "my-profile", 112 Region: "my-region", 113 SecretKey: "my-secret-key", 114 SkipCredsValidation: true, 115 SkipRequestingAccountId: true, 116 StsEndpoint: "https://endpoint-sts", 117 StsRegion: "my-sts-region", 118 Token: "my-token", 119 HTTPProxy: aws.String("my-http-proxy"), 120 HTTPSProxy: aws.String("my-https-proxy"), 121 NoProxy: "my-noproxy", 122 Insecure: true, 123 UseDualStackEndpoint: true, 124 UseFIPSEndpoint: true, 125 CustomCABundle: "my-custom-ca-bundle", 126 EC2MetadataServiceEnableState: imds.ClientDisabled, 127 EC2MetadataServiceEndpoint: "my-emde", 128 EC2MetadataServiceEndpointMode: "my-emde-mode", 129 SharedCredentialsFiles: []string{"my-scredf"}, 130 SharedConfigFiles: []string{"my-sconff"}, 131 AssumeRole: &awsbase.AssumeRole{ 132 RoleARN: "ar_arn", 133 Duration: time.Hour * 4, 134 ExternalID: "ar_extid", 135 Policy: "ar_policy", 136 PolicyARNs: []string{ 137 "arn:aws:iam::123456789012:policy/AR", 138 }, 139 SessionName: "ar_session_name", 140 Tags: map[string]string{ 141 "foo": "bar", 142 }, 143 TransitiveTagKeys: []string{ 144 "ar_tags", 145 }, 146 }, 147 AssumeRoleWithWebIdentity: &awsbase.AssumeRoleWithWebIdentity{ 148 RoleARN: "wi_arn", 149 Duration: time.Hour * 5, 150 Policy: "wi_policy", 151 PolicyARNs: []string{ 152 "arn:aws:iam::123456789012:policy/WI", 153 }, 154 SessionName: "wi_session_name", 155 WebIdentityToken: "wi_token", 156 WebIdentityTokenFile: "", 157 }, 158 AllowedAccountIds: []string{"account"}, 159 RetryMode: aws.RetryModeAdaptive, 160 }, 161 }, 162 } 163 164 for _, tc := range testCases { 165 t.Run(tc.name, func(t *testing.T) { 166 input, diags := hclsyntax.ParseConfig([]byte(tc.input), "test", hcl.InitialPos) 167 if diags.HasErrors() { 168 t.Fatal(diags.Error()) 169 } 170 171 config := new(Config) 172 173 diags = gohcl.DecodeBody(input.Body, nil, config) 174 if diags.HasErrors() { 175 t.Fatal(diags.Error()) 176 } 177 178 if config.KMSKeyID != "my-kms-key-id" { 179 t.Fatal("missing kms_key_id") 180 } 181 if config.KeySpec != "AES_256" { 182 t.Fatal("missing key_spec") 183 } 184 185 actual, err := config.asAWSBase() 186 if err != nil { 187 t.Fatal(err.Error()) 188 } 189 if !reflect.DeepEqual(tc.expected, *actual) { 190 t.Fatalf("Expected %s, got %s", spew.Sdump(tc.expected), spew.Sdump(*actual)) 191 } 192 }) 193 } 194 } 195 196 func TestValidate(t *testing.T) { 197 testCases := []struct { 198 name string 199 input Config 200 expected error 201 }{ 202 { 203 name: "valid", 204 input: Config{ 205 KMSKeyID: "my-kms-key-id", 206 KeySpec: "AES_256", 207 }, 208 expected: nil, 209 }, 210 { 211 name: "missing kms_key_id", 212 input: Config{ 213 KMSKeyID: "", 214 KeySpec: "AES_256", 215 }, 216 expected: fmt.Errorf("no kms_key_id provided"), 217 }, 218 { 219 name: "missing key_spec", 220 input: Config{ 221 KMSKeyID: "my-kms-key-id", 222 KeySpec: "", 223 }, 224 expected: fmt.Errorf("no key_spec provided"), 225 }, 226 { 227 name: "invalid key_spec", 228 input: Config{ 229 KMSKeyID: "my-kms-key-id", 230 KeySpec: "invalid??", 231 }, 232 }, 233 } 234 235 for _, tc := range testCases { 236 t.Run(tc.name, func(t *testing.T) { 237 err := tc.input.validate() 238 // check if the error message is the same 239 if tc.expected != nil { 240 if err.Error() != tc.expected.Error() { 241 t.Fatalf("Expected %q, got %q", tc.expected.Error(), err.Error()) 242 } 243 } 244 }) 245 } 246 } 247 248 func TestGetKeySpecAsAWSType(t *testing.T) { 249 250 aes256 := types.DataKeySpecAes256 251 aes128 := types.DataKeySpecAes128 252 253 cases := []struct { 254 key string 255 expected *types.DataKeySpec 256 }{ 257 { 258 key: "AES_256", 259 expected: &aes256, 260 }, 261 { 262 key: "AES_128", 263 expected: &aes128, 264 }, 265 { 266 key: "", 267 expected: nil, 268 }, 269 { 270 key: "invalidKey", 271 expected: nil, 272 }, 273 } 274 275 for _, c := range cases { 276 t.Run(c.key, func(t *testing.T) { 277 config := Config{ 278 KeySpec: c.key, 279 } 280 actual := config.getKeySpecAsAWSType() 281 if !reflect.DeepEqual(c.expected, actual) { 282 t.Fatalf("Expected %s, got %s", spew.Sdump(c.expected), spew.Sdump(actual)) 283 } 284 }) 285 } 286 }