mirror of
https://github.com/minio/minio.git
synced 2024-12-25 22:55:54 -05:00
parent
975237cbf8
commit
6d89435356
@ -940,8 +940,12 @@ func (a adminAPIHandlers) RemoveUser(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
accessKey := vars["accessKey"]
|
accessKey := vars["accessKey"]
|
||||||
if err := globalIAMSys.DeleteUser(accessKey); err != nil {
|
// Notify all other MinIO peers to delete user.
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
for _, nerr := range globalNotificationSys.DeleteUser(accessKey) {
|
||||||
|
if nerr.Err != nil {
|
||||||
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
|
logger.LogIf(ctx, nerr.Err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,8 +1010,8 @@ func (a adminAPIHandlers) SetUserStatus(w http.ResponseWriter, r *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify all other MinIO peers to reload users
|
// Notify all other MinIO peers to reload user.
|
||||||
for _, nerr := range globalNotificationSys.LoadUsers() {
|
for _, nerr := range globalNotificationSys.LoadUser(accessKey, false) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
logger.LogIf(ctx, nerr.Err)
|
logger.LogIf(ctx, nerr.Err)
|
||||||
@ -1065,8 +1069,8 @@ func (a adminAPIHandlers) AddUser(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify all other MinIO peers to reload users
|
// Notify all other Minio peers to reload user
|
||||||
for _, nerr := range globalNotificationSys.LoadUsers() {
|
for _, nerr := range globalNotificationSys.LoadUser(accessKey, false) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
logger.LogIf(ctx, nerr.Err)
|
logger.LogIf(ctx, nerr.Err)
|
||||||
@ -1083,7 +1087,7 @@ func (a adminAPIHandlers) ListCannedPolicies(w http.ResponseWriter, r *http.Requ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
policies, err := globalIAMSys.ListCannedPolicies()
|
policies, err := globalIAMSys.ListPolicies()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
@ -1115,13 +1119,13 @@ func (a adminAPIHandlers) RemoveCannedPolicy(w http.ResponseWriter, r *http.Requ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := globalIAMSys.DeleteCannedPolicy(policyName); err != nil {
|
if err := globalIAMSys.DeletePolicy(policyName); err != nil {
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify all other MinIO peers to reload users
|
// Notify all other MinIO peers to delete policy
|
||||||
for _, nerr := range globalNotificationSys.LoadUsers() {
|
for _, nerr := range globalNotificationSys.DeletePolicy(policyName) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
logger.LogIf(ctx, nerr.Err)
|
logger.LogIf(ctx, nerr.Err)
|
||||||
@ -1171,13 +1175,13 @@ func (a adminAPIHandlers) AddCannedPolicy(w http.ResponseWriter, r *http.Request
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalIAMSys.SetCannedPolicy(policyName, *iamPolicy); err != nil {
|
if err = globalIAMSys.SetPolicy(policyName, *iamPolicy); err != nil {
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify all other MinIO peers to reload users
|
// Notify all other MinIO peers to reload policy
|
||||||
for _, nerr := range globalNotificationSys.LoadUsers() {
|
for _, nerr := range globalNotificationSys.LoadPolicy(policyName) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
logger.LogIf(ctx, nerr.Err)
|
logger.LogIf(ctx, nerr.Err)
|
||||||
@ -1214,8 +1218,8 @@ func (a adminAPIHandlers) SetUserPolicy(w http.ResponseWriter, r *http.Request)
|
|||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify all other MinIO peers to reload users
|
// Notify all other Minio peers to reload user
|
||||||
for _, nerr := range globalNotificationSys.LoadUsers() {
|
for _, nerr := range globalNotificationSys.LoadUser(accessKey, false) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
logger.LogIf(ctx, nerr.Err)
|
logger.LogIf(ctx, nerr.Err)
|
||||||
|
396
cmd/iam.go
396
cmd/iam.go
@ -25,6 +25,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
etcd "github.com/coreos/etcd/clientv3"
|
etcd "github.com/coreos/etcd/clientv3"
|
||||||
|
"github.com/coreos/etcd/mvcc/mvccpb"
|
||||||
"github.com/minio/minio-go/v6/pkg/set"
|
"github.com/minio/minio-go/v6/pkg/set"
|
||||||
"github.com/minio/minio/cmd/logger"
|
"github.com/minio/minio/cmd/logger"
|
||||||
"github.com/minio/minio/pkg/auth"
|
"github.com/minio/minio/pkg/auth"
|
||||||
@ -60,6 +61,45 @@ type IAMSys struct {
|
|||||||
iamCannedPolicyMap map[string]iampolicy.Policy
|
iamCannedPolicyMap map[string]iampolicy.Policy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadPolicy - reloads a specific canned policy from backend disks or etcd.
|
||||||
|
func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error {
|
||||||
|
if objAPI == nil {
|
||||||
|
return errInvalidArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
sys.Lock()
|
||||||
|
defer sys.Unlock()
|
||||||
|
|
||||||
|
prefix := iamConfigPoliciesPrefix
|
||||||
|
if globalEtcdClient == nil {
|
||||||
|
return reloadPolicy(context.Background(), objAPI, prefix, policyName, sys.iamCannedPolicyMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, temp bool) error {
|
||||||
|
if objAPI == nil {
|
||||||
|
return errInvalidArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
sys.Lock()
|
||||||
|
defer sys.Unlock()
|
||||||
|
|
||||||
|
prefix := iamConfigUsersPrefix
|
||||||
|
if temp {
|
||||||
|
prefix = iamConfigSTSPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
if globalEtcdClient == nil {
|
||||||
|
return reloadUser(context.Background(), objAPI, prefix, accessKey, sys.iamUsersMap, sys.iamPolicyMap)
|
||||||
|
}
|
||||||
|
// When etcd is set, we use watch APIs so this code is not needed.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Load - loads iam subsystem
|
// Load - loads iam subsystem
|
||||||
func (sys *IAMSys) Load(objAPI ObjectLayer) error {
|
func (sys *IAMSys) Load(objAPI ObjectLayer) error {
|
||||||
if globalEtcdClient != nil {
|
if globalEtcdClient != nil {
|
||||||
@ -68,19 +108,63 @@ func (sys *IAMSys) Load(objAPI ObjectLayer) error {
|
|||||||
return sys.refresh(objAPI)
|
return sys.refresh(objAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init - initializes config system from iam.json
|
func (sys *IAMSys) reloadFromEvent(event *etcd.Event) {
|
||||||
func (sys *IAMSys) Init(objAPI ObjectLayer) error {
|
eventCreate := event.IsModify() || event.IsCreate()
|
||||||
if objAPI == nil {
|
eventDelete := event.Type == etcd.EventTypeDelete
|
||||||
return errInvalidArgument
|
usersPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigUsersPrefix)
|
||||||
|
stsPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigSTSPrefix)
|
||||||
|
policyPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPoliciesPrefix)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(),
|
||||||
|
defaultContextTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case eventCreate:
|
||||||
|
switch {
|
||||||
|
case usersPrefix:
|
||||||
|
accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key),
|
||||||
|
iamConfigUsersPrefix))
|
||||||
|
reloadEtcdUser(ctx, iamConfigUsersPrefix, accessKey,
|
||||||
|
sys.iamUsersMap, sys.iamPolicyMap)
|
||||||
|
case stsPrefix:
|
||||||
|
accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key),
|
||||||
|
iamConfigSTSPrefix))
|
||||||
|
reloadEtcdUser(ctx, iamConfigSTSPrefix, accessKey,
|
||||||
|
sys.iamUsersMap, sys.iamPolicyMap)
|
||||||
|
case policyPrefix:
|
||||||
|
policyName := path.Dir(strings.TrimPrefix(string(event.Kv.Key),
|
||||||
|
iamConfigPoliciesPrefix))
|
||||||
|
reloadEtcdPolicy(ctx, iamConfigPoliciesPrefix,
|
||||||
|
policyName, sys.iamCannedPolicyMap)
|
||||||
|
}
|
||||||
|
case eventDelete:
|
||||||
|
switch {
|
||||||
|
case usersPrefix:
|
||||||
|
accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key),
|
||||||
|
iamConfigUsersPrefix))
|
||||||
|
delete(sys.iamUsersMap, accessKey)
|
||||||
|
delete(sys.iamPolicyMap, accessKey)
|
||||||
|
case stsPrefix:
|
||||||
|
accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key),
|
||||||
|
iamConfigSTSPrefix))
|
||||||
|
delete(sys.iamUsersMap, accessKey)
|
||||||
|
delete(sys.iamPolicyMap, accessKey)
|
||||||
|
case policyPrefix:
|
||||||
|
policyName := path.Dir(strings.TrimPrefix(string(event.Kv.Key),
|
||||||
|
iamConfigPoliciesPrefix))
|
||||||
|
delete(sys.iamCannedPolicyMap, policyName)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if globalEtcdClient != nil {
|
// Watch etcd entries for IAM
|
||||||
defer func() {
|
func (sys *IAMSys) watchIAMEtcd() {
|
||||||
go func() {
|
watchEtcd := func() {
|
||||||
// Refresh IAMSys with etcd watch.
|
// Refresh IAMSys with etcd watch.
|
||||||
for {
|
for {
|
||||||
watchCh := globalEtcdClient.Watch(context.Background(),
|
watchCh := globalEtcdClient.Watch(context.Background(),
|
||||||
iamConfigPrefix, etcd.WithPrefix())
|
iamConfigPrefix, etcd.WithPrefix(), etcd.WithKeysOnly())
|
||||||
select {
|
select {
|
||||||
case <-GlobalServiceDoneCh:
|
case <-GlobalServiceDoneCh:
|
||||||
return
|
return
|
||||||
@ -96,18 +180,18 @@ func (sys *IAMSys) Init(objAPI ObjectLayer) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, event := range watchResp.Events {
|
for _, event := range watchResp.Events {
|
||||||
if event.IsModify() || event.IsCreate() || event.Type == etcd.EventTypeDelete {
|
sys.Lock()
|
||||||
sys.refreshEtcd()
|
sys.reloadFromEvent(event)
|
||||||
|
sys.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
go watchEtcd()
|
||||||
}()
|
}
|
||||||
} else {
|
|
||||||
defer func() {
|
func (sys *IAMSys) watchIAMDisk(objAPI ObjectLayer) {
|
||||||
// Refresh IAMSys in background.
|
watchDisk := func() {
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(globalRefreshIAMInterval)
|
ticker := time.NewTicker(globalRefreshIAMInterval)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
@ -118,8 +202,21 @@ func (sys *IAMSys) Init(objAPI ObjectLayer) error {
|
|||||||
sys.refresh(objAPI)
|
sys.refresh(objAPI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
}()
|
// Refresh IAMSys in background.
|
||||||
|
go watchDisk()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init - initializes config system from iam.json
|
||||||
|
func (sys *IAMSys) Init(objAPI ObjectLayer) error {
|
||||||
|
if objAPI == nil {
|
||||||
|
return errInvalidArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
if globalEtcdClient != nil {
|
||||||
|
defer sys.watchIAMEtcd()
|
||||||
|
} else {
|
||||||
|
defer sys.watchIAMDisk(objAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
doneCh := make(chan struct{})
|
doneCh := make(chan struct{})
|
||||||
@ -148,8 +245,8 @@ func (sys *IAMSys) Init(objAPI ObjectLayer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteCannedPolicy - deletes a canned policy.
|
// DeletePolicy - deletes a canned policy from backend or etcd.
|
||||||
func (sys *IAMSys) DeleteCannedPolicy(policyName string) error {
|
func (sys *IAMSys) DeletePolicy(policyName string) error {
|
||||||
objectAPI := newObjectLayerFn()
|
objectAPI := newObjectLayerFn()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return errServerNotInitialized
|
return errServerNotInitialized
|
||||||
@ -160,11 +257,17 @@ func (sys *IAMSys) DeleteCannedPolicy(policyName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
configFile := pathJoin(iamConfigPoliciesPrefix, policyName, iamPolicyFile)
|
pFile := pathJoin(iamConfigPoliciesPrefix, policyName, iamPolicyFile)
|
||||||
if globalEtcdClient != nil {
|
if globalEtcdClient != nil {
|
||||||
err = deleteConfigEtcd(context.Background(), globalEtcdClient, configFile)
|
err = deleteConfigEtcd(context.Background(), globalEtcdClient, pFile)
|
||||||
} else {
|
} else {
|
||||||
err = deleteConfig(context.Background(), objectAPI, configFile)
|
err = deleteConfig(context.Background(), objectAPI, pFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch err.(type) {
|
||||||
|
case ObjectNotFound:
|
||||||
|
// Ignore error if policy is already deleted.
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sys.Lock()
|
sys.Lock()
|
||||||
@ -174,8 +277,8 @@ func (sys *IAMSys) DeleteCannedPolicy(policyName string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListCannedPolicies - lists all canned policies.
|
// ListPolicies - lists all canned policies.
|
||||||
func (sys *IAMSys) ListCannedPolicies() (map[string][]byte, error) {
|
func (sys *IAMSys) ListPolicies() (map[string][]byte, error) {
|
||||||
objectAPI := newObjectLayerFn()
|
objectAPI := newObjectLayerFn()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return nil, errServerNotInitialized
|
return nil, errServerNotInitialized
|
||||||
@ -197,8 +300,8 @@ func (sys *IAMSys) ListCannedPolicies() (map[string][]byte, error) {
|
|||||||
return cannedPolicyMap, nil
|
return cannedPolicyMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCannedPolicy - sets a new canned policy.
|
// SetPolicy - sets a new canned policy.
|
||||||
func (sys *IAMSys) SetCannedPolicy(policyName string, p iampolicy.Policy) error {
|
func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error {
|
||||||
objectAPI := newObjectLayerFn()
|
objectAPI := newObjectLayerFn()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return errServerNotInitialized
|
return errServerNotInitialized
|
||||||
@ -279,11 +382,11 @@ func (sys *IAMSys) DeleteUser(accessKey string) error {
|
|||||||
pFile := pathJoin(iamConfigUsersPrefix, accessKey, iamPolicyFile)
|
pFile := pathJoin(iamConfigUsersPrefix, accessKey, iamPolicyFile)
|
||||||
iFile := pathJoin(iamConfigUsersPrefix, accessKey, iamIdentityFile)
|
iFile := pathJoin(iamConfigUsersPrefix, accessKey, iamIdentityFile)
|
||||||
if globalEtcdClient != nil {
|
if globalEtcdClient != nil {
|
||||||
// It is okay to ingnore errors when deleting policy.json for the user.
|
// It is okay to ignore errors when deleting policy.json for the user.
|
||||||
_ = deleteConfigEtcd(context.Background(), globalEtcdClient, pFile)
|
deleteConfigEtcd(context.Background(), globalEtcdClient, pFile)
|
||||||
err = deleteConfigEtcd(context.Background(), globalEtcdClient, iFile)
|
err = deleteConfigEtcd(context.Background(), globalEtcdClient, iFile)
|
||||||
} else {
|
} else {
|
||||||
// It is okay to ingnore errors when deleting policy.json for the user.
|
// It is okay to ignore errors when deleting policy.json for the user.
|
||||||
_ = deleteConfig(context.Background(), objectAPI, pFile)
|
_ = deleteConfig(context.Background(), objectAPI, pFile)
|
||||||
err = deleteConfig(context.Background(), objectAPI, iFile)
|
err = deleteConfig(context.Background(), objectAPI, iFile)
|
||||||
}
|
}
|
||||||
@ -291,7 +394,8 @@ func (sys *IAMSys) DeleteUser(accessKey string) error {
|
|||||||
//
|
//
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case ObjectNotFound:
|
case ObjectNotFound:
|
||||||
err = errNoSuchUser
|
// ignore if user is already deleted.
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sys.Lock()
|
sys.Lock()
|
||||||
@ -567,21 +671,9 @@ func (sys *IAMSys) IsAllowed(args iampolicy.Args) bool {
|
|||||||
|
|
||||||
var defaultContextTimeout = 30 * time.Second
|
var defaultContextTimeout = 30 * time.Second
|
||||||
|
|
||||||
// Similar to reloadUsers but updates users, policies maps from etcd server,
|
func etcdKvsToSet(prefix string, kvs []*mvccpb.KeyValue) set.StringSet {
|
||||||
func reloadEtcdUsers(prefix string, usersMap map[string]auth.Credentials, policyMap map[string]string) error {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout)
|
|
||||||
defer cancel()
|
|
||||||
r, err := globalEtcdClient.Get(ctx, prefix, etcd.WithPrefix(), etcd.WithKeysOnly())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// No users are created yet.
|
|
||||||
if r.Count == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
users := set.NewStringSet()
|
users := set.NewStringSet()
|
||||||
for _, kv := range r.Kvs {
|
for _, kv := range kvs {
|
||||||
// Extract user by stripping off the `prefix` value as suffix,
|
// Extract user by stripping off the `prefix` value as suffix,
|
||||||
// then strip off the remaining basename to obtain the prefix
|
// then strip off the remaining basename to obtain the prefix
|
||||||
// value, usually in the following form.
|
// value, usually in the following form.
|
||||||
@ -595,43 +687,45 @@ func reloadEtcdUsers(prefix string, usersMap map[string]auth.Credentials, policy
|
|||||||
users.Add(user)
|
users.Add(user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similar to reloadUsers but updates users, policies maps from etcd server,
|
||||||
|
func reloadEtcdUsers(prefix string, usersMap map[string]auth.Credentials, policyMap map[string]string) error {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout)
|
||||||
|
defer cancel()
|
||||||
|
r, err := globalEtcdClient.Get(ctx, prefix, etcd.WithPrefix(), etcd.WithKeysOnly())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// No users are created yet.
|
||||||
|
if r.Count == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
users := etcdKvsToSet(prefix, r.Kvs)
|
||||||
|
|
||||||
// Reload config and policies for all users.
|
// Reload config and policies for all users.
|
||||||
for _, user := range users.ToSlice() {
|
for _, user := range users.ToSlice() {
|
||||||
idFile := pathJoin(prefix, user, iamIdentityFile)
|
if err = reloadEtcdUser(ctx, prefix, user, usersMap, policyMap); err != nil {
|
||||||
pFile := pathJoin(prefix, user, iamPolicyFile)
|
|
||||||
cdata, cerr := readConfigEtcd(ctx, globalEtcdClient, idFile)
|
|
||||||
pdata, perr := readConfigEtcd(ctx, globalEtcdClient, pFile)
|
|
||||||
if cerr != nil && cerr != errConfigNotFound {
|
|
||||||
return cerr
|
|
||||||
}
|
|
||||||
if perr != nil && perr != errConfigNotFound {
|
|
||||||
return perr
|
|
||||||
}
|
|
||||||
if cerr == errConfigNotFound && perr == errConfigNotFound {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if cerr == nil {
|
|
||||||
var cred auth.Credentials
|
|
||||||
if err = json.Unmarshal(cdata, &cred); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cred.AccessKey = user
|
|
||||||
if cred.IsExpired() {
|
|
||||||
deleteConfigEtcd(ctx, globalEtcdClient, idFile)
|
|
||||||
deleteConfigEtcd(ctx, globalEtcdClient, pFile)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
usersMap[cred.AccessKey] = cred
|
return nil
|
||||||
}
|
}
|
||||||
if perr == nil {
|
|
||||||
var policyName string
|
func reloadEtcdPolicy(ctx context.Context, prefix string, policyName string,
|
||||||
if err = json.Unmarshal(pdata, &policyName); err != nil {
|
cannedPolicyMap map[string]iampolicy.Policy) error {
|
||||||
|
pFile := pathJoin(prefix, policyName, iamPolicyFile)
|
||||||
|
pdata, err := readConfigEtcd(ctx, globalEtcdClient, pFile)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
policyMap[user] = policyName
|
var p iampolicy.Policy
|
||||||
}
|
if err = json.Unmarshal(pdata, &p); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
cannedPolicyMap[policyName] = p
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,35 +741,29 @@ func reloadEtcdPolicies(prefix string, cannedPolicyMap map[string]iampolicy.Poli
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
policies := set.NewStringSet()
|
policies := etcdKvsToSet(prefix, r.Kvs)
|
||||||
for _, kv := range r.Kvs {
|
|
||||||
// Extract policy by stripping off the `prefix` value as suffix,
|
|
||||||
// then strip off the remaining basename to obtain the prefix
|
|
||||||
// value, usually in the following form.
|
|
||||||
//
|
|
||||||
// key := "config/iam/policies/newpolicy/identity.json"
|
|
||||||
// prefix := "config/iam/policies/"
|
|
||||||
// v := trim(trim(key, prefix), base(key)) == "newpolicy"
|
|
||||||
//
|
|
||||||
policyName := path.Clean(strings.TrimSuffix(strings.TrimPrefix(string(kv.Key), prefix), path.Base(string(kv.Key))))
|
|
||||||
if !policies.Contains(policyName) {
|
|
||||||
policies.Add(policyName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload config and policies for all policys.
|
// Reload config and policies for all policys.
|
||||||
for _, policyName := range policies.ToSlice() {
|
for _, policyName := range policies.ToSlice() {
|
||||||
|
if err = reloadEtcdPolicy(ctx, prefix, policyName, cannedPolicyMap); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func reloadPolicy(ctx context.Context, objectAPI ObjectLayer, prefix string,
|
||||||
|
policyName string, cannedPolicyMap map[string]iampolicy.Policy) error {
|
||||||
pFile := pathJoin(prefix, policyName, iamPolicyFile)
|
pFile := pathJoin(prefix, policyName, iamPolicyFile)
|
||||||
pdata, perr := readConfigEtcd(ctx, globalEtcdClient, pFile)
|
pdata, err := readConfig(context.Background(), objectAPI, pFile)
|
||||||
if perr != nil {
|
if err != nil {
|
||||||
return perr
|
return err
|
||||||
}
|
}
|
||||||
var p iampolicy.Policy
|
var p iampolicy.Policy
|
||||||
if err = json.Unmarshal(pdata, &p); err != nil {
|
if err = json.Unmarshal(pdata, &p); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cannedPolicyMap[policyName] = p
|
cannedPolicyMap[path.Base(prefix)] = p
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,16 +778,9 @@ func reloadPolicies(objectAPI ObjectLayer, prefix string, cannedPolicyMap map[st
|
|||||||
}
|
}
|
||||||
marker = lo.NextMarker
|
marker = lo.NextMarker
|
||||||
for _, prefix := range lo.Prefixes {
|
for _, prefix := range lo.Prefixes {
|
||||||
pFile := pathJoin(prefix, iamPolicyFile)
|
if err = reloadPolicy(context.Background(), objectAPI, "", prefix, cannedPolicyMap); err != nil {
|
||||||
pdata, perr := readConfig(context.Background(), objectAPI, pFile)
|
|
||||||
if perr != nil {
|
|
||||||
return perr
|
|
||||||
}
|
|
||||||
var p iampolicy.Policy
|
|
||||||
if err = json.Unmarshal(pdata, &p); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cannedPolicyMap[path.Base(prefix)] = p
|
|
||||||
}
|
}
|
||||||
if !lo.IsTruncated {
|
if !lo.IsTruncated {
|
||||||
break
|
break
|
||||||
@ -709,6 +790,86 @@ func reloadPolicies(objectAPI ObjectLayer, prefix string, cannedPolicyMap map[st
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reloadEtcdUser(ctx context.Context, prefix string, accessKey string,
|
||||||
|
usersMap map[string]auth.Credentials, policyMap map[string]string) error {
|
||||||
|
idFile := pathJoin(prefix, accessKey, iamIdentityFile)
|
||||||
|
pFile := pathJoin(prefix, accessKey, iamPolicyFile)
|
||||||
|
cdata, cerr := readConfigEtcd(ctx, globalEtcdClient, idFile)
|
||||||
|
pdata, perr := readConfigEtcd(ctx, globalEtcdClient, pFile)
|
||||||
|
if cerr != nil && cerr != errConfigNotFound {
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
if perr != nil && perr != errConfigNotFound {
|
||||||
|
return perr
|
||||||
|
}
|
||||||
|
if cerr == errConfigNotFound && perr == errConfigNotFound {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if cerr == nil {
|
||||||
|
var cred auth.Credentials
|
||||||
|
if err := json.Unmarshal(cdata, &cred); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cred.AccessKey = path.Base(accessKey)
|
||||||
|
if cred.IsExpired() {
|
||||||
|
// Delete expired identity.
|
||||||
|
deleteConfigEtcd(ctx, globalEtcdClient, idFile)
|
||||||
|
// Delete expired identity policy.
|
||||||
|
deleteConfigEtcd(ctx, globalEtcdClient, pFile)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
usersMap[cred.AccessKey] = cred
|
||||||
|
}
|
||||||
|
if perr == nil {
|
||||||
|
var policyName string
|
||||||
|
if err := json.Unmarshal(pdata, &policyName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
policyMap[path.Base(accessKey)] = policyName
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func reloadUser(ctx context.Context, objectAPI ObjectLayer, prefix string, accessKey string,
|
||||||
|
usersMap map[string]auth.Credentials, policyMap map[string]string) error {
|
||||||
|
idFile := pathJoin(prefix, accessKey, iamIdentityFile)
|
||||||
|
pFile := pathJoin(prefix, accessKey, iamPolicyFile)
|
||||||
|
cdata, cerr := readConfig(ctx, objectAPI, idFile)
|
||||||
|
pdata, perr := readConfig(ctx, objectAPI, pFile)
|
||||||
|
if cerr != nil && cerr != errConfigNotFound {
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
if perr != nil && perr != errConfigNotFound {
|
||||||
|
return perr
|
||||||
|
}
|
||||||
|
if cerr == errConfigNotFound && perr == errConfigNotFound {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if cerr == nil {
|
||||||
|
var cred auth.Credentials
|
||||||
|
if err := json.Unmarshal(cdata, &cred); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cred.AccessKey = path.Base(accessKey)
|
||||||
|
if cred.IsExpired() {
|
||||||
|
// Delete expired identity.
|
||||||
|
objectAPI.DeleteObject(context.Background(), minioMetaBucket, idFile)
|
||||||
|
// Delete expired identity policy.
|
||||||
|
objectAPI.DeleteObject(context.Background(), minioMetaBucket, pFile)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
usersMap[cred.AccessKey] = cred
|
||||||
|
}
|
||||||
|
if perr == nil {
|
||||||
|
var policyName string
|
||||||
|
if err := json.Unmarshal(pdata, &policyName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
policyMap[path.Base(accessKey)] = policyName
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// reloadUsers reads an updates users, policies from object layer into user and policy maps.
|
// reloadUsers reads an updates users, policies from object layer into user and policy maps.
|
||||||
func reloadUsers(objectAPI ObjectLayer, prefix string, usersMap map[string]auth.Credentials, policyMap map[string]string) error {
|
func reloadUsers(objectAPI ObjectLayer, prefix string, usersMap map[string]auth.Credentials, policyMap map[string]string) error {
|
||||||
marker := ""
|
marker := ""
|
||||||
@ -721,41 +882,10 @@ func reloadUsers(objectAPI ObjectLayer, prefix string, usersMap map[string]auth.
|
|||||||
}
|
}
|
||||||
marker = lo.NextMarker
|
marker = lo.NextMarker
|
||||||
for _, prefix := range lo.Prefixes {
|
for _, prefix := range lo.Prefixes {
|
||||||
idFile := pathJoin(prefix, iamIdentityFile)
|
// Prefix is empty because prefix is already part of the List output.
|
||||||
pFile := pathJoin(prefix, iamPolicyFile)
|
if err = reloadUser(context.Background(), objectAPI, "", prefix, usersMap, policyMap); err != nil {
|
||||||
cdata, cerr := readConfig(context.Background(), objectAPI, idFile)
|
|
||||||
pdata, perr := readConfig(context.Background(), objectAPI, pFile)
|
|
||||||
if cerr != nil && cerr != errConfigNotFound {
|
|
||||||
return cerr
|
|
||||||
}
|
|
||||||
if perr != nil && perr != errConfigNotFound {
|
|
||||||
return perr
|
|
||||||
}
|
|
||||||
if cerr == errConfigNotFound && perr == errConfigNotFound {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if cerr == nil {
|
|
||||||
var cred auth.Credentials
|
|
||||||
if err = json.Unmarshal(cdata, &cred); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cred.AccessKey = path.Base(prefix)
|
|
||||||
if cred.IsExpired() {
|
|
||||||
// Delete expired identity.
|
|
||||||
objectAPI.DeleteObject(context.Background(), minioMetaBucket, idFile)
|
|
||||||
// Delete expired identity policy.
|
|
||||||
objectAPI.DeleteObject(context.Background(), minioMetaBucket, pFile)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
usersMap[cred.AccessKey] = cred
|
|
||||||
}
|
|
||||||
if perr == nil {
|
|
||||||
var policyName string
|
|
||||||
if err = json.Unmarshal(pdata, &policyName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
policyMap[path.Base(prefix)] = policyName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !lo.IsTruncated {
|
if !lo.IsTruncated {
|
||||||
break
|
break
|
||||||
|
@ -157,6 +157,66 @@ func (sys *NotificationSys) ReloadFormat(dryRun bool) []NotificationPeerErr {
|
|||||||
return ng.Wait()
|
return ng.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletePolicy - deletes policy across all peers.
|
||||||
|
func (sys *NotificationSys) DeletePolicy(policyName string) []NotificationPeerErr {
|
||||||
|
ng := WithNPeers(len(sys.peerClients))
|
||||||
|
for idx, client := range sys.peerClients {
|
||||||
|
if client == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
client := client
|
||||||
|
ng.Go(context.Background(), func() error {
|
||||||
|
return client.DeletePolicy(policyName)
|
||||||
|
}, idx, *client.host)
|
||||||
|
}
|
||||||
|
return ng.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadPolicy - reloads a specific modified policy across all peers
|
||||||
|
func (sys *NotificationSys) LoadPolicy(policyName string) []NotificationPeerErr {
|
||||||
|
ng := WithNPeers(len(sys.peerClients))
|
||||||
|
for idx, client := range sys.peerClients {
|
||||||
|
if client == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
client := client
|
||||||
|
ng.Go(context.Background(), func() error {
|
||||||
|
return client.LoadPolicy(policyName)
|
||||||
|
}, idx, *client.host)
|
||||||
|
}
|
||||||
|
return ng.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUser - deletes a specific user across all peers
|
||||||
|
func (sys *NotificationSys) DeleteUser(accessKey string) []NotificationPeerErr {
|
||||||
|
ng := WithNPeers(len(sys.peerClients))
|
||||||
|
for idx, client := range sys.peerClients {
|
||||||
|
if client == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
client := client
|
||||||
|
ng.Go(context.Background(), func() error {
|
||||||
|
return client.DeleteUser(accessKey)
|
||||||
|
}, idx, *client.host)
|
||||||
|
}
|
||||||
|
return ng.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadUser - reloads a specific user across all peers
|
||||||
|
func (sys *NotificationSys) LoadUser(accessKey string, temp bool) []NotificationPeerErr {
|
||||||
|
ng := WithNPeers(len(sys.peerClients))
|
||||||
|
for idx, client := range sys.peerClients {
|
||||||
|
if client == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
client := client
|
||||||
|
ng.Go(context.Background(), func() error {
|
||||||
|
return client.LoadUser(accessKey, temp)
|
||||||
|
}, idx, *client.host)
|
||||||
|
}
|
||||||
|
return ng.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
// LoadUsers - calls LoadUsers RPC call on all peers.
|
// LoadUsers - calls LoadUsers RPC call on all peers.
|
||||||
func (sys *NotificationSys) LoadUsers() []NotificationPeerErr {
|
func (sys *NotificationSys) LoadUsers() []NotificationPeerErr {
|
||||||
ng := WithNPeers(len(sys.peerClients))
|
ng := WithNPeers(len(sys.peerClients))
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/minio/minio/cmd/http"
|
"github.com/minio/minio/cmd/http"
|
||||||
"github.com/minio/minio/cmd/logger"
|
"github.com/minio/minio/cmd/logger"
|
||||||
@ -337,6 +338,59 @@ func (client *peerRESTClient) PutBucketNotification(bucket string, rulesMap even
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletePolicy - delete a specific canned policy.
|
||||||
|
func (client *peerRESTClient) DeletePolicy(policyName string) (err error) {
|
||||||
|
values := make(url.Values)
|
||||||
|
values.Set(peerRESTPolicy, policyName)
|
||||||
|
|
||||||
|
respBody, err := client.call(peerRESTMethodDeletePolicy, values, nil, -1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer http.DrainBody(respBody)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadPolicy - reload a specific canned policy.
|
||||||
|
func (client *peerRESTClient) LoadPolicy(policyName string) (err error) {
|
||||||
|
values := make(url.Values)
|
||||||
|
values.Set(peerRESTPolicy, policyName)
|
||||||
|
|
||||||
|
respBody, err := client.call(peerRESTMethodLoadPolicy, values, nil, -1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer http.DrainBody(respBody)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUser - delete a specific user.
|
||||||
|
func (client *peerRESTClient) DeleteUser(accessKey string) (err error) {
|
||||||
|
values := make(url.Values)
|
||||||
|
values.Set(peerRESTUser, accessKey)
|
||||||
|
|
||||||
|
respBody, err := client.call(peerRESTMethodDeleteUser, values, nil, -1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer http.DrainBody(respBody)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadUser - reload a specific user.
|
||||||
|
func (client *peerRESTClient) LoadUser(accessKey string, temp bool) (err error) {
|
||||||
|
values := make(url.Values)
|
||||||
|
values.Set(peerRESTUser, accessKey)
|
||||||
|
values.Set(peerRESTUserTemp, strconv.FormatBool(temp))
|
||||||
|
|
||||||
|
respBody, err := client.call(peerRESTMethodLoadUser, values, nil, -1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer http.DrainBody(respBody)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// LoadUsers - send load users command to peer nodes.
|
// LoadUsers - send load users command to peer nodes.
|
||||||
func (client *peerRESTClient) LoadUsers() (err error) {
|
func (client *peerRESTClient) LoadUsers() (err error) {
|
||||||
respBody, err := client.call(peerRESTMethodLoadUsers, nil, nil, -1)
|
respBody, err := client.call(peerRESTMethodLoadUsers, nil, nil, -1)
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
const peerRESTVersion = "v1"
|
const peerRESTVersion = "v2"
|
||||||
const peerRESTPath = minioReservedBucketPath + "/peer/" + peerRESTVersion
|
const peerRESTPath = minioReservedBucketPath + "/peer/" + peerRESTVersion
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -28,6 +28,10 @@ const (
|
|||||||
peerRESTMethodSignalService = "signalservice"
|
peerRESTMethodSignalService = "signalservice"
|
||||||
peerRESTMethodGetLocks = "getlocks"
|
peerRESTMethodGetLocks = "getlocks"
|
||||||
peerRESTMethodBucketPolicyRemove = "removebucketpolicy"
|
peerRESTMethodBucketPolicyRemove = "removebucketpolicy"
|
||||||
|
peerRESTMethodLoadUser = "loaduser"
|
||||||
|
peerRESTMethodDeleteUser = "deleteuser"
|
||||||
|
peerRESTMethodLoadPolicy = "loadpolicy"
|
||||||
|
peerRESTMethodDeletePolicy = "deletepolicy"
|
||||||
peerRESTMethodLoadUsers = "loadusers"
|
peerRESTMethodLoadUsers = "loadusers"
|
||||||
peerRESTMethodStartProfiling = "startprofiling"
|
peerRESTMethodStartProfiling = "startprofiling"
|
||||||
peerRESTMethodDownloadProfilingData = "downloadprofilingdata"
|
peerRESTMethodDownloadProfilingData = "downloadprofilingdata"
|
||||||
@ -41,6 +45,9 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
peerRESTBucket = "bucket"
|
peerRESTBucket = "bucket"
|
||||||
|
peerRESTUser = "user"
|
||||||
|
peerRESTUserTemp = "user-temp"
|
||||||
|
peerRESTPolicy = "policy"
|
||||||
peerRESTSignal = "signal"
|
peerRESTSignal = "signal"
|
||||||
peerRESTProfiler = "profiler"
|
peerRESTProfiler = "profiler"
|
||||||
peerRESTDryRun = "dry-run"
|
peerRESTDryRun = "dry-run"
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -117,7 +118,125 @@ func (s *peerRESTServer) GetLocksHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadUsersHandler - returns server info.
|
// DeletePolicyHandler - deletes a policy on the server.
|
||||||
|
func (s *peerRESTServer) DeletePolicyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !s.IsValid(w, r) {
|
||||||
|
s.writeErrorResponse(w, errors.New("Invalid request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
objAPI := newObjectLayerFn()
|
||||||
|
if objAPI == nil {
|
||||||
|
s.writeErrorResponse(w, errServerNotInitialized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
policyName := vars[peerRESTPolicy]
|
||||||
|
if policyName == "" {
|
||||||
|
s.writeErrorResponse(w, errors.New("policyName is missing"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := globalIAMSys.DeletePolicy(policyName); err != nil {
|
||||||
|
s.writeErrorResponse(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadPolicyHandler - reloads a policy on the server.
|
||||||
|
func (s *peerRESTServer) LoadPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !s.IsValid(w, r) {
|
||||||
|
s.writeErrorResponse(w, errors.New("Invalid request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
objAPI := newObjectLayerFn()
|
||||||
|
if objAPI == nil {
|
||||||
|
s.writeErrorResponse(w, errServerNotInitialized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
policyName := vars[peerRESTPolicy]
|
||||||
|
if policyName == "" {
|
||||||
|
s.writeErrorResponse(w, errors.New("policyName is missing"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := globalIAMSys.LoadPolicy(objAPI, policyName); err != nil {
|
||||||
|
s.writeErrorResponse(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUserHandler - deletes a user on the server.
|
||||||
|
func (s *peerRESTServer) DeleteUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !s.IsValid(w, r) {
|
||||||
|
s.writeErrorResponse(w, errors.New("Invalid request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
objAPI := newObjectLayerFn()
|
||||||
|
if objAPI == nil {
|
||||||
|
s.writeErrorResponse(w, errServerNotInitialized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
accessKey := vars[peerRESTUser]
|
||||||
|
if accessKey == "" {
|
||||||
|
s.writeErrorResponse(w, errors.New("username is missing"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := globalIAMSys.DeleteUser(accessKey); err != nil {
|
||||||
|
s.writeErrorResponse(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadUserHandler - reloads a user on the server.
|
||||||
|
func (s *peerRESTServer) LoadUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !s.IsValid(w, r) {
|
||||||
|
s.writeErrorResponse(w, errors.New("Invalid request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
objAPI := newObjectLayerFn()
|
||||||
|
if objAPI == nil {
|
||||||
|
s.writeErrorResponse(w, errServerNotInitialized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
accessKey := vars[peerRESTUser]
|
||||||
|
if accessKey == "" {
|
||||||
|
s.writeErrorResponse(w, errors.New("username is missing"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
temp, err := strconv.ParseBool(vars[peerRESTUserTemp])
|
||||||
|
if err != nil {
|
||||||
|
s.writeErrorResponse(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = globalIAMSys.LoadUser(objAPI, accessKey, temp); err != nil {
|
||||||
|
s.writeErrorResponse(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadUsersHandler - reloads all users and canned policies.
|
||||||
func (s *peerRESTServer) LoadUsersHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *peerRESTServer) LoadUsersHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if !s.IsValid(w, r) {
|
if !s.IsValid(w, r) {
|
||||||
s.writeErrorResponse(w, errors.New("Invalid request"))
|
s.writeErrorResponse(w, errors.New("Invalid request"))
|
||||||
@ -576,6 +695,10 @@ func registerPeerRESTHandlers(router *mux.Router) {
|
|||||||
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketPolicyRemove).HandlerFunc(httpTraceAll(server.RemoveBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketPolicyRemove).HandlerFunc(httpTraceAll(server.RemoveBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketPolicySet).HandlerFunc(httpTraceHdrs(server.SetBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketPolicySet).HandlerFunc(httpTraceHdrs(server.SetBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
|
|
||||||
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodDeletePolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
||||||
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadPolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
||||||
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodDeleteUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser)...)
|
||||||
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...)
|
||||||
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadUsers).HandlerFunc(httpTraceAll(server.LoadUsersHandler))
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadUsers).HandlerFunc(httpTraceAll(server.LoadUsersHandler))
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodStartProfiling).HandlerFunc(httpTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...)
|
subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodStartProfiling).HandlerFunc(httpTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...)
|
||||||
|
@ -189,7 +189,7 @@ func (sts *stsAPIHandlers) AssumeRole(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify all other MinIO peers to reload temp users
|
// Notify all other MinIO peers to reload temp users
|
||||||
for _, nerr := range globalNotificationSys.LoadUsers() {
|
for _, nerr := range globalNotificationSys.LoadUser(cred.AccessKey, true) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
logger.LogIf(ctx, nerr.Err)
|
logger.LogIf(ctx, nerr.Err)
|
||||||
@ -306,7 +306,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify all other MinIO peers to reload temp users
|
// Notify all other MinIO peers to reload temp users
|
||||||
for _, nerr := range globalNotificationSys.LoadUsers() {
|
for _, nerr := range globalNotificationSys.LoadUser(cred.AccessKey, true) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||||
logger.LogIf(ctx, nerr.Err)
|
logger.LogIf(ctx, nerr.Err)
|
||||||
|
Loading…
Reference in New Issue
Block a user