feat(cli) Implement parsing of target-prefixed attrs for cross account dynamic host catalogs (#84)
This commit is contained in:
1 parent
e5b28b919d
commit
1eed21718b
5 files changed
+505
-2
No files matched your search
@@ -186,3 +186,63 @@ func GetCredentialAttributes(in *structpb.Struct) (*CredentialAttributes, error)
|
|||||||
RoleTags: roleTags,
|
RoleTags: roleTags,
|
||||||
}, nil
|
}, 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) {
|
func TestGetCredentialsConfig(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
package credential
|
package credential
|
||||||
|
|
||||||
const (
|
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"
|
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"
|
ConstAccessKeyId = "access_key_id"
|
||||||
|
|
||||||
// ConstSecretAccessKey is the key for the secret access key in the aws credentials.
|
// 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 is the key for the tags used for assuming a IAM role.
|
||||||
ConstRoleTags = "role_tags"
|
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 {
|
type CatalogAttributes struct {
|
||||||
*cred.CredentialAttributes
|
*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 is used for configuring how the aws client will resolve requests.
|
||||||
DualStack bool
|
DualStack bool
|
||||||
|
|
||||||
@@ -39,6 +42,14 @@ func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
|||||||
return nil, err
|
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)
|
dualStack, err := values.GetBoolValue(in, ConstAwsDualStack, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
badFields[fmt.Sprintf("attributes.%s", ConstAwsDualStack)] = err.Error()
|
badFields[fmt.Sprintf("attributes.%s", ConstAwsDualStack)] = err.Error()
|
||||||
@@ -66,6 +77,16 @@ func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
|||||||
continue
|
continue
|
||||||
case cred.ConstRoleTags:
|
case cred.ConstRoleTags:
|
||||||
continue
|
continue
|
||||||
|
case cred.ConstTargetRegion:
|
||||||
|
continue
|
||||||
|
case cred.ConstTargetRoleArn:
|
||||||
|
continue
|
||||||
|
case cred.ConstTargetRoleExternalId:
|
||||||
|
continue
|
||||||
|
case cred.ConstTargetRoleSessionName:
|
||||||
|
continue
|
||||||
|
case cred.ConstTargetRoleTags:
|
||||||
|
continue
|
||||||
default:
|
default:
|
||||||
badFields[fmt.Sprintf("attributes.%s", s)] = "unrecognized field"
|
badFields[fmt.Sprintf("attributes.%s", s)] = "unrecognized field"
|
||||||
}
|
}
|
||||||
@@ -77,6 +98,7 @@ func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
|||||||
|
|
||||||
return &CatalogAttributes{
|
return &CatalogAttributes{
|
||||||
CredentialAttributes: credAttributes,
|
CredentialAttributes: credAttributes,
|
||||||
|
TargetAccount: targetCredAttributes,
|
||||||
DualStack: dualStack,
|
DualStack: dualStack,
|
||||||
InstanceAddressesOnly: instanceAddressesOnly,
|
InstanceAddressesOnly: instanceAddressesOnly,
|
||||||
}, nil
|
}, nil
|
||||||
@@ -121,3 +143,19 @@ func getSetAttributes(in *structpb.Struct) (*SetAttributes, error) {
|
|||||||
|
|
||||||
return &setAttrs, nil
|
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 {
|
for _, tc := range cases {
|
||||||
|
|||||||
Reference in new issue
Block a user