sa: Allow empty policy to indicate parent user's policy is inherited (#9185)

This commit is contained in:
Anis Elleuch 2020-03-23 22:17:18 +01:00 committed by GitHub
parent 9a951da881
commit 791821d590
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 21 deletions

View file

@ -211,8 +211,9 @@ func getClaimsFromToken(r *http.Request) (map[string]interface{}, error) {
// If OPA is not set, session token should
// have a policy and its mandatory, reject
// requests without policy claim.
_, pok := claims.Lookup(iamPolicyClaimName())
if !pok {
_, pokOpenID := claims.Lookup(iamPolicyClaimNameOpenID())
_, pokSA := claims.Lookup(iamPolicyClaimNameSA())
if !pokOpenID && !pokSA {
return nil, errAuthentication
}

View file

@ -798,17 +798,18 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPol
}
if len(sessionPolicy) > 16*1024 {
return auth.Credentials{}, fmt.Errorf("Session policy should not exceed 16*1024 characters")
return auth.Credentials{}, fmt.Errorf("Session policy should not exceed 16 KiB characters")
}
policy, err := iampolicy.ParseConfig(bytes.NewReader([]byte(sessionPolicy)))
if err != nil {
return auth.Credentials{}, err
}
// Version in policy must not be empty
if policy.Version == "" {
return auth.Credentials{}, fmt.Errorf("Invalid session policy version")
if len(sessionPolicy) > 0 {
policy, err := iampolicy.ParseConfig(bytes.NewReader([]byte(sessionPolicy)))
if err != nil {
return auth.Credentials{}, err
}
// Version in policy must not be empty
if policy.Version == "" {
return auth.Credentials{}, fmt.Errorf("Invalid session policy version")
}
}
sys.Lock()
@ -836,9 +837,14 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPol
}
m := make(map[string]interface{})
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString([]byte(sessionPolicy))
m[parentClaim] = parentUser
m[iamPolicyClaimName()] = "embedded-policy"
if len(sessionPolicy) > 0 {
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString([]byte(sessionPolicy))
m[iamPolicyClaimNameSA()] = "embedded-policy"
} else {
m[iamPolicyClaimNameSA()] = "inherited-policy"
}
secret := globalActiveCred.SecretKey
cred, err := auth.GetNewCredentialsWithMetadata(m, secret)
@ -1473,6 +1479,11 @@ func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parent string) b
if parentInClaim != parent {
return false
}
} else {
// This is needed so a malicious user cannot
// use a leaked session key of another user
// to widen its privileges.
return false
}
// Check if the parent is allowed to perform this action, reject if not
@ -1508,12 +1519,27 @@ func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parent string) b
availablePolicies[i].Statements...)
}
serviceAcc := args.AccountName
args.AccountName = parent
if !combinedPolicy.IsAllowed(args) {
parentArgs := args
parentArgs.AccountName = parent
if !combinedPolicy.IsAllowed(parentArgs) {
return false
}
args.AccountName = serviceAcc
saPolicyClaim, ok := args.Claims[iamPolicyClaimNameSA()]
if ok {
saPolicyClaimStr, ok := saPolicyClaim.(string)
if !ok {
// Sub policy if set, should be a string reject
// malformed/malicious requests.
return false
}
if saPolicyClaimStr == "inherited-policy" {
// Immediately returns true since at this stage, since
// parent user is allowed to do this action.
return true
}
}
// Now check if we have a sessionPolicy.
spolicy, ok := args.Claims[iampolicy.SessionPolicyName]
@ -1605,7 +1631,7 @@ func (sys *IAMSys) IsAllowedSTS(args iampolicy.Args) bool {
return combinedPolicy.IsAllowed(args)
}
pnameSlice, ok := args.GetPolicies(iamPolicyClaimName())
pnameSlice, ok := args.GetPolicies(iamPolicyClaimNameOpenID())
if !ok {
// When claims are set, it should have a policy claim field.
return false

View file

@ -215,7 +215,7 @@ func (sts *stsAPIHandlers) AssumeRole(w http.ResponseWriter, r *http.Request) {
// This policy is the policy associated with the user
// requesting for temporary credentials. The temporary
// credentials will inherit the same policy requirements.
m[iamPolicyClaimName()] = policyName
m[iamPolicyClaimNameOpenID()] = policyName
if len(sessionPolicyStr) > 0 {
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString([]byte(sessionPolicyStr))
@ -351,7 +351,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Requ
// be set and configured on your identity provider as part of
// JWT custom claims.
var policyName string
if v, ok := m[iamPolicyClaimName()]; ok {
if v, ok := m[iamPolicyClaimNameOpenID()]; ok {
policyName, _ = v.(string)
}

View file

@ -620,10 +620,14 @@ func getMinioMode() string {
return mode
}
func iamPolicyClaimName() string {
func iamPolicyClaimNameOpenID() string {
return globalOpenIDConfig.ClaimPrefix + globalOpenIDConfig.ClaimName
}
func iamPolicyClaimNameSA() string {
return "sa-policy"
}
func isWORMEnabled(bucket string) bool {
if isMinioMetaBucketName(bucket) {
return false