feat(cli) Implement parsing of target-prefixed attrs for cross account dynamic host catalogs (#84)
This commit is contained in:
1 parent
0d36d4de0b
commit
0cd593a433
5 files changed
+505
-2
No files matched your search
@@ -186,3 +186,63 @@ func GetCredentialAttributes(in *structpb.Struct) (*CredentialAttributes, error)
|
||||
RoleTags: roleTags,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetTargetCredentialAttributes parses values out of a protobuf struct input and returns a CredentialAttributes used
|
||||
// for configuring a second AWS session. target_role_arn is required when parsing target credentials.
|
||||
// A status error is returned with an InvalidArgument code when target account attributes are missing
|
||||
// required values or have invalid value types.
|
||||
func GetTargetCredentialAttributes(in *structpb.Struct) (*CredentialAttributes, error) {
|
||||
badFields := make(map[string]string)
|
||||
|
||||
// Parse the role ARN of the target account to AssumeRole into.
|
||||
targetRoleArn, err := values.GetStringValue(in, ConstTargetRoleArn, true)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstTargetRoleArn)] = err.Error()
|
||||
}
|
||||
|
||||
// try parsing target_region, fallback to region, adds target_region to bad fields only when malformed since not required
|
||||
targetRegion, err := values.GetStringValue(in, ConstTargetRegion, false)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstTargetRegion)] = err.Error()
|
||||
}
|
||||
if targetRegion == "" {
|
||||
targetRegion, err = values.GetStringValue(in, ConstRegion, true) // region is required for processing
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstRegion)] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// the remaining fields are optional and only raise errors when malformed
|
||||
disableCredentialRotation, err := values.GetBoolValue(in, ConstDisableCredentialRotation, false)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstDisableCredentialRotation)] = err.Error()
|
||||
}
|
||||
|
||||
targetRoleExternalId, err := values.GetStringValue(in, ConstTargetRoleExternalId, false)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstTargetRoleExternalId)] = err.Error()
|
||||
}
|
||||
|
||||
targetRoleSessionName, err := values.GetStringValue(in, ConstTargetRoleSessionName, false)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstTargetRoleSessionName)] = err.Error()
|
||||
}
|
||||
|
||||
targetRoleTags, err := values.GetMapStringString(in, ConstTargetRoleTags, false)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstTargetRoleTags)] = err.Error()
|
||||
}
|
||||
|
||||
if len(badFields) > 0 {
|
||||
return nil, errors.InvalidArgumentError("Error in the attributes provided", badFields)
|
||||
}
|
||||
|
||||
return &CredentialAttributes{
|
||||
Region: targetRegion,
|
||||
DisableCredentialRotation: disableCredentialRotation,
|
||||
RoleArn: targetRoleArn,
|
||||
RoleExternalId: targetRoleExternalId,
|
||||
RoleSessionName: targetRoleSessionName,
|
||||
RoleTags: targetRoleTags,
|
||||
}, nil
|
||||
}
|
||||
@@ -101,6 +101,232 @@ func TestGetCredentialAttributes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTargetCredentialAttributes(t *testing.T) {
|
||||
const targetRoleArn = "arn:aws:iam::222222222222:role/Target"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
in map[string]any
|
||||
expected *CredentialAttributes
|
||||
expectedErrContains string
|
||||
}{
|
||||
{
|
||||
name: "missing target_role_arn",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: missing required value \"target_role_arn\"",
|
||||
},
|
||||
{
|
||||
name: "missing target_role_arn and region",
|
||||
in: map[string]any{},
|
||||
expectedErrContains: "attributes.target_role_arn: missing required value \"target_role_arn\"",
|
||||
},
|
||||
{
|
||||
name: "empty target_role_arn",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: "",
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: value \"target_role_arn\" cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "wrong type target_role_arn",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: true,
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: unexpected type for value \"target_role_arn\": want string, got bool",
|
||||
},
|
||||
{
|
||||
name: "target_region without target_role_arn",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRegion: "eu-west-1",
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: missing required value \"target_role_arn\"",
|
||||
},
|
||||
{
|
||||
name: "other target fields without target_role_arn",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleExternalId: "ext",
|
||||
ConstTargetRoleSessionName: "sess",
|
||||
ConstTargetRoleTags: map[string]any{"k": "v"},
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: missing required value \"target_role_arn\"",
|
||||
},
|
||||
{
|
||||
name: "target_role_arn uses region when target_region omitted",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
},
|
||||
expected: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
RoleArn: targetRoleArn,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "target_role_arn without target_region or region",
|
||||
in: map[string]any{
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
},
|
||||
expectedErrContains: "missing required value \"region\"",
|
||||
},
|
||||
{
|
||||
name: "target_region overrides region",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRegion: "eu-west-1",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
},
|
||||
expected: &CredentialAttributes{
|
||||
Region: "eu-west-1",
|
||||
RoleArn: targetRoleArn,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty target_region falls back to region",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRegion: "",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
},
|
||||
expected: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
RoleArn: targetRoleArn,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all optional target fields",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstDisableCredentialRotation: true,
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
ConstTargetRegion: "eu-west-1",
|
||||
ConstTargetRoleExternalId: "target-ext",
|
||||
ConstTargetRoleSessionName: "target-sess",
|
||||
ConstTargetRoleTags: map[string]any{"env": "target"},
|
||||
},
|
||||
expected: &CredentialAttributes{
|
||||
Region: "eu-west-1",
|
||||
DisableCredentialRotation: true,
|
||||
RoleArn: targetRoleArn,
|
||||
RoleExternalId: "target-ext",
|
||||
RoleSessionName: "target-sess",
|
||||
RoleTags: map[string]string{"env": "target"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "optional target fields omitted do not copy principal role fields",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstRoleArn: "arn:aws:iam::111111111111:role/Principal",
|
||||
ConstRoleExternalId: "principal-ext",
|
||||
ConstRoleSessionName: "principal-sess",
|
||||
ConstRoleTags: map[string]any{"env": "principal"},
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
},
|
||||
expected: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
RoleArn: targetRoleArn,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "disable_credential_rotation false is copied",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstDisableCredentialRotation: false,
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
},
|
||||
expected: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
DisableCredentialRotation: false,
|
||||
RoleArn: targetRoleArn,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wrong type target_region",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
ConstTargetRegion: true,
|
||||
},
|
||||
expectedErrContains: "attributes.target_region: unexpected type for value \"target_region\": want string, got bool",
|
||||
},
|
||||
{
|
||||
name: "wrong type target_role_external_id",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
ConstTargetRoleExternalId: true,
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_external_id: unexpected type for value \"target_role_external_id\": want string, got bool",
|
||||
},
|
||||
{
|
||||
name: "wrong type target_role_session_name",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
ConstTargetRoleSessionName: true,
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_session_name: unexpected type for value \"target_role_session_name\": want string, got bool",
|
||||
},
|
||||
{
|
||||
name: "wrong type target_role_tags",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
ConstTargetRoleTags: true,
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_tags: unexpected type for value \"target_role_tags\": want map[string]string, got bool",
|
||||
},
|
||||
{
|
||||
name: "wrong type target_role_tag value",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
ConstTargetRoleTags: map[string]any{
|
||||
"env": true,
|
||||
},
|
||||
},
|
||||
expectedErrContains: `unexpected type for value in map["env"]: want string, got bool`,
|
||||
},
|
||||
{
|
||||
name: "wrong type disable_credential_rotation",
|
||||
in: map[string]any{
|
||||
ConstRegion: "us-west-2",
|
||||
ConstTargetRoleArn: targetRoleArn,
|
||||
ConstDisableCredentialRotation: "sure",
|
||||
},
|
||||
expectedErrContains: "attributes.disable_credential_rotation: unexpected type for value \"disable_credential_rotation\": want bool, got string",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
input, err := structpb.NewStruct(tc.in)
|
||||
require.NoError(err)
|
||||
|
||||
actual, err := GetTargetCredentialAttributes(input)
|
||||
if tc.expectedErrContains != "" {
|
||||
require.Error(err)
|
||||
require.Nil(actual)
|
||||
require.Contains(err.Error(), tc.expectedErrContains)
|
||||
require.Equal(codes.InvalidArgument, status.Code(err))
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(err)
|
||||
require.Equal(tc.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCredentialsConfig(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
package credential
|
||||
|
||||
const (
|
||||
// ConstAccessKey is the key for the region in the aws credentials.
|
||||
// ConstRegion is the key for the region in the aws credentials.
|
||||
ConstRegion = "region"
|
||||
|
||||
// ConstAccessKey is the key for the access key id in the aws credentials.
|
||||
// ConstAccessKeyId is the key for the access key id in the aws credentials.
|
||||
ConstAccessKeyId = "access_key_id"
|
||||
|
||||
// ConstSecretAccessKey is the key for the secret access key in the aws credentials.
|
||||
@@ -30,4 +30,19 @@ const (
|
||||
|
||||
// ConstRoleTags is the key for the tags used for assuming a IAM role.
|
||||
ConstRoleTags = "role_tags"
|
||||
|
||||
// ConstTargetRegion is the key for the region of the target account in the aws credentials.
|
||||
ConstTargetRegion = "target_region"
|
||||
|
||||
// ConstTargetRoleArn is the key for assuming a IAM role for the target account.
|
||||
ConstTargetRoleArn = "target_role_arn"
|
||||
|
||||
// ConstTargetRoleExternalId is the key for the external id used for assuming a IAM role for the target account.
|
||||
ConstTargetRoleExternalId = "target_role_external_id"
|
||||
|
||||
// ConstTargetRoleSessionName is the key for the session name used for assuming a IAM role of the target account.
|
||||
ConstTargetRoleSessionName = "target_role_session_name"
|
||||
|
||||
// ConstTargetRoleTags is the key for the tags used for assuming a IAM role of the target account.
|
||||
ConstTargetRoleTags = "target_role_tags"
|
||||
)
|
||||
@@ -20,6 +20,9 @@ import (
|
||||
type CatalogAttributes struct {
|
||||
*cred.CredentialAttributes
|
||||
|
||||
// TargetAccount optionally holds the credentials used to AssumeRole into a second, affiliated account when provided.
|
||||
TargetAccount *cred.CredentialAttributes
|
||||
|
||||
// DualStack is used for configuring how the aws client will resolve requests.
|
||||
DualStack bool
|
||||
|
||||
@@ -39,6 +42,14 @@ func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var targetCredAttributes *cred.CredentialAttributes
|
||||
if hasTargetAccountAttributes(in) {
|
||||
targetCredAttributes, err = cred.GetTargetCredentialAttributes(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
dualStack, err := values.GetBoolValue(in, ConstAwsDualStack, false)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstAwsDualStack)] = err.Error()
|
||||
@@ -66,6 +77,16 @@ func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
||||
continue
|
||||
case cred.ConstRoleTags:
|
||||
continue
|
||||
case cred.ConstTargetRegion:
|
||||
continue
|
||||
case cred.ConstTargetRoleArn:
|
||||
continue
|
||||
case cred.ConstTargetRoleExternalId:
|
||||
continue
|
||||
case cred.ConstTargetRoleSessionName:
|
||||
continue
|
||||
case cred.ConstTargetRoleTags:
|
||||
continue
|
||||
default:
|
||||
badFields[fmt.Sprintf("attributes.%s", s)] = "unrecognized field"
|
||||
}
|
||||
@@ -77,6 +98,7 @@ func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
||||
|
||||
return &CatalogAttributes{
|
||||
CredentialAttributes: credAttributes,
|
||||
TargetAccount: targetCredAttributes,
|
||||
DualStack: dualStack,
|
||||
InstanceAddressesOnly: instanceAddressesOnly,
|
||||
}, nil
|
||||
@@ -121,3 +143,19 @@ func getSetAttributes(in *structpb.Struct) (*SetAttributes, error) {
|
||||
|
||||
return &setAttrs, nil
|
||||
}
|
||||
|
||||
func hasTargetAccountAttributes(in *structpb.Struct) bool {
|
||||
fields := in.GetFields()
|
||||
|
||||
_, hasTargetRegion := fields[cred.ConstTargetRegion]
|
||||
_, hasTargetRoleArn := fields[cred.ConstTargetRoleArn]
|
||||
_, hasTargetRoleExternalID := fields[cred.ConstTargetRoleExternalId]
|
||||
_, hasTargetRoleSessionName := fields[cred.ConstTargetRoleSessionName]
|
||||
_, hasTargetRoleTags := fields[cred.ConstTargetRoleTags]
|
||||
|
||||
return hasTargetRegion ||
|
||||
hasTargetRoleArn ||
|
||||
hasTargetRoleExternalID ||
|
||||
hasTargetRoleSessionName ||
|
||||
hasTargetRoleTags
|
||||
}
|
||||
@@ -118,6 +118,170 @@ func TestGetCatalogAttributes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "target_region without target_role_arn",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"target_region": structpb.NewStringValue("eu-west-1"),
|
||||
},
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: missing required value \"target_role_arn\"",
|
||||
},
|
||||
{
|
||||
name: "target role field without target_role_arn",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"target_role_external_id": structpb.NewStringValue("target-ext"),
|
||||
},
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: missing required value \"target_role_arn\"",
|
||||
},
|
||||
{
|
||||
name: "other target role fields without target_role_arn",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"target_role_session_name": structpb.NewStringValue("target-session"),
|
||||
"target_role_tags": structpb.NewStructValue(&structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"env": structpb.NewStringValue("target"),
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: missing required value \"target_role_arn\"",
|
||||
},
|
||||
{
|
||||
name: "empty target_role_arn with target_region",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"target_role_arn": structpb.NewStringValue(""),
|
||||
"target_region": structpb.NewStringValue("eu-west-1"),
|
||||
},
|
||||
},
|
||||
expectedErrContains: "attributes.target_role_arn: value \"target_role_arn\" cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "target_role_arn without target_region uses region; principal sts fields are not copied",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"disable_credential_rotation": structpb.NewBoolValue(true),
|
||||
"role_arn": structpb.NewStringValue("arn:aws:iam::111111111111:role/Principal"),
|
||||
"role_external_id": structpb.NewStringValue("principal-ext"),
|
||||
"role_session_name": structpb.NewStringValue("principal-sess"),
|
||||
"role_tags": structpb.NewStructValue(&structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"env": structpb.NewStringValue("principal"),
|
||||
},
|
||||
}),
|
||||
"target_role_arn": structpb.NewStringValue("arn:aws:iam::222222222222:role/Target"),
|
||||
},
|
||||
},
|
||||
expected: &CatalogAttributes{
|
||||
CredentialAttributes: &cred.CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
DisableCredentialRotation: true,
|
||||
RoleArn: "arn:aws:iam::111111111111:role/Principal",
|
||||
RoleExternalId: "principal-ext",
|
||||
RoleSessionName: "principal-sess",
|
||||
RoleTags: map[string]string{
|
||||
"env": "principal",
|
||||
},
|
||||
},
|
||||
TargetAccount: &cred.CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
DisableCredentialRotation: true,
|
||||
RoleArn: "arn:aws:iam::222222222222:role/Target",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "target attributes are independent of principal",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"disable_credential_rotation": structpb.NewBoolValue(true),
|
||||
"role_arn": structpb.NewStringValue("arn:aws:iam::111111111111:role/Principal"),
|
||||
"role_external_id": structpb.NewStringValue("principal-ext"),
|
||||
"role_session_name": structpb.NewStringValue("principal-sess"),
|
||||
"role_tags": structpb.NewStructValue(&structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"env": structpb.NewStringValue("principal"),
|
||||
},
|
||||
}),
|
||||
"target_role_arn": structpb.NewStringValue("arn:aws:iam::222222222222:role/Target"),
|
||||
"target_region": structpb.NewStringValue("eu-west-1"),
|
||||
"target_role_external_id": structpb.NewStringValue("target-ext"),
|
||||
"target_role_session_name": structpb.NewStringValue("target-sess"),
|
||||
"target_role_tags": structpb.NewStructValue(&structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"env": structpb.NewStringValue("target"),
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
expected: &CatalogAttributes{
|
||||
CredentialAttributes: &cred.CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
DisableCredentialRotation: true,
|
||||
RoleArn: "arn:aws:iam::111111111111:role/Principal",
|
||||
RoleExternalId: "principal-ext",
|
||||
RoleSessionName: "principal-sess",
|
||||
RoleTags: map[string]string{
|
||||
"env": "principal",
|
||||
},
|
||||
},
|
||||
TargetAccount: &cred.CredentialAttributes{
|
||||
Region: "eu-west-1",
|
||||
DisableCredentialRotation: true,
|
||||
RoleArn: "arn:aws:iam::222222222222:role/Target",
|
||||
RoleExternalId: "target-ext",
|
||||
RoleSessionName: "target-sess",
|
||||
RoleTags: map[string]string{
|
||||
"env": "target",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "catalog dual_stack and instance_addresses_only with target",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"dual_stack": structpb.NewBoolValue(true),
|
||||
"instance_addresses_only": structpb.NewBoolValue(true),
|
||||
"target_role_arn": structpb.NewStringValue("arn:aws:iam::222222222222:role/Target"),
|
||||
},
|
||||
},
|
||||
expected: &CatalogAttributes{
|
||||
CredentialAttributes: &credential.CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
DisableCredentialRotation: false,
|
||||
},
|
||||
TargetAccount: &cred.CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
DisableCredentialRotation: false,
|
||||
RoleArn: "arn:aws:iam::222222222222:role/Target",
|
||||
},
|
||||
DualStack: true,
|
||||
InstanceAddressesOnly: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unknown field with target_role_arn",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"region": structpb.NewStringValue("us-west-2"),
|
||||
"target_role_arn": structpb.NewStringValue("arn:aws:iam::222222222222:role/Target"),
|
||||
"foo": structpb.NewBoolValue(true),
|
||||
},
|
||||
},
|
||||
expectedErrContains: "attributes.foo: unrecognized field",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
Reference in new issue
Block a user