Files
opentf/internal/encryption/keyprovider/aws_kms/config_test.go

297 lines
7.6 KiB
Go

// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package aws_kms
import (
"fmt"
"reflect"
"testing"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go-v2/service/kms/types"
"github.com/davecgh/go-spew/spew"
awsbase "github.com/hashicorp/aws-sdk-go-base/v2"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/opentofu/opentofu/internal/httpclient"
"github.com/opentofu/opentofu/version"
)
func TestConfig_asAWSBase(t *testing.T) {
testCases := []struct {
name string
input string
expected awsbase.Config
}{
{
name: "minconfig",
input: `
kms_key_id = "my-kms-key-id"
key_spec = "AES_256"
region = "magic-mountain"`,
expected: awsbase.Config{
Region: "magic-mountain",
CallerDocumentationURL: "https://opentofu.org/docs/language/settings/backends/s3",
CallerName: "KMS Key Provider",
MaxRetries: 5,
APNInfo: &awsbase.APNInfo{
PartnerName: "OpenTofu-AWS-KMS",
Products: []awsbase.UserAgentProduct{
{Name: httpclient.DefaultApplicationName, Version: version.String()},
},
},
},
},
{
name: "maxconfig",
input: `
kms_key_id = "my-kms-key-id"
key_spec = "AES_256"
access_key = "my-access-key"
endpoints {
iam = "endpoint-iam"
sts = "endpoint-sts"
}
max_retries = 42
profile = "my-profile"
region = "my-region"
secret_key = "my-secret-key"
skip_credentials_validation = true
skip_requesting_account_id = true
sts_region = "my-sts-region"
token = "my-token"
http_proxy = "my-http-proxy"
https_proxy = "my-https-proxy"
no_proxy = "my-noproxy"
insecure = true
use_dualstack_endpoint = true
use_fips_endpoint = true
custom_ca_bundle = "my-custom-ca-bundle"
ec2_metadata_service_endpoint = "my-emde"
ec2_metadata_service_endpoint_mode = "my-emde-mode"
skip_metadata_api_check = false
shared_credentials_files = ["my-scredf"]
shared_config_files = ["my-sconff"]
assume_role = {
role_arn = "ar_arn"
duration = "4h"
external_id = "ar_extid"
policy = "ar_policy"
policy_arns = ["arn:aws:iam::123456789012:policy/AR"]
session_name = "ar_session_name"
tags = {
foo = "bar"
}
transitive_tag_keys = ["ar_tags"]
}
assume_role_with_web_identity = {
role_arn = "wi_arn"
duration = "5h"
policy = "wi_policy"
policy_arns = ["arn:aws:iam::123456789012:policy/WI"]
session_name = "wi_session_name"
web_identity_token = "wi_token"
//web_identity_token_file = "wi_token_file"
}
allowed_account_ids = ["account"]
//forbidden_account_ids = ?
retry_mode = "adaptive"
`,
expected: awsbase.Config{
CallerDocumentationURL: "https://opentofu.org/docs/language/settings/backends/s3",
CallerName: "KMS Key Provider",
APNInfo: &awsbase.APNInfo{
PartnerName: "OpenTofu-AWS-KMS",
Products: []awsbase.UserAgentProduct{
{Name: httpclient.DefaultApplicationName, Version: version.String()},
},
},
AccessKey: "my-access-key",
IamEndpoint: "https://endpoint-iam",
MaxRetries: 42,
Profile: "my-profile",
Region: "my-region",
SecretKey: "my-secret-key",
SkipCredsValidation: true,
SkipRequestingAccountId: true,
StsEndpoint: "https://endpoint-sts",
StsRegion: "my-sts-region",
Token: "my-token",
HTTPProxy: aws.String("my-http-proxy"),
HTTPSProxy: aws.String("my-https-proxy"),
NoProxy: "my-noproxy",
Insecure: true,
UseDualStackEndpoint: true,
UseFIPSEndpoint: true,
CustomCABundle: "my-custom-ca-bundle",
EC2MetadataServiceEnableState: imds.ClientDisabled,
EC2MetadataServiceEndpoint: "my-emde",
EC2MetadataServiceEndpointMode: "my-emde-mode",
SharedCredentialsFiles: []string{"my-scredf"},
SharedConfigFiles: []string{"my-sconff"},
AssumeRole: []awsbase.AssumeRole{
{
RoleARN: "ar_arn",
Duration: time.Hour * 4,
ExternalID: "ar_extid",
Policy: "ar_policy",
PolicyARNs: []string{
"arn:aws:iam::123456789012:policy/AR",
},
SessionName: "ar_session_name",
Tags: map[string]string{
"foo": "bar",
},
TransitiveTagKeys: []string{
"ar_tags",
},
},
},
AssumeRoleWithWebIdentity: &awsbase.AssumeRoleWithWebIdentity{
RoleARN: "wi_arn",
Duration: time.Hour * 5,
Policy: "wi_policy",
PolicyARNs: []string{
"arn:aws:iam::123456789012:policy/WI",
},
SessionName: "wi_session_name",
WebIdentityToken: "wi_token",
WebIdentityTokenFile: "",
},
AllowedAccountIds: []string{"account"},
RetryMode: aws.RetryModeAdaptive,
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
input, diags := hclsyntax.ParseConfig([]byte(tc.input), "test", hcl.InitialPos)
if diags.HasErrors() {
t.Fatal(diags.Error())
}
config := new(Config)
diags = gohcl.DecodeBody(input.Body, nil, config)
if diags.HasErrors() {
t.Fatal(diags.Error())
}
if config.KMSKeyID != "my-kms-key-id" {
t.Fatal("missing kms_key_id")
}
if config.KeySpec != "AES_256" {
t.Fatal("missing key_spec")
}
actual, err := config.asAWSBase()
if err != nil {
t.Fatal(err.Error())
}
if !reflect.DeepEqual(tc.expected, *actual) {
t.Fatalf("Expected %s, got %s", spew.Sdump(tc.expected), spew.Sdump(*actual))
}
})
}
}
func TestValidate(t *testing.T) {
testCases := []struct {
name string
input Config
expected error
}{
{
name: "valid",
input: Config{
KMSKeyID: "my-kms-key-id",
KeySpec: "AES_256",
},
expected: nil,
},
{
name: "missing kms_key_id",
input: Config{
KMSKeyID: "",
KeySpec: "AES_256",
},
expected: fmt.Errorf("no kms_key_id provided"),
},
{
name: "missing key_spec",
input: Config{
KMSKeyID: "my-kms-key-id",
KeySpec: "",
},
expected: fmt.Errorf("no key_spec provided"),
},
{
name: "invalid key_spec",
input: Config{
KMSKeyID: "my-kms-key-id",
KeySpec: "invalid??",
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.input.validate()
// check if the error message is the same
if tc.expected != nil {
if err.Error() != tc.expected.Error() {
t.Fatalf("Expected %q, got %q", tc.expected.Error(), err.Error())
}
}
})
}
}
func TestGetKeySpecAsAWSType(t *testing.T) {
aes256 := types.DataKeySpecAes256
aes128 := types.DataKeySpecAes128
cases := []struct {
key string
expected *types.DataKeySpec
}{
{
key: "AES_256",
expected: &aes256,
},
{
key: "AES_128",
expected: &aes128,
},
{
key: "",
expected: nil,
},
{
key: "invalidKey",
expected: nil,
},
}
for _, c := range cases {
t.Run(c.key, func(t *testing.T) {
config := Config{
KeySpec: c.key,
}
actual := config.getKeySpecAsAWSType()
if !reflect.DeepEqual(c.expected, actual) {
t.Fatalf("Expected %s, got %s", spew.Sdump(c.expected), spew.Sdump(actual))
}
})
}
}