fix: parentUser mapped policy for OIDC creds (#12293)

missing parentUser for OIDC STS creds can lead
to fail to authenticate, this PR attempts to
fix the parentUser policy map for distributed
setups.
This commit is contained in:
Harshavardhana 2021-05-13 16:21:06 -07:00 committed by GitHub
parent 9cd9f5a0b3
commit 397391c89f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -401,6 +401,22 @@ func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, userType IAMUs
if err != nil && err != errNoSuchPolicy { if err != nil && err != errNoSuchPolicy {
return err return err
} }
// We are on purpose not persisting the policy map for parent
// user, although this is a hack, it is a good enough hack
// at this point in time - we need to overhaul our OIDC
// usage with service accounts with a more cleaner implementation
//
// This mapping is necessary to ensure that valid credentials
// have necessary ParentUser present - this is mainly for only
// webIdentity based STS tokens.
cred, ok := sys.iamUsersMap[accessKey]
if ok {
if cred.IsTemp() && cred.ParentUser != "" && cred.ParentUser != globalActiveCred.AccessKey {
if _, ok := sys.iamUserPolicyMap[cred.ParentUser]; !ok {
sys.iamUserPolicyMap[cred.ParentUser] = sys.iamUserPolicyMap[accessKey]
}
}
}
} }
// When etcd is set, we use watch APIs so this code is not needed. // When etcd is set, we use watch APIs so this code is not needed.
return nil return nil
@ -872,8 +888,14 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa
sys.store.lock() sys.store.lock()
defer sys.store.unlock() defer sys.store.unlock()
if err := sys.store.saveMappedPolicy(context.Background(), accessKey, stsUser, false, mp, options{ttl: ttl}); err != nil {
return err
}
sys.iamUserPolicyMap[accessKey] = mp
// We are on purpose not persisting the policy map for parent // We are on purpose not persisting the policy map for parent
// user, although this is a hack, it is a good enoug hack // user, although this is a hack, it is a good enough hack
// at this point in time - we need to overhaul our OIDC // at this point in time - we need to overhaul our OIDC
// usage with service accounts with a more cleaner implementation // usage with service accounts with a more cleaner implementation
// //
@ -882,20 +904,9 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa
// webIdentity based STS tokens. // webIdentity based STS tokens.
if cred.IsTemp() && cred.ParentUser != "" && cred.ParentUser != globalActiveCred.AccessKey { if cred.IsTemp() && cred.ParentUser != "" && cred.ParentUser != globalActiveCred.AccessKey {
if _, ok := sys.iamUserPolicyMap[cred.ParentUser]; !ok { if _, ok := sys.iamUserPolicyMap[cred.ParentUser]; !ok {
if err := sys.store.saveMappedPolicy(context.Background(), accessKey, stsUser, false, mp, options{ttl: ttl}); err != nil {
sys.store.unlock()
return err
}
sys.iamUserPolicyMap[cred.ParentUser] = mp sys.iamUserPolicyMap[cred.ParentUser] = mp
} }
} }
if err := sys.store.saveMappedPolicy(context.Background(), accessKey, stsUser, false, mp, options{ttl: ttl}); err != nil {
sys.store.unlock()
return err
}
sys.iamUserPolicyMap[accessKey] = mp
} else { } else {
sys.store.lock() sys.store.lock()
defer sys.store.unlock() defer sys.store.unlock()
@ -1115,33 +1126,16 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, gro
defer sys.store.unlock() defer sys.store.unlock()
cr, found := sys.iamUsersMap[parentUser] cr, found := sys.iamUsersMap[parentUser]
switch { // Disallow service accounts to further create more service accounts.
// User found if found && cr.IsServiceAccount() {
case found: return auth.Credentials{}, errIAMActionNotAllowed
// Disallow service accounts to further create more service accounts. }
if cr.IsServiceAccount() {
return auth.Credentials{}, errIAMActionNotAllowed policies, err := sys.policyDBGet(parentUser, false)
} if err != nil {
// Allow creating service accounts for root user return auth.Credentials{}, err
case parentUser == globalActiveCred.AccessKey: }
// For LDAP/OpenID users we would need this fallback if len(policies) == 0 {
case sys.usersSysType != MinIOUsersSysType:
_, ok := sys.iamUserPolicyMap[parentUser]
if !ok {
var groupHasPolicy bool
for _, group := range groups {
_, ok = sys.iamGroupPolicyMap[group]
if !ok {
continue
}
groupHasPolicy = true
break
}
if !groupHasPolicy {
return auth.Credentials{}, errNoSuchUser
}
}
default:
return auth.Credentials{}, errNoSuchUser return auth.Credentials{}, errNoSuchUser
} }
@ -1157,7 +1151,6 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, gro
var ( var (
cred auth.Credentials cred auth.Credentials
err error
) )
if len(opts.accessKey) > 0 { if len(opts.accessKey) > 0 {
@ -1894,29 +1887,22 @@ func (sys *IAMSys) policyDBGet(name string, isGroup bool) (policies []string, er
return sys.iamGroupPolicyMap[name].toSlice(), nil return sys.iamGroupPolicyMap[name].toSlice(), nil
} }
var u auth.Credentials if name == globalActiveCred.AccessKey {
var ok bool return []string{"consoleAdmin"}, nil
if sys.usersSysType == MinIOUsersSysType { }
if name == globalActiveCred.AccessKey {
return []string{"consoleAdmin"}, nil
}
// When looking for a user's policies, we also check if the user // When looking for a user's policies, we also check if the user
// and the groups they are member of are enabled. // and the groups they are member of are enabled.
u, ok = sys.iamUsersMap[name] var parentName string
if !ok { u, ok := sys.iamUsersMap[name]
return nil, errNoSuchUser if ok {
} parentName = u.ParentUser
if !u.IsValid() {
return nil, nil
}
} }
mp, ok := sys.iamUserPolicyMap[name] mp, ok := sys.iamUserPolicyMap[name]
if !ok { if !ok {
if u.ParentUser != "" { if parentName != "" {
mp = sys.iamUserPolicyMap[u.ParentUser] mp = sys.iamUserPolicyMap[parentName]
} }
} }