2026-05-11 22:37:05 -07:00
// Copyright IBM Corp. 2021, 2026
2023-03-20 11:02:17 -07:00
// SPDX-License-Identifier: MPL-2.0
package credential
import (
"testing"
2023-09-22 12:26:08 -07:00
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
2023-03-20 11:02:17 -07:00
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
)
func TestGetCredentialAttributes ( t * testing . T ) {
cases := [] struct {
name string
in map [ string ] any
expected * CredentialAttributes
expectedErrContains string
}{
{
name : "missing region" ,
in : map [ string ] any {},
expectedErrContains : "missing required value \"region\"" ,
},
{
name : "bad value for disable_credential_rotation" ,
in : map [ string ] any {
ConstRegion : "us-west-2" ,
ConstDisableCredentialRotation : "sure" ,
},
expectedErrContains : "unexpected type for value \"disable_credential_rotation\": want bool, got string" ,
},
{
name : "default" ,
in : map [ string ] any {
ConstRegion : "us-west-2" ,
},
expected : & CredentialAttributes {
Region : "us-west-2" ,
DisableCredentialRotation : false ,
},
},
{
name : "with disable_credential_rotation" ,
in : map [ string ] any {
ConstRegion : "us-west-2" ,
ConstDisableCredentialRotation : true ,
},
expected : & CredentialAttributes {
Region : "us-west-2" ,
DisableCredentialRotation : true ,
},
},
2023-07-18 16:33:24 -07:00
{
name : "with assume role" ,
in : map [ string ] any {
ConstRegion : "us-west-2" ,
ConstRoleArn : "arn:aws:iam::123456789012:role/S3Access" ,
ConstRoleExternalId : "1234567890" ,
ConstRoleSessionName : "test-session" ,
ConstRoleTags : map [ string ] interface {}{
"foo" : "bar" ,
},
},
expected : & CredentialAttributes {
Region : "us-west-2" ,
DisableCredentialRotation : false ,
RoleArn : "arn:aws:iam::123456789012:role/S3Access" ,
RoleExternalId : "1234567890" ,
RoleSessionName : "test-session" ,
RoleTags : map [ string ] string {
"foo" : "bar" ,
},
},
},
2023-03-20 11:02:17 -07:00
}
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 := GetCredentialAttributes ( input )
if tc . expectedErrContains != "" {
require . Error ( err )
require . Contains ( err . Error (), tc . expectedErrContains )
require . Equal ( status . Code ( err ), codes . InvalidArgument )
return
}
require . NoError ( err )
require . EqualValues ( tc . expected . Region , actual . Region )
require . EqualValues ( tc . expected . DisableCredentialRotation , actual . DisableCredentialRotation )
})
}
}
func TestGetCredentialsConfig ( t * testing . T ) {
cases := [] struct {
name string
2023-07-18 16:33:24 -07:00
secrets * structpb . Struct
attrs * CredentialAttributes
2024-10-28 11:50:18 -07:00
dualStack bool
2023-03-20 11:02:17 -07:00
expected * awsutil . CredentialsConfig
expectedErrContains string
}{
{
2023-09-22 12:26:08 -07:00
name : "no credentials" ,
2023-07-18 16:33:24 -07:00
attrs : & CredentialAttributes {
Region : "us-west-2" ,
},
expected : & awsutil . CredentialsConfig {
Region : "us-west-2" ,
},
2023-03-20 11:02:17 -07:00
},
{
2023-07-18 16:33:24 -07:00
name : "with static credentials" ,
secrets : & structpb . Struct {
Fields : map [ string ] * structpb . Value {
2023-09-22 12:26:08 -07:00
ConstAccessKeyId : structpb . NewStringValue ( "AKIAfoobar" ),
2023-07-18 16:33:24 -07:00
ConstSecretAccessKey : structpb . NewStringValue ( "bazqux" ),
},
},
attrs : & CredentialAttributes {
Region : "us-west-2" ,
},
expected : & awsutil . CredentialsConfig {
2023-09-22 12:26:08 -07:00
AccessKey : "AKIAfoobar" ,
2023-07-18 16:33:24 -07:00
SecretKey : "bazqux" ,
Region : "us-west-2" ,
},
},
2024-10-28 11:50:18 -07:00
{
name : "with dualstack" ,
secrets : & structpb . Struct {
Fields : map [ string ] * structpb . Value {
ConstAccessKeyId : structpb . NewStringValue ( "AKIAfoobar" ),
ConstSecretAccessKey : structpb . NewStringValue ( "bazqux" ),
},
},
dualStack : true ,
attrs : & CredentialAttributes {
Region : "us-west-2" ,
},
expected : & awsutil . CredentialsConfig {
AccessKey : "AKIAfoobar" ,
SecretKey : "bazqux" ,
Region : "us-west-2" ,
},
},
2023-03-20 11:02:17 -07:00
{
name : "unknown fields" ,
2023-07-18 16:33:24 -07:00
secrets : & structpb . Struct {
Fields : map [ string ] * structpb . Value {
2023-09-22 12:26:08 -07:00
ConstAccessKeyId : structpb . NewStringValue ( "AKIAfoobar" ),
2023-07-18 16:33:24 -07:00
ConstSecretAccessKey : structpb . NewStringValue ( "bazqux" ),
"foo" : structpb . NewBoolValue ( true ),
"bar" : structpb . NewBoolValue ( true ),
},
},
attrs : & CredentialAttributes {
Region : "us-west-2" ,
2023-03-20 11:02:17 -07:00
},
expectedErrContains : "secrets.bar: unrecognized field, secrets.foo: unrecognized field" ,
},
2023-05-25 22:19:43 -07:00
{
name : "valid ignore creds_last_rotated_time" ,
2023-07-18 16:33:24 -07:00
secrets : & structpb . Struct {
Fields : map [ string ] * structpb . Value {
2023-09-22 12:26:08 -07:00
ConstAccessKeyId : structpb . NewStringValue ( "AKIAfoobar" ),
2023-07-18 16:33:24 -07:00
ConstSecretAccessKey : structpb . NewStringValue ( "bazqux" ),
ConstCredsLastRotatedTime : structpb . NewStringValue ( "2006-01-02T15:04:05+07:00" ),
},
},
attrs : & CredentialAttributes {
Region : "us-west-2" ,
2023-05-25 22:19:43 -07:00
},
expected : & awsutil . CredentialsConfig {
2023-09-22 12:26:08 -07:00
AccessKey : "AKIAfoobar" ,
2023-05-25 22:19:43 -07:00
SecretKey : "bazqux" ,
Region : "us-west-2" ,
},
},
2023-03-20 11:02:17 -07:00
{
2023-07-18 16:33:24 -07:00
name : "with assume role" ,
secrets : & structpb . Struct {
Fields : map [ string ] * structpb . Value {},
},
attrs : & CredentialAttributes {
Region : "us-west-2" ,
RoleArn : "arn:aws:iam::123456789012:role/S3Access" ,
RoleExternalId : "1234567890" ,
RoleSessionName : "test-session" ,
RoleTags : map [ string ] string {
"foo" : "bar" ,
},
2023-09-22 12:26:08 -07:00
DisableCredentialRotation : true ,
2023-03-20 11:02:17 -07:00
},
expected : & awsutil . CredentialsConfig {
2023-07-18 16:33:24 -07:00
Region : "us-west-2" ,
RoleARN : "arn:aws:iam::123456789012:role/S3Access" ,
RoleExternalId : "1234567890" ,
RoleSessionName : "test-session" ,
RoleTags : map [ string ] string {
"foo" : "bar" ,
},
},
},
{
name : "with static credential & assume role" ,
secrets : & structpb . Struct {
Fields : map [ string ] * structpb . Value {
2023-09-22 12:26:08 -07:00
ConstAccessKeyId : structpb . NewStringValue ( "AKIAfoobar" ),
2023-07-18 16:33:24 -07:00
ConstSecretAccessKey : structpb . NewStringValue ( "bazqux" ),
},
},
attrs : & CredentialAttributes {
Region : "us-west-2" ,
RoleArn : "arn:aws:iam::123456789012:role/S3Access" ,
RoleExternalId : "1234567890" ,
RoleSessionName : "test-session" ,
RoleTags : map [ string ] string {
"foo" : "bar" ,
},
},
2023-09-22 12:26:08 -07:00
expectedErrContains : "attributes.role_arn: conflicts with access_key_id and secret_access_key values, secrets.access_key_id: conflicts with role_arn value, secrets.secret_access_key: conflicts with role_arn value" ,
},
{
name : "with dynamic credentials and no disable credential rotation" ,
secrets : & structpb . Struct { Fields : map [ string ] * structpb . Value {}},
attrs : & CredentialAttributes {
2023-07-18 16:33:24 -07:00
Region : "us-west-2" ,
2023-09-22 12:26:08 -07:00
RoleArn : "arn:aws:iam::123456789012:role/S3Access" ,
2023-07-18 16:33:24 -07:00
RoleExternalId : "1234567890" ,
RoleSessionName : "test-session" ,
RoleTags : map [ string ] string {
"foo" : "bar" ,
},
2023-03-20 11:02:17 -07:00
},
2023-09-22 12:26:08 -07:00
expectedErrContains : "attributes.disable_credential_rotation: disable_credential_rotation attribute is required when providing a role_arn" ,
2023-03-20 11:02:17 -07:00
},
}
for _ , tc := range cases {
tc := tc
t . Run ( tc . name , func ( t * testing . T ) {
require := require . New ( t )
2024-10-28 11:50:18 -07:00
actual , err := GetCredentialsConfig ( tc . secrets , tc . attrs , tc . dualStack )
2023-03-20 11:02:17 -07:00
if tc . expectedErrContains != "" {
require . Error ( err )
require . Contains ( err . Error (), tc . expectedErrContains )
require . Equal ( status . Code ( err ), codes . InvalidArgument )
return
}
require . NoError ( err )
require . Equal ( tc . expected . AccessKey , actual . AccessKey )
require . Equal ( tc . expected . SecretKey , actual . SecretKey )
require . Equal ( tc . expected . Region , actual . Region )
2023-07-18 16:33:24 -07:00
require . Equal ( tc . expected . RoleARN , actual . RoleARN )
require . Equal ( tc . expected . RoleExternalId , actual . RoleExternalId )
require . Equal ( tc . expected . RoleSessionName , actual . RoleSessionName )
require . Equal ( tc . expected . RoleTags , actual . RoleTags )
2024-10-28 11:50:18 -07:00
if tc . dualStack {
require . NotNil ( actual . IAMEndpointResolver )
require . NotNil ( actual . STSEndpointResolver )
} else {
require . Nil ( actual . IAMEndpointResolver )
require . Nil ( actual . STSEndpointResolver )
}
2023-03-20 11:02:17 -07:00
})
}
}