sts: Add support of AssumeRoleWithWebIdentity and DurationSeconds (#18835)

To force limit the duration of STS accounts, the user can create a new
policy, like the following:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["sts:AssumeRoleWithWebIdentity"],
    "Condition": {"NumericLessThanEquals": {"sts:DurationSeconds": "300"}}
  }]
}

And force binding the policy to all OpenID users, whether using a claim name or role
ARN.
This commit is contained in:
Anis Eleuch 2024-02-05 20:44:23 +01:00 committed by GitHub
parent e046eb1d17
commit 7aa00bff89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 39 additions and 0 deletions

View file

@ -66,6 +66,14 @@ func NewPolicySys() *PolicySys {
return &PolicySys{}
}
func getSTSConditionValues(r *http.Request, lc string, cred auth.Credentials) map[string][]string {
m := make(map[string][]string)
if d := r.Form.Get("DurationSeconds"); d != "" {
m["DurationSeconds"] = []string{d}
}
return m
}
func getConditionValues(r *http.Request, lc string, cred auth.Credentials) map[string][]string {
currTime := UTCNow()

View file

@ -2054,6 +2054,13 @@ func (sys *IAMSys) GetCombinedPolicy(policies ...string) policy.Policy {
return policy
}
// doesPolicyAllow - checks if the given policy allows the passed action with given args. This is rarely needed.
// Notice there is no account name involved, so this is a dangerous function.
func (sys *IAMSys) doesPolicyAllow(policy string, args policy.Args) bool {
// Policies were found, evaluate all of them.
return sys.GetCombinedPolicy(policy).IsAllowed(args)
}
// IsAllowed - checks given policy args is allowed to continue the Rest API.
func (sys *IAMSys) IsAllowed(args policy.Args) bool {
// If opa is configured, use OPA always.

View file

@ -493,6 +493,30 @@ func (sts *stsAPIHandlers) AssumeRoleWithSSO(w http.ResponseWriter, r *http.Requ
cred.ParentUser = base64.RawURLEncoding.EncodeToString(bs)
}
// Deny this assume role request if the policy that the user intends to bind
// has a sts:DurationSeconds condition, which is not satisfied as well
{
p := policyName
if p == "" {
var err error
_, p, err = globalIAMSys.GetRolePolicy(roleArnStr)
if err != nil {
writeSTSErrorResponse(ctx, w, ErrSTSAccessDenied, err)
return
}
}
if !globalIAMSys.doesPolicyAllow(p, policy.Args{
DenyOnly: true,
Action: policy.AssumeRoleWithWebIdentityAction,
ConditionValues: getSTSConditionValues(r, "", cred),
Claims: cred.Claims,
}) {
writeSTSErrorResponse(ctx, w, ErrSTSAccessDenied, errors.New("this user does not have enough permission"))
return
}
}
// Set the newly generated credentials.
updatedAt, err := globalIAMSys.SetTempUser(ctx, cred.AccessKey, cred, policyName)
if err != nil {