mirror of
https://github.com/minio/minio.git
synced 2025-11-07 21:02:58 -05:00
fix: check sub-policy properly when present (#21642)
This fixes a security issue where sub-policy attached to a service account or STS account is not properly validated under certain "own" account operations (like creating new service accounts). This allowed a service account to create new service accounts for the same user bypassing the inline policy restriction.
This commit is contained in:
committed by
GitHub
parent
334c313da4
commit
c1a49490c7
33
cmd/iam.go
33
cmd/iam.go
@@ -2400,21 +2400,8 @@ func isAllowedBySessionPolicyForServiceAccount(args policy.Args) (hasSessionPoli
|
||||
// policy, regardless of whether the number of statements is 0, this
|
||||
// includes `null`, `{}` and `{"Statement": null}`. In fact, MinIO Console
|
||||
// sends `null` when no policy is set and the intended behavior is that the
|
||||
// service account should inherit parent policy.
|
||||
//
|
||||
// However, for a policy like `{"Statement":[]}`, the intention is to not
|
||||
// provide any permissions via the session policy - i.e. the service account
|
||||
// can do nothing (such a JSON could be generated by an external application
|
||||
// as the policy for the service account). Inheriting the parent policy in
|
||||
// such a case, is a security issue. Ideally, we should not allow such
|
||||
// behavior, but for compatibility with the Console, we currently allow it.
|
||||
//
|
||||
// TODO:
|
||||
//
|
||||
// 1. fix console behavior and allow this inheritance for service accounts
|
||||
// created before a certain (TBD) future date.
|
||||
//
|
||||
// 2. do not allow empty statement policies for service accounts.
|
||||
// service account should inherit parent policy. So when policy is empty in
|
||||
// all fields we return hasSessionPolicy=false.
|
||||
if subPolicy.Version == "" && subPolicy.Statements == nil && subPolicy.ID == "" {
|
||||
hasSessionPolicy = false
|
||||
return hasSessionPolicy, isAllowed
|
||||
@@ -2423,8 +2410,16 @@ func isAllowedBySessionPolicyForServiceAccount(args policy.Args) (hasSessionPoli
|
||||
// As the session policy exists, even if the parent is the root account, it
|
||||
// must be restricted by it. So, we set `.IsOwner` to false here
|
||||
// unconditionally.
|
||||
//
|
||||
// We also set `DenyOnly` arg to false here - this is an IMPORTANT corner
|
||||
// case: DenyOnly is used only for allowing an account to do actions related
|
||||
// to its own account (like create service accounts for itself, among
|
||||
// others). However when a session policy is present, we need to validate
|
||||
// that the action is actually allowed, rather than checking if the action
|
||||
// is only disallowed.
|
||||
sessionPolicyArgs := args
|
||||
sessionPolicyArgs.IsOwner = false
|
||||
sessionPolicyArgs.DenyOnly = false
|
||||
|
||||
// Sub policy is set and valid.
|
||||
return hasSessionPolicy, subPolicy.IsAllowed(sessionPolicyArgs)
|
||||
@@ -2465,8 +2460,16 @@ func isAllowedBySessionPolicy(args policy.Args) (hasSessionPolicy bool, isAllowe
|
||||
// As the session policy exists, even if the parent is the root account, it
|
||||
// must be restricted by it. So, we set `.IsOwner` to false here
|
||||
// unconditionally.
|
||||
//
|
||||
// We also set `DenyOnly` arg to false here - this is an IMPORTANT corner
|
||||
// case: DenyOnly is used only for allowing an account to do actions related
|
||||
// to its own account (like create service accounts for itself, among
|
||||
// others). However when a session policy is present, we need to validate
|
||||
// that the action is actually allowed, rather than checking if the action
|
||||
// is only disallowed.
|
||||
sessionPolicyArgs := args
|
||||
sessionPolicyArgs.IsOwner = false
|
||||
sessionPolicyArgs.DenyOnly = false
|
||||
|
||||
// Sub policy is set and valid.
|
||||
return hasSessionPolicy, subPolicy.IsAllowed(sessionPolicyArgs)
|
||||
|
||||
Reference in New Issue
Block a user