Skip to content

Commit d552963

Browse files
committed
feat(eks): add support for cross account login
Signed-off-by: Casale, Robert <[email protected]>
1 parent 6ed0ffa commit d552963

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

pkg/plugins/discovery/aws/provider.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ func New(input *provider.PluginCreationInput) (discovery.Provider, error) {
7171

7272
type eksClusteProviderConfig struct {
7373
common.ClusterProviderConfig
74-
Region *string `json:"region"`
75-
RegionFilter *string `json:"region-filter"`
76-
RoleArn *string `json:"role-arn"`
77-
RoleFilter *string `json:"role-filter"`
74+
AssumeRoleARN *string `json:"assume-role-arn"`
75+
Region *string `json:"region"`
76+
RegionFilter *string `json:"region-filter"`
77+
RoleArn *string `json:"role-arn"`
78+
RoleFilter *string `json:"role-filter"`
7879
}
7980

8081
// EKSClusterProvider will discover EKS clusters in AWS
@@ -129,8 +130,9 @@ func ConfigurationItems(scopeTo string) (config.ConfigurationSet, error) {
129130
cs := aws.SharedConfig()
130131

131132
cs.String("aws-shared-credentials-file", os.Getenv("AWS_SHARED_CREDENTIALS_FILE"), "Location to store AWS credentials file")
133+
cs.String("assume-role-arn", "", "ARN of the AWS role to be assumed")
132134
cs.String("region-filter", "", "A regex filter to apply to the AWS regions list, e.g. '^us-|^eu-' will only show US and eu regions") //nolint: errcheck
133-
cs.String("role-arn", "", "ARN of the AWS role to be assumed") //nolint: errcheck
135+
cs.String("role-arn", "", "ARN of the AWS role to be logged in with") //nolint: errcheck
134136
cs.String("role-filter", "", "A filter to apply to the roles list, e.g. 'EKS' will only show roles that contain EKS in the name") //nolint: errcheck
135137

136138
return cs, nil

pkg/plugins/identity/saml/saml.go

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ func (p *samlIdentityProvider) bindAndValidateConfig(cs config.ConfigurationSet)
184184

185185
func (p *samlIdentityProvider) createAccount(cs config.ConfigurationSet) (*cfg.IDPAccount, error) {
186186
account := &cfg.IDPAccount{
187+
Username: p.config.Username,
187188
URL: p.config.IdpEndpoint,
188189
Provider: p.config.IdpProvider,
189190
MFA: "Auto",

pkg/plugins/identity/saml/sp/aws/provider.go

+52
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"go.uber.org/zap"
2828

2929
"github.com/aws/aws-sdk-go/aws"
30+
"github.com/aws/aws-sdk-go/aws/credentials"
3031
"github.com/aws/aws-sdk-go/aws/endpoints"
3132
"github.com/aws/aws-sdk-go/aws/session"
3233
"github.com/aws/aws-sdk-go/service/sts"
@@ -76,6 +77,11 @@ func (p *ServiceProvider) PopulateAccount(account *cfg.IDPAccount, cfg config.Co
7677
account.AmazonWebservicesURN = "urn:amazon:webservices"
7778
account.Profile = "kconnect-saml-provider"
7879

80+
assumeRoleCfg := cfg.Get("assume-role-arn")
81+
if assumeRoleCfg != nil && assumeRoleCfg.Value.(string) != "" {
82+
account.AssumeRoleARN = assumeRoleCfg.Value.(string)
83+
}
84+
7985
regionCfg := cfg.Get("region")
8086
if regionCfg == nil || regionCfg.Value.(string) == "" {
8187
return ErrNoRegion
@@ -131,6 +137,18 @@ func (p *ServiceProvider) ProcessAssertions(account *cfg.IDPAccount, samlAsserti
131137
return nil, fmt.Errorf("logging into AWS using STS and SAMLAssertion: %w", err)
132138
}
133139

140+
// switch AWS IAM role
141+
if account.AssumeRoleARN != "" {
142+
awsCreds, err = p.assumeRoleARN(account, awsCreds)
143+
if err != nil {
144+
return nil, fmt.Errorf("assuming role in AWS: %w", err)
145+
}
146+
if err := cfg.SetValue("assume-role-arn", account.AssumeRoleARN); err != nil {
147+
return nil, fmt.Errorf("setting assume-role-arn config value: %w", err)
148+
}
149+
p.logger.Debugw("role assumed", "assume-role", account.AssumeRoleARN)
150+
}
151+
134152
// Create profile based on the AWS creds
135153
identifier, err := kaws.CreateIDFromCreds(awsCreds)
136154
if err != nil {
@@ -301,6 +319,40 @@ func (p *ServiceProvider) loginToStsUsingRole(account *cfg.IDPAccount, role *sam
301319
}, nil
302320
}
303321

322+
func (p *ServiceProvider) assumeRoleARN(account *cfg.IDPAccount, awsCreds *awsconfig.AWSCredentials) (*awsconfig.AWSCredentials, error) {
323+
sess, err := session.NewSession(&aws.Config{
324+
Region: &account.Region,
325+
STSRegionalEndpoint: endpoints.RegionalSTSEndpoint,
326+
Credentials: credentials.NewStaticCredentials(
327+
awsCreds.AWSAccessKey,
328+
awsCreds.AWSSecretKey,
329+
awsCreds.AWSSessionToken,
330+
),
331+
})
332+
if err != nil {
333+
return nil, fmt.Errorf("creating aws session: %w", err)
334+
}
335+
assumeRoleInput := &sts.AssumeRoleInput{
336+
RoleArn: &account.AssumeRoleARN,
337+
RoleSessionName: &account.Username,
338+
DurationSeconds: aws.Int64(int64(account.SessionDuration)),
339+
}
340+
out, err := sts.New(sess).AssumeRole(assumeRoleInput)
341+
if err != nil {
342+
return nil, fmt.Errorf("failed to assume role: %w", err)
343+
}
344+
345+
return &awsconfig.AWSCredentials{
346+
AWSAccessKey: aws.StringValue(out.Credentials.AccessKeyId),
347+
AWSSecretKey: aws.StringValue(out.Credentials.SecretAccessKey),
348+
AWSSessionToken: aws.StringValue(out.Credentials.SessionToken),
349+
AWSSecurityToken: aws.StringValue(out.Credentials.SessionToken),
350+
PrincipalARN: aws.StringValue(out.AssumedRoleUser.Arn),
351+
Expires: out.Credentials.Expiration.Local(),
352+
Region: account.Region,
353+
}, nil
354+
}
355+
304356
// TODO: use the version form saml2aws when modules are fixed
305357
func (p *ServiceProvider) extractDestinationURL(data []byte) (string, error) {
306358

0 commit comments

Comments
 (0)