Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement assume-time policy limiting #1342

Merged
merged 2 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions cmd/saml2aws/commands/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,22 @@ func loginToStsUsingRole(account *cfg.IDPAccount, role *saml2aws.AWSRole, samlAs
DurationSeconds: aws.Int64(int64(account.SessionDuration)),
}

if 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))
}
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
Comment on lines +368 to +381
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when the policies/policyARNs are removed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The policyfile would be a local file. If the local file doesn't exist, I would expect that to generate the new wrapped error. If the PolicyFile doesn't represent a valid policy, or if there is an attempt to use the arn of a policy that doesn't exist, I would expect AssumeRole to return an error, so those would end up with a wrapped error and "Error retrieving STS credentials using SAML." There are a few things we could do, like validating the format of ARN's or the general shape of the json policy document ahead of time, but I wasn't sure how much you would want to add there. I don't think we can validate the existence of the actual policies pointed to by the policyARN's in a meaningful way, because we don't really have AWS creds yet. I am using this while scoping things like AWS' canned ReadOnly and SecurityAudit policies, and those haven't gone away yet.
I wasn't sure what you meant by "removed" precisely, but hopefully it was covered in there.

}

log.Println("Requesting AWS credentials using SAML assertion.")

resp, err := svc.AssumeRoleWithSAML(params)
Expand Down
2 changes: 2 additions & 0 deletions cmd/saml2aws/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions pkg/cfg/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
8 changes: 8 additions & 0 deletions pkg/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type CommonFlags struct {
Username string
Password string
RoleArn string
PolicyFile string
PolicyARNs string
AmazonWebservicesURN string
SessionDuration int
SkipPrompt bool
Expand Down Expand Up @@ -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
}
Expand Down
Loading