diff --git a/cmd/bucket-policy.go b/cmd/bucket-policy.go index f0a216c9e..9e1330b63 100644 --- a/cmd/bucket-policy.go +++ b/cmd/bucket-policy.go @@ -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() diff --git a/cmd/iam.go b/cmd/iam.go index ed437e345..edcb9e77f 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -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. diff --git a/cmd/sts-handlers.go b/cmd/sts-handlers.go index 4ecd72cb0..215a2ff35 100644 --- a/cmd/sts-handlers.go +++ b/cmd/sts-handlers.go @@ -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 {