Set the policy mapping for a user or group (#8036)

Add API to set policy mapping for a user or group

Contains a breaking Admin APIs change.

- Also enforce all applicable policies
- Removes the previous /set-user-policy API

 Bump up peerRESTVersion

Add get user info API to show groups of a user
This commit is contained in:
Aditya Manthramurthy
2019-08-13 13:41:06 -07:00
committed by kannappanr
parent bc79b435a2
commit bf9b619d86
10 changed files with 301 additions and 78 deletions

View File

@@ -259,6 +259,33 @@ func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error {
return nil
}
// LoadPolicyMapping - loads the mapped policy for a user or group
// from storage into server memory.
func (sys *IAMSys) LoadPolicyMapping(objAPI ObjectLayer, userOrGroup string, isGroup bool) error {
if objAPI == nil {
return errInvalidArgument
}
sys.Lock()
defer sys.Unlock()
if globalEtcdClient == nil {
var err error
if isGroup {
err = sys.store.loadMappedPolicy(userOrGroup, false, isGroup, sys.iamGroupPolicyMap)
} else {
err = sys.store.loadMappedPolicy(userOrGroup, false, isGroup, sys.iamUserPolicyMap)
}
// Ignore policy not mapped error
if err != nil && err != errConfigNotFound {
return err
}
}
// When etcd is set, we use watch APIs so this code is not needed.
return nil
}
// LoadUser - reloads a specific user from backend disks or etcd.
func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, isSTS bool) error {
if objAPI == nil {
@@ -516,6 +543,29 @@ func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) {
return users, nil
}
// GetUserInfo - get info on a user.
func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) {
objectAPI := newObjectLayerFn()
if objectAPI == nil {
return u, errServerNotInitialized
}
sys.RLock()
defer sys.RUnlock()
creds, found := sys.iamUsersMap[name]
if !found {
return u, errNoSuchUser
}
u = madmin.UserInfo{
PolicyName: sys.iamUserPolicyMap[name].Policy,
Status: madmin.AccountStatus(creds.Status),
MemberOf: sys.iamUserGroupMemberships[name].ToSlice(),
}
return u, nil
}
// SetUserStatus - sets current user status, supports disabled or enabled.
func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error {
objectAPI := newObjectLayerFn()
@@ -776,6 +826,16 @@ func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error {
// GetGroupDescription - builds up group description
func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err error) {
ps, err := sys.PolicyDBGet(group, true)
if err != nil {
return gd, err
}
// A group may be mapped to at most one policy.
policy := ""
if len(ps) > 0 {
policy = ps[0]
}
sys.RLock()
defer sys.RUnlock()
@@ -784,17 +844,6 @@ func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err e
return gd, errNoSuchGroup
}
var p []string
p, err = sys.policyDBGet(group, true)
if err != nil {
return gd, err
}
policy := ""
if len(p) > 0 {
policy = p[0]
}
return madmin.GroupDesc{
Name: group,
Status: gi.Status,
@@ -837,21 +886,28 @@ func (sys *IAMSys) policyDBSet(objectAPI ObjectLayer, name, policy string, isSTS
if name == "" || policy == "" {
return errInvalidArgument
}
if _, ok := sys.iamUsersMap[name]; !ok {
return errNoSuchUser
}
if _, ok := sys.iamPolicyDocsMap[policy]; !ok {
return errNoSuchPolicy
}
if _, ok := sys.iamUsersMap[name]; !ok {
return errNoSuchUser
if !isGroup {
if _, ok := sys.iamUsersMap[name]; !ok {
return errNoSuchUser
}
} else {
if _, ok := sys.iamGroupsMap[name]; !ok {
return errNoSuchGroup
}
}
mp := newMappedPolicy(policy)
if err := sys.store.saveMappedPolicy(name, isSTS, isGroup, mp); err != nil {
return err
}
sys.iamUserPolicyMap[name] = mp
if !isGroup {
sys.iamUserPolicyMap[name] = mp
} else {
sys.iamGroupPolicyMap[name] = mp
}
return nil
}
@@ -991,18 +1047,42 @@ func (sys *IAMSys) IsAllowed(args iampolicy.Args) bool {
return sys.IsAllowedSTS(args)
}
// Policies don't apply to the owner.
if args.IsOwner {
return true
}
policies, err := sys.PolicyDBGet(args.AccountName, false)
if err != nil {
logger.LogIf(context.Background(), err)
return false
}
if len(policies) == 0 {
// No policy found.
return false
}
// Policies were found, evaluate all of them.
sys.RLock()
defer sys.RUnlock()
// If policy is available for given user, check the policy.
if mp, found := sys.iamUserPolicyMap[args.AccountName]; found {
p, ok := sys.iamPolicyDocsMap[mp.Policy]
return ok && p.IsAllowed(args)
var availablePolicies []iampolicy.Policy
for _, pname := range policies {
p, found := sys.iamPolicyDocsMap[pname]
if found {
availablePolicies = append(availablePolicies, p)
}
}
// As policy is not available and OPA is not configured,
// return the owner value.
return args.IsOwner
if len(availablePolicies) == 0 {
return false
}
combinedPolicy := availablePolicies[0]
for i := 1; i < len(availablePolicies); i++ {
combinedPolicy.Statements = append(combinedPolicy.Statements,
availablePolicies[i].Statements...)
}
return combinedPolicy.IsAllowed(args)
}
// Set default canned policies only if not already overridden by users.