Skip to content

Commit b387622

Browse files
authored
feat: hierarchical RoleSessionName resolution when assume (#884)
1 parent e504d8b commit b387622

File tree

5 files changed

+86
-15
lines changed

5 files changed

+86
-15
lines changed

pkg/cfaws/assumer_aws_credential_process.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,7 @@ func (cpa *CredentialProcessAssumer) AssumeTerminal(ctx context.Context, c *Prof
6666
return aws.Credentials{}, err
6767
}
6868
stsp := stscreds.NewAssumeRoleProvider(sts.New(sts.Options{Credentials: aws.NewCredentialsCache(&CredProv{creds}), Region: region}), c.AWSConfig.RoleARN, func(aro *stscreds.AssumeRoleOptions) {
69-
if c.AWSConfig.RoleSessionName != "" {
70-
aro.RoleSessionName = c.AWSConfig.RoleSessionName
71-
} else {
72-
aro.RoleSessionName = sessionName()
73-
}
69+
aro.RoleSessionName = getRoleSessionNameFromProfile(c)
7470
if c.AWSConfig.MFASerial != "" {
7571
aro.SerialNumber = &c.AWSConfig.MFASerial
7672
aro.TokenProvider = MfaTokenProvider

pkg/cfaws/assumer_aws_iam.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,8 @@ func (aia *AwsIamAssumer) AssumeTerminal(ctx context.Context, c *Profile, config
120120
aro.SerialNumber = aws.String(c.AWSConfig.MFASerial)
121121
}
122122
}
123-
if c.AWSConfig.RoleSessionName != "" {
124-
aro.RoleSessionName = c.AWSConfig.RoleSessionName
125-
} else {
126-
aro.RoleSessionName = sessionName()
127-
}
123+
124+
aro.RoleSessionName = getRoleSessionNameFromProfile(c)
128125
}))
129126

130127
cfg, err := config.LoadDefaultConfig(ctx, opts...)

pkg/cfaws/assumer_aws_sso.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,7 @@ func (c *Profile) SSOLoginWithToken(ctx context.Context, cfg *aws.Config, access
112112
stsClient := sts.New(sts.Options{Credentials: aws.NewCredentialsCache(credProvider), Region: region})
113113
stsp := stscreds.NewAssumeRoleProvider(stsClient, p.AWSConfig.RoleARN, func(aro *stscreds.AssumeRoleOptions) {
114114
// all configuration goes in here for this profile
115-
if p.AWSConfig.RoleSessionName != "" {
116-
aro.RoleSessionName = p.AWSConfig.RoleSessionName
117-
} else {
118-
aro.RoleSessionName = sessionName()
119-
}
115+
aro.RoleSessionName = getRoleSessionNameFromProfile(p)
120116
if p.AWSConfig.MFASerial != "" {
121117
aro.SerialNumber = &p.AWSConfig.MFASerial
122118
aro.TokenProvider = MfaTokenProvider

pkg/cfaws/session_name.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,30 @@ func sessionName() string {
99
// using the acronym gntd to ensure the id is not longer than 32 chars
1010
return "gntd-" + ksuid.New().String()
1111
}
12+
13+
// findRoleSessionNameInParents recursively searches parent profiles for a RoleSessionName.
14+
func findRoleSessionNameInParents(profile *Profile) string {
15+
if profile == nil {
16+
return ""
17+
}
18+
if profile.AWSConfig.RoleSessionName != "" {
19+
return profile.AWSConfig.RoleSessionName
20+
}
21+
if len(profile.Parents) > 0 {
22+
return findRoleSessionNameInParents(profile.Parents[0])
23+
}
24+
return ""
25+
}
26+
27+
// getRoleSessionNameFromProfile determines the RoleSessionName for a profile.
28+
// It checks the profile itself, then recursively checks parent profiles, and finally falls back to a generated session name.
29+
func getRoleSessionNameFromProfile(profile *Profile) string {
30+
if profile.AWSConfig.RoleSessionName != "" {
31+
return profile.AWSConfig.RoleSessionName
32+
}
33+
parentRoleSessionName := findRoleSessionNameInParents(profile)
34+
if parentRoleSessionName != "" {
35+
return parentRoleSessionName
36+
}
37+
return sessionName()
38+
}

pkg/cfaws/session_name_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cfaws
33
import (
44
"testing"
55

6+
"github.com/aws/aws-sdk-go-v2/config"
67
"github.com/stretchr/testify/assert"
78
)
89

@@ -13,3 +14,57 @@ func TestSessionName(t *testing.T) {
1314
name := sessionName()
1415
assert.LessOrEqual(t, len(name), 32)
1516
}
17+
18+
func TestFindRoleSessionNameInParents(t *testing.T) {
19+
// Test case: No parent profiles
20+
profile := &Profile{
21+
AWSConfig: config.SharedConfig{RoleSessionName: ""},
22+
Parents: nil,
23+
}
24+
assert.Equal(t, "", findRoleSessionNameInParents(profile))
25+
26+
// Test case: Parent profile with RoleSessionName
27+
parentProfile := &Profile{
28+
AWSConfig: config.SharedConfig{RoleSessionName: "parent-session"},
29+
Parents: nil,
30+
}
31+
profile.Parents = []*Profile{parentProfile}
32+
assert.Equal(t, "parent-session", findRoleSessionNameInParents(profile))
33+
34+
// Test case: Multiple parent profiles
35+
grandParentProfile := &Profile{
36+
AWSConfig: config.SharedConfig{RoleSessionName: "grandparent-session"},
37+
Parents: nil,
38+
}
39+
parentProfile.Parents = []*Profile{grandParentProfile}
40+
assert.Equal(t, "parent-session", findRoleSessionNameInParents(profile))
41+
}
42+
43+
func TestGetRoleSessionNameFromProfile(t *testing.T) {
44+
// Test case: Profile with RoleSessionName
45+
profile := &Profile{
46+
AWSConfig: config.SharedConfig{RoleSessionName: "profile-session"},
47+
Parents: nil,
48+
}
49+
assert.Equal(t, "profile-session", getRoleSessionNameFromProfile(profile))
50+
51+
// Test case: Parent profile with RoleSessionName
52+
parentProfile := &Profile{
53+
AWSConfig: config.SharedConfig{RoleSessionName: "parent-session"},
54+
Parents: nil,
55+
}
56+
profile = &Profile{
57+
AWSConfig: config.SharedConfig{RoleSessionName: ""},
58+
Parents: []*Profile{parentProfile},
59+
}
60+
assert.Equal(t, "parent-session", getRoleSessionNameFromProfile(profile))
61+
62+
// Test case: No RoleSessionName in profile or parents
63+
profile = &Profile{
64+
AWSConfig: config.SharedConfig{RoleSessionName: ""},
65+
Parents: nil,
66+
}
67+
name := getRoleSessionNameFromProfile(profile)
68+
assert.NotEmpty(t, name)
69+
assert.Contains(t, name, "gntd-")
70+
}

0 commit comments

Comments
 (0)