From 9566f0cbb7237c09d886255fa60f3225490ce43f Mon Sep 17 00:00:00 2001 From: Eldon Stegall Date: Wed, 4 Sep 2024 17:57:22 +0000 Subject: [PATCH 1/2] Implement assume-time policy limiting --- cmd/saml2aws/commands/login.go | 17 +++++++++++++++++ cmd/saml2aws/main.go | 2 ++ pkg/cfg/cfg.go | 2 ++ pkg/flags/flags.go | 8 ++++++++ 4 files changed, 29 insertions(+) diff --git a/cmd/saml2aws/commands/login.go b/cmd/saml2aws/commands/login.go index 3262f1ec2..f7282ea88 100644 --- a/cmd/saml2aws/commands/login.go +++ b/cmd/saml2aws/commands/login.go @@ -4,6 +4,7 @@ import ( b64 "encoding/base64" "encoding/json" "fmt" + "io/ioutil" "log" "os" "strings" @@ -365,6 +366,22 @@ func loginToStsUsingRole(account *cfg.IDPAccount, role *saml2aws.AWSRole, samlAs DurationSeconds: aws.Int64(int64(account.SessionDuration)), } + if account.PolicyFile != "" { + policy, err := ioutil.ReadFile(account.PolicyFile) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("Failed to load supplimental policy file: %s", account.PolicyFile)) + } + params.Policy = aws.String(string(policy)) + } + + if account.PolicyARNs != "" { + var arns []*sts.PolicyDescriptorType + for _, arn := range strings.Split(account.PolicyARNs, ",") { + arns = append(arns, &sts.PolicyDescriptorType{Arn: aws.String(arn)}) + } + params.PolicyArns = arns + } + log.Println("Requesting AWS credentials using SAML assertion.") resp, err := svc.AssumeRoleWithSAML(params) diff --git a/cmd/saml2aws/main.go b/cmd/saml2aws/main.go index 31c5baa1c..fe6a96372 100644 --- a/cmd/saml2aws/main.go +++ b/cmd/saml2aws/main.go @@ -83,6 +83,8 @@ func main() { app.Flag("password", "The password used to login. (env: SAML2AWS_PASSWORD)").Envar("SAML2AWS_PASSWORD").StringVar(&commonFlags.Password) app.Flag("mfa-token", "The current MFA token (supported in Keycloak, ADFS, GoogleApps). (env: SAML2AWS_MFA_TOKEN)").Envar("SAML2AWS_MFA_TOKEN").StringVar(&commonFlags.MFAToken) app.Flag("role", "The ARN of the role to assume. (env: SAML2AWS_ROLE)").Envar("SAML2AWS_ROLE").StringVar(&commonFlags.RoleArn) + app.Flag("policyfile", "The file containing the supplemental AssumeRole policy. (env: SAML2AWS_POLICY_FILE)").Envar("SAML2AWS_POLICY_FILE").StringVar(&commonFlags.PolicyFile) + app.Flag("policyarns", "The ARN of supplemental policies to restrict the token. (env: SAML2AWS_POLICY_ARNS)").Envar("SAML2AWS_POLICY_ARNS").StringVar(&commonFlags.PolicyARNs) app.Flag("aws-urn", "The URN used by SAML when you login. (env: SAML2AWS_AWS_URN)").Envar("SAML2AWS_AWS_URN").StringVar(&commonFlags.AmazonWebservicesURN) app.Flag("skip-prompt", "Skip prompting for parameters during login.").BoolVar(&commonFlags.SkipPrompt) app.Flag("session-duration", "The duration of your AWS Session. (env: SAML2AWS_SESSION_DURATION)").Envar("SAML2AWS_SESSION_DURATION").IntVar(&commonFlags.SessionDuration) diff --git a/pkg/cfg/cfg.go b/pkg/cfg/cfg.go index 244384c49..101491c04 100644 --- a/pkg/cfg/cfg.go +++ b/pkg/cfg/cfg.go @@ -52,6 +52,8 @@ type IDPAccount struct { ResourceID string `ini:"resource_id"` // used by F5APM Subdomain string `ini:"subdomain"` // used by OneLogin RoleARN string `ini:"role_arn"` + PolicyFile string `ini:"policy_file"` + PolicyARNs string `ini:"policy_arn_list"` Region string `ini:"region"` HttpAttemptsCount string `ini:"http_attempts_count"` HttpRetryDelay string `ini:"http_retry_delay"` diff --git a/pkg/flags/flags.go b/pkg/flags/flags.go index 0e7607ef7..167980f11 100644 --- a/pkg/flags/flags.go +++ b/pkg/flags/flags.go @@ -22,6 +22,8 @@ type CommonFlags struct { Username string Password string RoleArn string + PolicyFile string + PolicyARNs string AmazonWebservicesURN string SessionDuration int SkipPrompt bool @@ -115,6 +117,12 @@ func ApplyFlagOverrides(commonFlags *CommonFlags, account *cfg.IDPAccount) { if commonFlags.RoleArn != "" { account.RoleARN = commonFlags.RoleArn } + if commonFlags.PolicyFile != "" { + account.PolicyFile = commonFlags.PolicyFile + } + if commonFlags.PolicyARNs != "" { + account.PolicyARNs = commonFlags.PolicyARNs + } if commonFlags.ResourceID != "" { account.ResourceID = commonFlags.ResourceID } From f4a0d2e43ae481ed32d5a7c4c12ff3328cb08104 Mon Sep 17 00:00:00 2001 From: Eldon Stegall Date: Mon, 9 Sep 2024 22:35:44 +0000 Subject: [PATCH 2/2] Avoid deprecated package --- cmd/saml2aws/commands/login.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/saml2aws/commands/login.go b/cmd/saml2aws/commands/login.go index f7282ea88..6884f4b30 100644 --- a/cmd/saml2aws/commands/login.go +++ b/cmd/saml2aws/commands/login.go @@ -4,7 +4,6 @@ import ( b64 "encoding/base64" "encoding/json" "fmt" - "io/ioutil" "log" "os" "strings" @@ -367,7 +366,7 @@ func loginToStsUsingRole(account *cfg.IDPAccount, role *saml2aws.AWSRole, samlAs } if account.PolicyFile != "" { - policy, err := ioutil.ReadFile(account.PolicyFile) + policy, err := os.ReadFile(account.PolicyFile) if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("Failed to load supplimental policy file: %s", account.PolicyFile)) }