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

master
Anis Elleuch 5 years ago committed by GitHub
parent 9a951da881
commit 791821d590
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      cmd/auth-handler.go
  2. 44
      cmd/iam.go
  3. 4
      cmd/sts-handlers.go
  4. 6
      cmd/utils.go

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

@ -798,18 +798,19 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPol
} }
if len(sessionPolicy) > 16*1024 { 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")
} }
if len(sessionPolicy) > 0 {
policy, err := iampolicy.ParseConfig(bytes.NewReader([]byte(sessionPolicy))) policy, err := iampolicy.ParseConfig(bytes.NewReader([]byte(sessionPolicy)))
if err != nil { if err != nil {
return auth.Credentials{}, err return auth.Credentials{}, err
} }
// Version in policy must not be empty // Version in policy must not be empty
if policy.Version == "" { if policy.Version == "" {
return auth.Credentials{}, fmt.Errorf("Invalid session policy version") return auth.Credentials{}, fmt.Errorf("Invalid session policy version")
} }
}
sys.Lock() sys.Lock()
defer sys.Unlock() defer sys.Unlock()
@ -836,9 +837,14 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPol
} }
m := make(map[string]interface{}) m := make(map[string]interface{})
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString([]byte(sessionPolicy))
m[parentClaim] = parentUser 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 secret := globalActiveCred.SecretKey
cred, err := auth.GetNewCredentialsWithMetadata(m, secret) cred, err := auth.GetNewCredentialsWithMetadata(m, secret)
@ -1473,6 +1479,11 @@ func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parent string) b
if parentInClaim != parent { if parentInClaim != parent {
return false 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 // 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...) availablePolicies[i].Statements...)
} }
serviceAcc := args.AccountName parentArgs := args
args.AccountName = parent parentArgs.AccountName = parent
if !combinedPolicy.IsAllowed(args) { if !combinedPolicy.IsAllowed(parentArgs) {
return false
}
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 return false
} }
args.AccountName = serviceAcc
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. // Now check if we have a sessionPolicy.
spolicy, ok := args.Claims[iampolicy.SessionPolicyName] spolicy, ok := args.Claims[iampolicy.SessionPolicyName]
@ -1605,7 +1631,7 @@ func (sys *IAMSys) IsAllowedSTS(args iampolicy.Args) bool {
return combinedPolicy.IsAllowed(args) return combinedPolicy.IsAllowed(args)
} }
pnameSlice, ok := args.GetPolicies(iamPolicyClaimName()) pnameSlice, ok := args.GetPolicies(iamPolicyClaimNameOpenID())
if !ok { if !ok {
// When claims are set, it should have a policy claim field. // When claims are set, it should have a policy claim field.
return false return false

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

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

Loading…
Cancel
Save