mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
Add option to policy info API to return create/mod timestamps (#13796)
- This introduces a new admin API with a query parameter (v=2) to return a response with the timestamps - Older API still works for compatibility/smooth transition in console
This commit is contained in:
parent
878d368cea
commit
44fefe5b9f
@ -1198,6 +1198,16 @@ func (a adminAPIHandlers) AccountInfoHandler(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
|
||||
// InfoCannedPolicy - GET /minio/admin/v3/info-canned-policy?name={policyName}
|
||||
//
|
||||
// Newer API response with policy timestamps is returned with query parameter
|
||||
// `v=2` like:
|
||||
//
|
||||
// GET /minio/admin/v3/info-canned-policy?name={policyName}&v=2
|
||||
//
|
||||
// The newer API will eventually become the default (and only) one. The older
|
||||
// response is to return only the policy JSON. The newer response returns
|
||||
// timestamps along with the policy JSON. Both versions are supported for now,
|
||||
// for smooth transition to new API.
|
||||
func (a adminAPIHandlers) InfoCannedPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "InfoCannedPolicy")
|
||||
|
||||
@ -1208,13 +1218,36 @@ func (a adminAPIHandlers) InfoCannedPolicy(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
policy, err := globalIAMSys.InfoPolicy(mux.Vars(r)["name"])
|
||||
name := mux.Vars(r)["name"]
|
||||
policies := newMappedPolicy(name).toSlice()
|
||||
if len(policies) != 1 {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, errTooManyPolicies), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
policyDoc, err := globalIAMSys.InfoPolicy(name)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := json.MarshalIndent(policy, "", " ")
|
||||
// Is the new API version being requested?
|
||||
infoPolicyAPIVersion := r.Form.Get("v")
|
||||
if infoPolicyAPIVersion == "2" {
|
||||
buf, err := json.MarshalIndent(policyDoc, "", " ")
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
w.Write(buf)
|
||||
return
|
||||
} else if infoPolicyAPIVersion != "" {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, errors.New("invalid version parameter 'v' supplied")), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
// Return the older API response value of just the policy json.
|
||||
buf, err := json.MarshalIndent(policyDoc.Policy, "", " ")
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
|
@ -29,26 +29,31 @@ import (
|
||||
|
||||
var errConfigNotFound = errors.New("config file not found")
|
||||
|
||||
func readConfig(ctx context.Context, objAPI ObjectLayer, configFile string) ([]byte, error) {
|
||||
func readConfigWithMetadata(ctx context.Context, objAPI ObjectLayer, configFile string) ([]byte, ObjectInfo, error) {
|
||||
r, err := objAPI.GetObjectNInfo(ctx, minioMetaBucket, configFile, nil, http.Header{}, readLock, ObjectOptions{})
|
||||
if err != nil {
|
||||
// Treat object not found as config not found.
|
||||
if isErrObjectNotFound(err) {
|
||||
return nil, errConfigNotFound
|
||||
return nil, ObjectInfo{}, errConfigNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
return nil, ObjectInfo{}, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, ObjectInfo{}, err
|
||||
}
|
||||
if len(buf) == 0 {
|
||||
return nil, errConfigNotFound
|
||||
return nil, ObjectInfo{}, errConfigNotFound
|
||||
}
|
||||
return buf, nil
|
||||
return buf, r.ObjInfo, nil
|
||||
}
|
||||
|
||||
func readConfig(ctx context.Context, objAPI ObjectLayer, configFile string) ([]byte, error) {
|
||||
buf, _, err := readConfigWithMetadata(ctx, objAPI, configFile)
|
||||
return buf, err
|
||||
}
|
||||
|
||||
type objectDeleter interface {
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/minio/minio/internal/auth"
|
||||
iampolicy "github.com/minio/pkg/iam/policy"
|
||||
)
|
||||
|
||||
type iamDummyStore struct {
|
||||
@ -64,7 +63,7 @@ func (ids *iamDummyStore) migrateBackendFormat(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ids *iamDummyStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error {
|
||||
func (ids *iamDummyStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]PolicyDoc) error {
|
||||
v, ok := ids.iamPolicyDocsMap[policy]
|
||||
if !ok {
|
||||
return errNoSuchPolicy
|
||||
@ -73,7 +72,7 @@ func (ids *iamDummyStore) loadPolicyDoc(ctx context.Context, policy string, m ma
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ids *iamDummyStore) loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error {
|
||||
func (ids *iamDummyStore) loadPolicyDocs(ctx context.Context, m map[string]PolicyDoc) error {
|
||||
for k, v := range ids.iamPolicyDocsMap {
|
||||
m[k] = v
|
||||
}
|
||||
@ -154,7 +153,7 @@ func (ids *iamDummyStore) deleteIAMConfig(ctx context.Context, path string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ids *iamDummyStore) savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error {
|
||||
func (ids *iamDummyStore) savePolicyDoc(ctx context.Context, policyName string, p PolicyDoc) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@ import (
|
||||
"github.com/minio/minio/internal/config"
|
||||
"github.com/minio/minio/internal/kms"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
iampolicy "github.com/minio/pkg/iam/policy"
|
||||
"go.etcd.io/etcd/api/v3/mvccpb"
|
||||
etcd "go.etcd.io/etcd/client/v3"
|
||||
)
|
||||
@ -115,7 +114,7 @@ func (ies *IAMEtcdStore) saveIAMConfig(ctx context.Context, item interface{}, it
|
||||
return saveKeyEtcd(ctx, ies.client, itemPath, data, opts...)
|
||||
}
|
||||
|
||||
func getIAMConfig(item interface{}, data []byte, itemPath string) error {
|
||||
func decryptData(data []byte, itemPath string) ([]byte, error) {
|
||||
var err error
|
||||
if !utf8.Valid(data) && GlobalKMS != nil {
|
||||
data, err = config.DecryptBytes(GlobalKMS, data, kms.Context{
|
||||
@ -127,11 +126,19 @@ func getIAMConfig(item interface{}, data []byte, itemPath string) error {
|
||||
data, err = config.DecryptBytes(GlobalKMS, data, kms.Context{
|
||||
minioMetaBucket: itemPath,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func getIAMConfig(item interface{}, data []byte, itemPath string) error {
|
||||
data, err := decryptData(data, itemPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return json.Unmarshal(data, item)
|
||||
}
|
||||
@ -144,6 +151,14 @@ func (ies *IAMEtcdStore) loadIAMConfig(ctx context.Context, item interface{}, pa
|
||||
return getIAMConfig(item, data, path)
|
||||
}
|
||||
|
||||
func (ies *IAMEtcdStore) loadIAMConfigBytes(ctx context.Context, path string) ([]byte, error) {
|
||||
data, err := readKeyEtcd(ctx, ies.client, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return decryptData(data, path)
|
||||
}
|
||||
|
||||
func (ies *IAMEtcdStore) deleteIAMConfig(ctx context.Context, path string) error {
|
||||
return deleteKeyEtcd(ctx, ies.client, path)
|
||||
}
|
||||
@ -263,34 +278,46 @@ func (ies *IAMEtcdStore) migrateBackendFormat(ctx context.Context) error {
|
||||
return ies.migrateToV1(ctx)
|
||||
}
|
||||
|
||||
func (ies *IAMEtcdStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error {
|
||||
var p iampolicy.Policy
|
||||
err := ies.loadIAMConfig(ctx, &p, getPolicyDocPath(policy))
|
||||
func (ies *IAMEtcdStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]PolicyDoc) error {
|
||||
data, err := ies.loadIAMConfigBytes(ctx, getPolicyDocPath(policy))
|
||||
if err != nil {
|
||||
if err == errConfigNotFound {
|
||||
return errNoSuchPolicy
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
var p PolicyDoc
|
||||
err = p.parseJSON(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m[policy] = p
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ies *IAMEtcdStore) getPolicyDocKV(ctx context.Context, kvs *mvccpb.KeyValue, m map[string]iampolicy.Policy) error {
|
||||
var p iampolicy.Policy
|
||||
err := getIAMConfig(&p, kvs.Value, string(kvs.Key))
|
||||
func (ies *IAMEtcdStore) getPolicyDocKV(ctx context.Context, kvs *mvccpb.KeyValue, m map[string]PolicyDoc) error {
|
||||
data, err := decryptData(kvs.Value, string(kvs.Key))
|
||||
if err != nil {
|
||||
if err == errConfigNotFound {
|
||||
return errNoSuchPolicy
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
var p PolicyDoc
|
||||
err = p.parseJSON(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
policy := extractPathPrefixAndSuffix(string(kvs.Key), iamConfigPoliciesPrefix, path.Base(string(kvs.Key)))
|
||||
m[policy] = p
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ies *IAMEtcdStore) loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error {
|
||||
func (ies *IAMEtcdStore) loadPolicyDocs(ctx context.Context, m map[string]PolicyDoc) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
|
||||
defer cancel()
|
||||
// Retrieve all keys and values to avoid too many calls to etcd in case of
|
||||
@ -473,7 +500,7 @@ func (ies *IAMEtcdStore) loadMappedPolicies(ctx context.Context, userType IAMUse
|
||||
|
||||
}
|
||||
|
||||
func (ies *IAMEtcdStore) savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error {
|
||||
func (ies *IAMEtcdStore) savePolicyDoc(ctx context.Context, policyName string, p PolicyDoc) error {
|
||||
return ies.saveIAMConfig(ctx, &p, getPolicyDocPath(policyName))
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ import (
|
||||
"github.com/minio/minio/internal/config"
|
||||
"github.com/minio/minio/internal/kms"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
iampolicy "github.com/minio/pkg/iam/policy"
|
||||
)
|
||||
|
||||
// IAMObjectStore implements IAMStorageAPI
|
||||
@ -218,19 +217,27 @@ func (iamOS *IAMObjectStore) saveIAMConfig(ctx context.Context, item interface{}
|
||||
return saveConfig(ctx, iamOS.objAPI, objPath, data)
|
||||
}
|
||||
|
||||
func (iamOS *IAMObjectStore) loadIAMConfig(ctx context.Context, item interface{}, objPath string) error {
|
||||
data, err := readConfig(ctx, iamOS.objAPI, objPath)
|
||||
func (iamOS *IAMObjectStore) loadIAMConfigBytesWithMetadata(ctx context.Context, objPath string) ([]byte, ObjectInfo, error) {
|
||||
data, meta, err := readConfigWithMetadata(ctx, iamOS.objAPI, objPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, meta, err
|
||||
}
|
||||
if !utf8.Valid(data) && GlobalKMS != nil {
|
||||
data, err = config.DecryptBytes(GlobalKMS, data, kms.Context{
|
||||
minioMetaBucket: path.Join(minioMetaBucket, objPath),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, meta, err
|
||||
}
|
||||
}
|
||||
return data, meta, nil
|
||||
}
|
||||
|
||||
func (iamOS *IAMObjectStore) loadIAMConfig(ctx context.Context, item interface{}, objPath string) error {
|
||||
data, _, err := iamOS.loadIAMConfigBytesWithMetadata(ctx, objPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return json.Unmarshal(data, item)
|
||||
}
|
||||
@ -239,20 +246,34 @@ func (iamOS *IAMObjectStore) deleteIAMConfig(ctx context.Context, path string) e
|
||||
return deleteConfig(ctx, iamOS.objAPI, path)
|
||||
}
|
||||
|
||||
func (iamOS *IAMObjectStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error {
|
||||
var p iampolicy.Policy
|
||||
err := iamOS.loadIAMConfig(ctx, &p, getPolicyDocPath(policy))
|
||||
func (iamOS *IAMObjectStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]PolicyDoc) error {
|
||||
data, objInfo, err := iamOS.loadIAMConfigBytesWithMetadata(ctx, getPolicyDocPath(policy))
|
||||
if err != nil {
|
||||
if err == errConfigNotFound {
|
||||
return errNoSuchPolicy
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
var p PolicyDoc
|
||||
err = p.parseJSON(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Version == 0 {
|
||||
// This means that policy was in the old version (without any
|
||||
// timestamp info). We fetch the mod time of the file and save
|
||||
// that as create and update date.
|
||||
p.CreateDate = objInfo.ModTime
|
||||
p.UpdateDate = objInfo.ModTime
|
||||
}
|
||||
|
||||
m[policy] = p
|
||||
return nil
|
||||
}
|
||||
|
||||
func (iamOS *IAMObjectStore) loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error {
|
||||
func (iamOS *IAMObjectStore) loadPolicyDocs(ctx context.Context, m map[string]PolicyDoc) error {
|
||||
for item := range listIAMConfigItems(ctx, iamOS.objAPI, iamConfigPoliciesPrefix) {
|
||||
if item.Err != nil {
|
||||
return item.Err
|
||||
@ -385,7 +406,7 @@ func (iamOS *IAMObjectStore) loadMappedPolicies(ctx context.Context, userType IA
|
||||
return nil
|
||||
}
|
||||
|
||||
func (iamOS *IAMObjectStore) savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error {
|
||||
func (iamOS *IAMObjectStore) savePolicyDoc(ctx context.Context, policyName string, p PolicyDoc) error {
|
||||
return iamOS.saveIAMConfig(ctx, &p, getPolicyDocPath(policyName))
|
||||
}
|
||||
|
||||
|
120
cmd/iam-store.go
120
cmd/iam-store.go
@ -24,8 +24,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/minio/madmin-go"
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/internal/auth"
|
||||
@ -169,6 +171,64 @@ func newMappedPolicy(policy string) MappedPolicy {
|
||||
return MappedPolicy{Version: 1, Policies: policy}
|
||||
}
|
||||
|
||||
// PolicyDoc represents an IAM policy with some metadata.
|
||||
type PolicyDoc struct {
|
||||
Version int `json:",omitempty"`
|
||||
Policy iampolicy.Policy
|
||||
CreateDate time.Time `json:",omitempty"`
|
||||
UpdateDate time.Time `json:",omitempty"`
|
||||
}
|
||||
|
||||
func newPolicyDoc(p iampolicy.Policy) PolicyDoc {
|
||||
now := UTCNow().Round(time.Millisecond)
|
||||
return PolicyDoc{
|
||||
Version: 1,
|
||||
Policy: p,
|
||||
CreateDate: now,
|
||||
UpdateDate: now,
|
||||
}
|
||||
}
|
||||
|
||||
// defaultPolicyDoc - used to wrap a default policy as PolicyDoc.
|
||||
func defaultPolicyDoc(p iampolicy.Policy) PolicyDoc {
|
||||
return PolicyDoc{
|
||||
Version: 1,
|
||||
Policy: p,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *PolicyDoc) update(p iampolicy.Policy) {
|
||||
now := UTCNow().Round(time.Millisecond)
|
||||
d.UpdateDate = now
|
||||
if d.CreateDate.IsZero() {
|
||||
d.CreateDate = now
|
||||
}
|
||||
d.Policy = p
|
||||
}
|
||||
|
||||
// parseJSON parses both the old and the new format for storing policy
|
||||
// definitions.
|
||||
//
|
||||
// The on-disk format of policy definitions has changed (around early 12/2021)
|
||||
// from iampolicy.Policy to PolicyDoc. To avoid a migration, loading supports
|
||||
// both the old and the new formats.
|
||||
func (d *PolicyDoc) parseJSON(data []byte) error {
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
var doc PolicyDoc
|
||||
err := json.Unmarshal(data, &doc)
|
||||
if err != nil {
|
||||
err2 := json.Unmarshal(data, &doc.Policy)
|
||||
if err2 != nil {
|
||||
// Just return the first error.
|
||||
return err
|
||||
}
|
||||
d.Policy = doc.Policy
|
||||
return nil
|
||||
}
|
||||
*d = doc
|
||||
return nil
|
||||
}
|
||||
|
||||
// key options
|
||||
type options struct {
|
||||
ttl int64 // expiry in seconds
|
||||
@ -182,7 +242,7 @@ type iamWatchEvent struct {
|
||||
// iamCache contains in-memory cache of IAM data.
|
||||
type iamCache struct {
|
||||
// map of policy names to policy definitions
|
||||
iamPolicyDocsMap map[string]iampolicy.Policy
|
||||
iamPolicyDocsMap map[string]PolicyDoc
|
||||
// map of usernames to credentials
|
||||
iamUsersMap map[string]auth.Credentials
|
||||
// map of group names to group info
|
||||
@ -197,7 +257,7 @@ type iamCache struct {
|
||||
|
||||
func newIamCache() *iamCache {
|
||||
return &iamCache{
|
||||
iamPolicyDocsMap: map[string]iampolicy.Policy{},
|
||||
iamPolicyDocsMap: map[string]PolicyDoc{},
|
||||
iamUsersMap: map[string]auth.Credentials{},
|
||||
iamGroupsMap: map[string]GroupInfo{},
|
||||
iamUserGroupMemberships: map[string]set.StringSet{},
|
||||
@ -332,8 +392,8 @@ type IAMStorageAPI interface {
|
||||
|
||||
getUsersSysType() UsersSysType
|
||||
|
||||
loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error
|
||||
loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error
|
||||
loadPolicyDoc(ctx context.Context, policy string, m map[string]PolicyDoc) error
|
||||
loadPolicyDocs(ctx context.Context, m map[string]PolicyDoc) error
|
||||
|
||||
loadUser(ctx context.Context, user string, userType IAMUserType, m map[string]auth.Credentials) error
|
||||
loadUsers(ctx context.Context, userType IAMUserType, m map[string]auth.Credentials) error
|
||||
@ -348,7 +408,7 @@ type IAMStorageAPI interface {
|
||||
loadIAMConfig(ctx context.Context, item interface{}, path string) error
|
||||
deleteIAMConfig(ctx context.Context, path string) error
|
||||
|
||||
savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error
|
||||
savePolicyDoc(ctx context.Context, policyName string, p PolicyDoc) error
|
||||
saveMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, mp MappedPolicy, opts ...options) error
|
||||
saveUserIdentity(ctx context.Context, name string, userType IAMUserType, u UserIdentity, opts ...options) error
|
||||
saveGroupInfo(ctx context.Context, group string, gi GroupInfo) error
|
||||
@ -366,10 +426,10 @@ type iamStorageWatcher interface {
|
||||
}
|
||||
|
||||
// Set default canned policies only if not already overridden by users.
|
||||
func setDefaultCannedPolicies(policies map[string]iampolicy.Policy) {
|
||||
func setDefaultCannedPolicies(policies map[string]PolicyDoc) {
|
||||
for _, v := range iampolicy.DefaultPolicies {
|
||||
if _, ok := policies[v.Name]; !ok {
|
||||
policies[v.Name] = v.Definition
|
||||
policies[v.Name] = defaultPolicyDoc(v.Definition)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -947,13 +1007,31 @@ func (store *IAMStoreSys) GetPolicy(name string) (iampolicy.Policy, error) {
|
||||
}
|
||||
v, ok := cache.iamPolicyDocsMap[policy]
|
||||
if !ok {
|
||||
return v, errNoSuchPolicy
|
||||
return v.Policy, errNoSuchPolicy
|
||||
}
|
||||
combinedPolicy = combinedPolicy.Merge(v)
|
||||
combinedPolicy = combinedPolicy.Merge(v.Policy)
|
||||
}
|
||||
return combinedPolicy, nil
|
||||
}
|
||||
|
||||
// GetPolicyDoc - gets the policy doc which has the policy and some metadata.
|
||||
// Exactly one policy must be specified here.
|
||||
func (store *IAMStoreSys) GetPolicyDoc(name string) (r PolicyDoc, err error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return r, errInvalidArgument
|
||||
}
|
||||
|
||||
cache := store.rlock()
|
||||
defer store.runlock()
|
||||
|
||||
v, ok := cache.iamPolicyDocsMap[name]
|
||||
if !ok {
|
||||
return r, errNoSuchPolicy
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// SetPolicy - creates a policy with name.
|
||||
func (store *IAMStoreSys) SetPolicy(ctx context.Context, name string, policy iampolicy.Policy) error {
|
||||
|
||||
@ -964,11 +1042,21 @@ func (store *IAMStoreSys) SetPolicy(ctx context.Context, name string, policy iam
|
||||
cache := store.lock()
|
||||
defer store.unlock()
|
||||
|
||||
if err := store.savePolicyDoc(ctx, name, policy); err != nil {
|
||||
var (
|
||||
d PolicyDoc
|
||||
ok bool
|
||||
)
|
||||
if d, ok = cache.iamPolicyDocsMap[name]; ok {
|
||||
d.update(policy)
|
||||
} else {
|
||||
d = newPolicyDoc(policy)
|
||||
}
|
||||
|
||||
if err := store.savePolicyDoc(ctx, name, d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cache.iamPolicyDocsMap[name] = policy
|
||||
cache.iamPolicyDocsMap[name] = d
|
||||
return nil
|
||||
|
||||
}
|
||||
@ -979,7 +1067,7 @@ func (store *IAMStoreSys) ListPolicies(ctx context.Context, bucketName string) (
|
||||
cache := store.lock()
|
||||
defer store.unlock()
|
||||
|
||||
m := map[string]iampolicy.Policy{}
|
||||
m := map[string]PolicyDoc{}
|
||||
err := store.loadPolicyDocs(ctx, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -992,8 +1080,8 @@ func (store *IAMStoreSys) ListPolicies(ctx context.Context, bucketName string) (
|
||||
|
||||
ret := map[string]iampolicy.Policy{}
|
||||
for k, v := range m {
|
||||
if bucketName == "" || v.MatchResource(bucketName) {
|
||||
ret[k] = v
|
||||
if bucketName == "" || v.Policy.MatchResource(bucketName) {
|
||||
ret[k] = v.Policy
|
||||
}
|
||||
}
|
||||
|
||||
@ -1011,9 +1099,9 @@ func filterPolicies(cache *iamCache, policyName string, bucketName string) (stri
|
||||
}
|
||||
p, found := cache.iamPolicyDocsMap[policy]
|
||||
if found {
|
||||
if bucketName == "" || p.MatchResource(bucketName) {
|
||||
if bucketName == "" || p.Policy.MatchResource(bucketName) {
|
||||
policies = append(policies, policy)
|
||||
combinedPolicy = combinedPolicy.Merge(p)
|
||||
combinedPolicy = combinedPolicy.Merge(p.Policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
23
cmd/iam.go
23
cmd/iam.go
@ -477,13 +477,28 @@ func (sys *IAMSys) DeletePolicy(ctx context.Context, policyName string, notifyPe
|
||||
return nil
|
||||
}
|
||||
|
||||
// InfoPolicy - expands the canned policy into its JSON structure.
|
||||
func (sys *IAMSys) InfoPolicy(policyName string) (iampolicy.Policy, error) {
|
||||
// InfoPolicy - returns the policy definition with some metadata.
|
||||
func (sys *IAMSys) InfoPolicy(policyName string) (*madmin.PolicyInfo, error) {
|
||||
if !sys.Initialized() {
|
||||
return iampolicy.Policy{}, errServerNotInitialized
|
||||
return nil, errServerNotInitialized
|
||||
}
|
||||
|
||||
return sys.store.GetPolicy(policyName)
|
||||
d, err := sys.store.GetPolicyDoc(policyName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pdata, err := json.Marshal(d.Policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &madmin.PolicyInfo{
|
||||
PolicyName: policyName,
|
||||
Policy: pdata,
|
||||
CreateDate: d.CreateDate,
|
||||
UpdateDate: d.UpdateDate,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListPolicies - lists all canned policies.
|
||||
|
@ -84,6 +84,10 @@ var errNoSuchPolicy = errors.New("Specified canned policy does not exist")
|
||||
// error returned when policy to be deleted is in use.
|
||||
var errPolicyInUse = errors.New("Specified policy is in use and cannot be deleted.")
|
||||
|
||||
// error returned when more than a single policy is specified when only one is
|
||||
// expectd.
|
||||
var errTooManyPolicies = errors.New("Only a single policy may be specified here.")
|
||||
|
||||
// error returned in IAM subsystem when an external users systems is configured.
|
||||
var errIAMActionNotAllowed = errors.New("Specified IAM action is not allowed")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user