mirror of
				https://github.com/minio/minio.git
				synced 2025-10-29 15:55:00 -04:00 
			
		
		
		
	add missing admin actions, enhance AccountUsageInfo (#9607)
This commit is contained in:
		
							parent
							
								
									247795dd36
								
							
						
					
					
						commit
						814ddc0923
					
				| @ -572,6 +572,111 @@ func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Re | ||||
| 	writeSuccessNoContent(w) | ||||
| } | ||||
| 
 | ||||
| // AccountUsageInfoHandler returns usage | ||||
| func (a adminAPIHandlers) AccountUsageInfoHandler(w http.ResponseWriter, r *http.Request) { | ||||
| 	ctx := newContext(r, w, "AccountUsageInfo") | ||||
| 
 | ||||
| 	defer logger.AuditLog(w, r, "AccountUsageInfo", mustGetClaimsFromToken(r)) | ||||
| 
 | ||||
| 	// Get current object layer instance. | ||||
| 	objectAPI := newObjectLayerWithoutSafeModeFn() | ||||
| 	if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { | ||||
| 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | ||||
| 	if s3Err != ErrNone { | ||||
| 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Set prefix value for "s3:prefix" policy conditionals. | ||||
| 	r.Header.Set("prefix", "") | ||||
| 
 | ||||
| 	// Set delimiter value for "s3:delimiter" policy conditionals. | ||||
| 	r.Header.Set("delimiter", SlashSeparator) | ||||
| 
 | ||||
| 	isAllowedAccess := func(bucketName string) (rd, wr bool) { | ||||
| 		// Use the following trick to filter in place | ||||
| 		// https://github.com/golang/go/wiki/SliceTricks#filter-in-place | ||||
| 		if globalIAMSys.IsAllowed(iampolicy.Args{ | ||||
| 			AccountName:     cred.AccessKey, | ||||
| 			Action:          iampolicy.ListBucketAction, | ||||
| 			BucketName:      bucketName, | ||||
| 			ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | ||||
| 			IsOwner:         owner, | ||||
| 			ObjectName:      "", | ||||
| 			Claims:          claims, | ||||
| 		}) { | ||||
| 			rd = true | ||||
| 		} | ||||
| 
 | ||||
| 		if globalIAMSys.IsAllowed(iampolicy.Args{ | ||||
| 			AccountName:     cred.AccessKey, | ||||
| 			Action:          iampolicy.PutObjectAction, | ||||
| 			BucketName:      bucketName, | ||||
| 			ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | ||||
| 			IsOwner:         owner, | ||||
| 			ObjectName:      "", | ||||
| 			Claims:          claims, | ||||
| 		}) { | ||||
| 			wr = true | ||||
| 		} | ||||
| 
 | ||||
| 		return rd, wr | ||||
| 	} | ||||
| 
 | ||||
| 	buckets, err := objectAPI.ListBuckets(ctx) | ||||
| 	if err != nil { | ||||
| 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Load the latest calculated data usage | ||||
| 	dataUsageInfo, err := loadDataUsageFromBackend(ctx, objectAPI) | ||||
| 	if err != nil { | ||||
| 		logger.LogIf(ctx, err) | ||||
| 	} | ||||
| 
 | ||||
| 	accountName := cred.AccessKey | ||||
| 	if cred.ParentUser != "" { | ||||
| 		accountName = cred.ParentUser | ||||
| 	} | ||||
| 
 | ||||
| 	acctInfo := madmin.AccountUsageInfo{ | ||||
| 		AccountName: accountName, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, bucket := range buckets { | ||||
| 		rd, wr := isAllowedAccess(bucket.Name) | ||||
| 		if rd || wr { | ||||
| 			var size uint64 | ||||
| 			// Fetch the data usage of the current bucket | ||||
| 			if !dataUsageInfo.LastUpdate.IsZero() && len(dataUsageInfo.BucketsSizes) > 0 { | ||||
| 				size = dataUsageInfo.BucketsSizes[bucket.Name] | ||||
| 			} | ||||
| 			acctInfo.Buckets = append(acctInfo.Buckets, madmin.BucketUsageInfo{ | ||||
| 				Name:    bucket.Name, | ||||
| 				Created: bucket.Created, | ||||
| 				Size:    size, | ||||
| 				Access: madmin.AccountAccess{ | ||||
| 					Read:  rd, | ||||
| 					Write: wr, | ||||
| 				}, | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	usageInfoJSON, err := json.Marshal(acctInfo) | ||||
| 	if err != nil { | ||||
| 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	writeSuccessResponseJSON(w, usageInfoJSON) | ||||
| } | ||||
| 
 | ||||
| // InfoCannedPolicyV2 - GET /minio/admin/v2/info-canned-policy?name={policyName} | ||||
| func (a adminAPIHandlers) InfoCannedPolicyV2(w http.ResponseWriter, r *http.Request) { | ||||
| 	ctx := newContext(r, w, "InfoCannedPolicyV2") | ||||
|  | ||||
| @ -326,70 +326,6 @@ func (a adminAPIHandlers) DataUsageInfoHandler(w http.ResponseWriter, r *http.Re | ||||
| 	writeSuccessResponseJSON(w, dataUsageInfoJSON) | ||||
| } | ||||
| 
 | ||||
| func (a adminAPIHandlers) AccountingUsageInfoHandler(w http.ResponseWriter, r *http.Request) { | ||||
| 	ctx := newContext(r, w, "AccountingUsageInfo") | ||||
| 
 | ||||
| 	defer logger.AuditLog(w, r, "AccountingUsageInfo", mustGetClaimsFromToken(r)) | ||||
| 
 | ||||
| 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.AccountingUsageInfoAdminAction) | ||||
| 	if objectAPI == nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	var accountingUsageInfo = make(map[string]madmin.BucketAccountingUsage) | ||||
| 
 | ||||
| 	buckets, err := objectAPI.ListBuckets(ctx) | ||||
| 	if err != nil { | ||||
| 		// writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), r.URL) | ||||
| 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	users, err := globalIAMSys.ListUsers() | ||||
| 	if err != nil { | ||||
| 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Load the latest calculated data usage | ||||
| 	dataUsageInfo, err := loadDataUsageFromBackend(ctx, objectAPI) | ||||
| 	if err != nil { | ||||
| 		logger.LogIf(ctx, err) | ||||
| 	} | ||||
| 
 | ||||
| 	// Calculate for each bucket, which users are allowed to access to it | ||||
| 	for _, bucket := range buckets { | ||||
| 		bucketUsageInfo := madmin.BucketAccountingUsage{} | ||||
| 
 | ||||
| 		// Fetch the data usage of the current bucket | ||||
| 		if !dataUsageInfo.LastUpdate.IsZero() && dataUsageInfo.BucketsSizes != nil { | ||||
| 			bucketUsageInfo.Size = dataUsageInfo.BucketsSizes[bucket.Name] | ||||
| 		} | ||||
| 
 | ||||
| 		for user := range users { | ||||
| 			rd, wr, custom := globalIAMSys.GetAccountAccess(user, bucket.Name) | ||||
| 			if rd || wr || custom { | ||||
| 				bucketUsageInfo.AccessList = append(bucketUsageInfo.AccessList, madmin.AccountAccess{ | ||||
| 					AccountName: user, | ||||
| 					Read:        rd, | ||||
| 					Write:       wr, | ||||
| 					Custom:      custom, | ||||
| 				}) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		accountingUsageInfo[bucket.Name] = bucketUsageInfo | ||||
| 	} | ||||
| 
 | ||||
| 	usageInfoJSON, err := json.Marshal(accountingUsageInfo) | ||||
| 	if err != nil { | ||||
| 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	writeSuccessResponseJSON(w, usageInfoJSON) | ||||
| } | ||||
| 
 | ||||
| func newLockEntry(l lockRequesterInfo, resource, server string) *madmin.LockEntry { | ||||
| 	entry := &madmin.LockEntry{ | ||||
| 		Timestamp:  l.Timestamp, | ||||
|  | ||||
| @ -62,8 +62,6 @@ func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps, enab | ||||
| 		// DataUsageInfo operations | ||||
| 		adminRouter.Methods(http.MethodGet).Path(adminVersion + "/datausageinfo").HandlerFunc(httpTraceAll(adminAPI.DataUsageInfoHandler)) | ||||
| 
 | ||||
| 		adminRouter.Methods(http.MethodGet).Path(adminVersion + "/accountingusageinfo").HandlerFunc(httpTraceAll(adminAPI.AccountingUsageInfoHandler)) | ||||
| 
 | ||||
| 		if globalIsDistXL || globalIsXL { | ||||
| 			/// Heal operations | ||||
| 
 | ||||
| @ -115,6 +113,9 @@ func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps, enab | ||||
| 			adminRouter.Methods(http.MethodPut).Path(adminVersion+"/add-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.AddCannedPolicy)).Queries("name", "{name:.*}") | ||||
| 
 | ||||
| 			// Add user IAM | ||||
| 
 | ||||
| 			adminRouter.Methods(http.MethodGet).Path(adminVersion + "/accountusageinfo").HandlerFunc(httpTraceAll(adminAPI.AccountUsageInfoHandler)) | ||||
| 
 | ||||
| 			adminRouter.Methods(http.MethodPut).Path(adminVersion+"/add-user").HandlerFunc(httpTraceHdrs(adminAPI.AddUser)).Queries("accessKey", "{accessKey:.*}") | ||||
| 
 | ||||
| 			adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-user-status").HandlerFunc(httpTraceHdrs(adminAPI.SetUserStatus)).Queries("accessKey", "{accessKey:.*}").Queries("status", "{status:.*}") | ||||
|  | ||||
							
								
								
									
										105
									
								
								cmd/iam.go
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								cmd/iam.go
									
									
									
									
									
								
							| @ -28,7 +28,6 @@ import ( | ||||
| 	"github.com/minio/minio/cmd/config" | ||||
| 	"github.com/minio/minio/cmd/logger" | ||||
| 	"github.com/minio/minio/pkg/auth" | ||||
| 	"github.com/minio/minio/pkg/bucket/policy" | ||||
| 	iampolicy "github.com/minio/minio/pkg/iam/policy" | ||||
| 	"github.com/minio/minio/pkg/madmin" | ||||
| ) | ||||
| @ -1345,110 +1344,6 @@ func (sys *IAMSys) policyDBSet(name, policyName string, userType IAMUserType, is | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| var iamAccountReadAccessActions = iampolicy.NewActionSet( | ||||
| 	iampolicy.ListMultipartUploadPartsAction, | ||||
| 	iampolicy.ListBucketMultipartUploadsAction, | ||||
| 	iampolicy.ListBucketAction, | ||||
| 	iampolicy.HeadBucketAction, | ||||
| 	iampolicy.GetObjectAction, | ||||
| 	iampolicy.GetBucketLocationAction, | ||||
| 
 | ||||
| 	// iampolicy.ListAllMyBucketsAction, | ||||
| ) | ||||
| 
 | ||||
| var iamAccountWriteAccessActions = iampolicy.NewActionSet( | ||||
| 	iampolicy.AbortMultipartUploadAction, | ||||
| 	iampolicy.CreateBucketAction, | ||||
| 	iampolicy.PutObjectAction, | ||||
| 	iampolicy.DeleteObjectAction, | ||||
| 	iampolicy.DeleteBucketAction, | ||||
| ) | ||||
| 
 | ||||
| var iamAccountOtherAccessActions = iampolicy.NewActionSet( | ||||
| 	iampolicy.BypassGovernanceRetentionAction, | ||||
| 	iampolicy.PutObjectRetentionAction, | ||||
| 	iampolicy.GetObjectRetentionAction, | ||||
| 	iampolicy.GetObjectLegalHoldAction, | ||||
| 	iampolicy.PutObjectLegalHoldAction, | ||||
| 	iampolicy.GetBucketObjectLockConfigurationAction, | ||||
| 	iampolicy.PutBucketObjectLockConfigurationAction, | ||||
| 
 | ||||
| 	iampolicy.ListenBucketNotificationAction, | ||||
| 
 | ||||
| 	iampolicy.PutBucketLifecycleAction, | ||||
| 	iampolicy.GetBucketLifecycleAction, | ||||
| 
 | ||||
| 	iampolicy.PutBucketNotificationAction, | ||||
| 	iampolicy.GetBucketNotificationAction, | ||||
| 
 | ||||
| 	iampolicy.PutBucketPolicyAction, | ||||
| 	iampolicy.DeleteBucketPolicyAction, | ||||
| 	iampolicy.GetBucketPolicyAction, | ||||
| 
 | ||||
| 	iampolicy.PutBucketEncryptionAction, | ||||
| 	iampolicy.GetBucketEncryptionAction, | ||||
| ) | ||||
| 
 | ||||
| // GetAccountAccess iterates over all policies documents associated to a user | ||||
| // and returns if the user has read and/or write access to any resource. | ||||
| func (sys *IAMSys) GetAccountAccess(accountName, bucket string) (rd, wr, o bool) { | ||||
| 	policies, err := sys.PolicyDBGet(accountName, false) | ||||
| 	if err != nil { | ||||
| 		return false, false, false | ||||
| 	} | ||||
| 
 | ||||
| 	if len(policies) == 0 { | ||||
| 		// No policy found. | ||||
| 		return false, false, false | ||||
| 	} | ||||
| 
 | ||||
| 	// Policies were found, evaluate all of them. | ||||
| 	sys.store.rlock() | ||||
| 	defer sys.store.runlock() | ||||
| 
 | ||||
| 	var availablePolicies []iampolicy.Policy | ||||
| 	for _, pname := range policies { | ||||
| 		p, found := sys.iamPolicyDocsMap[pname] | ||||
| 		if found { | ||||
| 			availablePolicies = append(availablePolicies, p) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if len(availablePolicies) == 0 { | ||||
| 		return false, false, false | ||||
| 	} | ||||
| 
 | ||||
| 	combinedPolicy := availablePolicies[0] | ||||
| 	for i := 1; i < len(availablePolicies); i++ { | ||||
| 		combinedPolicy.Statements = append(combinedPolicy.Statements, | ||||
| 			availablePolicies[i].Statements...) | ||||
| 	} | ||||
| 
 | ||||
| 	allActions := iampolicy.NewActionSet(iampolicy.AllActions) | ||||
| 	for _, st := range combinedPolicy.Statements { | ||||
| 		// Ignore if this is not an allow policy statement | ||||
| 		if st.Effect != policy.Allow { | ||||
| 			continue | ||||
| 		} | ||||
| 		// Fast calculation if there is s3:* permissions to any resource | ||||
| 		if !st.Actions.Intersection(allActions).IsEmpty() { | ||||
| 			rd, wr, o = true, true, true | ||||
| 			break | ||||
| 		} | ||||
| 		if !st.Actions.Intersection(iamAccountReadAccessActions).IsEmpty() { | ||||
| 			rd = true | ||||
| 		} | ||||
| 		if !st.Actions.Intersection(iamAccountWriteAccessActions).IsEmpty() { | ||||
| 			wr = true | ||||
| 		} | ||||
| 		if !st.Actions.Intersection(iamAccountOtherAccessActions).IsEmpty() { | ||||
| 			o = true | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // PolicyDBGet - gets policy set on a user or group. Since a user may | ||||
| // be a member of multiple groups, this function returns an array of | ||||
| // applicable policies (each group is mapped to at most one policy). | ||||
|  | ||||
| @ -140,7 +140,6 @@ const ( | ||||
| 
 | ||||
| // List of all supported actions. | ||||
| var supportedActions = map[Action]struct{}{ | ||||
| 	AllActions:                             {}, | ||||
| 	AbortMultipartUploadAction:             {}, | ||||
| 	CreateBucketAction:                     {}, | ||||
| 	DeleteBucketAction:                     {}, | ||||
| @ -157,25 +156,26 @@ var supportedActions = map[Action]struct{}{ | ||||
| 	ListBucketMultipartUploadsAction:       {}, | ||||
| 	ListenBucketNotificationAction:         {}, | ||||
| 	ListMultipartUploadPartsAction:         {}, | ||||
| 	PutBucketLifecycleAction:               {}, | ||||
| 	GetBucketLifecycleAction:               {}, | ||||
| 	PutBucketNotificationAction:            {}, | ||||
| 	PutBucketPolicyAction:                  {}, | ||||
| 	PutObjectAction:                        {}, | ||||
| 	GetBucketLifecycleAction:               {}, | ||||
| 	PutBucketLifecycleAction:               {}, | ||||
| 	BypassGovernanceRetentionAction:        {}, | ||||
| 	PutObjectRetentionAction:               {}, | ||||
| 	GetObjectRetentionAction:               {}, | ||||
| 	GetObjectLegalHoldAction:               {}, | ||||
| 	PutObjectLegalHoldAction:               {}, | ||||
| 	PutBucketObjectLockConfigurationAction: {}, | ||||
| 	GetBucketObjectLockConfigurationAction: {}, | ||||
| 	PutBucketTaggingAction:                 {}, | ||||
| 	PutBucketObjectLockConfigurationAction: {}, | ||||
| 	GetBucketTaggingAction:                 {}, | ||||
| 	BypassGovernanceRetentionAction:        {}, | ||||
| 	PutBucketTaggingAction:                 {}, | ||||
| 	GetObjectTaggingAction:                 {}, | ||||
| 	PutObjectTaggingAction:                 {}, | ||||
| 	DeleteObjectTaggingAction:              {}, | ||||
| 	PutBucketEncryptionAction:              {}, | ||||
| 	GetBucketEncryptionAction:              {}, | ||||
| 	AllActions:                             {}, | ||||
| } | ||||
| 
 | ||||
| // List of all supported object actions. | ||||
|  | ||||
| @ -31,8 +31,6 @@ const ( | ||||
| 
 | ||||
| 	// StorageInfoAdminAction - allow listing server info | ||||
| 	StorageInfoAdminAction = "admin:StorageInfo" | ||||
| 	// AccountingUsageInfoAdminAction - allow listing accounting usage info | ||||
| 	AccountingUsageInfoAdminAction = "admin:AccountingUsageInfo" | ||||
| 	// DataUsageInfoAdminAction - allow listing data usage info | ||||
| 	DataUsageInfoAdminAction = "admin:DataUsageInfo" | ||||
| 	// TopLocksAdminAction - allow listing top locks | ||||
| @ -114,17 +112,16 @@ const ( | ||||
| 
 | ||||
| // List of all supported admin actions. | ||||
| var supportedAdminActions = map[AdminAction]struct{}{ | ||||
| 	AllAdminActions:                {}, | ||||
| 	HealAdminAction:                {}, | ||||
| 	ServerInfoAdminAction:          {}, | ||||
| 	StorageInfoAdminAction:         {}, | ||||
| 	DataUsageInfoAdminAction:       {}, | ||||
| 	TopLocksAdminAction:            {}, | ||||
| 	ProfilingAdminAction:           {}, | ||||
| 	TraceAdminAction:               {}, | ||||
| 	OBDInfoAdminAction:             {}, | ||||
| 	ConsoleLogAdminAction:          {}, | ||||
| 	KMSKeyStatusAdminAction:        {}, | ||||
| 	ServerInfoAdminAction:          {}, | ||||
| 	OBDInfoAdminAction:             {}, | ||||
| 	ServerUpdateAdminAction:        {}, | ||||
| 	ServiceRestartAdminAction:      {}, | ||||
| 	ServiceStopAdminAction:         {}, | ||||
| @ -137,6 +134,7 @@ var supportedAdminActions = map[AdminAction]struct{}{ | ||||
| 	GetUserAdminAction:             {}, | ||||
| 	AddUserToGroupAdminAction:      {}, | ||||
| 	RemoveUserFromGroupAdminAction: {}, | ||||
| 	GetGroupAdminAction:            {}, | ||||
| 	ListGroupsAdminAction:          {}, | ||||
| 	EnableGroupAdminAction:         {}, | ||||
| 	DisableGroupAdminAction:        {}, | ||||
| @ -144,9 +142,10 @@ var supportedAdminActions = map[AdminAction]struct{}{ | ||||
| 	DeletePolicyAdminAction:        {}, | ||||
| 	GetPolicyAdminAction:           {}, | ||||
| 	AttachPolicyAdminAction:        {}, | ||||
| 	ListUserPoliciesAdminAction:    {}, | ||||
| 	SetBucketQuotaAdminAction:      {}, | ||||
| 	GetBucketQuotaAdminAction:      {}, | ||||
| 	ListUserPoliciesAdminAction:    {}, | ||||
| 	AllAdminActions:                {}, | ||||
| } | ||||
| 
 | ||||
| func parseAdminAction(s string) (AdminAction, error) { | ||||
|  | ||||
| @ -192,50 +192,6 @@ func (adm *AdminClient) DataUsageInfo(ctx context.Context) (DataUsageInfo, error | ||||
| 	return dataUsageInfo, nil | ||||
| } | ||||
| 
 | ||||
| // AccountAccess contains information about | ||||
| type AccountAccess struct { | ||||
| 	AccountName string `json:"accountName"` | ||||
| 	Read        bool   `json:"read"` | ||||
| 	Write       bool   `json:"write"` | ||||
| 	Custom      bool   `json:"custom"` | ||||
| } | ||||
| 
 | ||||
| // BucketAccountingUsage represents the accounting usage of a particular bucket | ||||
| type BucketAccountingUsage struct { | ||||
| 	Size       uint64          `json:"size"` | ||||
| 	AccessList []AccountAccess `json:"accessList"` | ||||
| } | ||||
| 
 | ||||
| // AccountingUsageInfo returns the accounting usage info, currently it returns | ||||
| // the type of access of different accounts to the different buckets. | ||||
| func (adm *AdminClient) AccountingUsageInfo(ctx context.Context) (map[string]BucketAccountingUsage, error) { | ||||
| 	resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/accountingusageinfo"}) | ||||
| 	defer closeResponse(resp) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Check response http status code | ||||
| 	if resp.StatusCode != http.StatusOK { | ||||
| 		return nil, httpRespToErrorResponse(resp) | ||||
| 	} | ||||
| 
 | ||||
| 	// Unmarshal the server's json response | ||||
| 	var accountingUsageInfo map[string]BucketAccountingUsage | ||||
| 
 | ||||
| 	respBytes, err := ioutil.ReadAll(resp.Body) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	err = json.Unmarshal(respBytes, &accountingUsageInfo) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return accountingUsageInfo, nil | ||||
| } | ||||
| 
 | ||||
| // InfoMessage container to hold server admin related information. | ||||
| type InfoMessage struct { | ||||
| 	Mode         string             `json:"mode,omitempty"` | ||||
|  | ||||
| @ -23,11 +23,63 @@ import ( | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/minio/minio/pkg/auth" | ||||
| 	iampolicy "github.com/minio/minio/pkg/iam/policy" | ||||
| ) | ||||
| 
 | ||||
| // AccountAccess contains information about | ||||
| type AccountAccess struct { | ||||
| 	Read  bool `json:"read"` | ||||
| 	Write bool `json:"write"` | ||||
| } | ||||
| 
 | ||||
| // BucketUsageInfo represents bucket usage of a bucket, and its relevant | ||||
| // access type for an account | ||||
| type BucketUsageInfo struct { | ||||
| 	Name    string        `json:"name"` | ||||
| 	Size    uint64        `json:"size"` | ||||
| 	Created time.Time     `json:"created"` | ||||
| 	Access  AccountAccess `json:"access"` | ||||
| } | ||||
| 
 | ||||
| // AccountUsageInfo represents the account usage info of an | ||||
| // account across buckets. | ||||
| type AccountUsageInfo struct { | ||||
| 	AccountName string | ||||
| 	Buckets     []BucketUsageInfo | ||||
| } | ||||
| 
 | ||||
| // AccountUsageInfo returns the usage info for the authenticating account. | ||||
| func (adm *AdminClient) AccountUsageInfo(ctx context.Context) (AccountUsageInfo, error) { | ||||
| 	resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/accountusageinfo"}) | ||||
| 	defer closeResponse(resp) | ||||
| 	if err != nil { | ||||
| 		return AccountUsageInfo{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Check response http status code | ||||
| 	if resp.StatusCode != http.StatusOK { | ||||
| 		return AccountUsageInfo{}, httpRespToErrorResponse(resp) | ||||
| 	} | ||||
| 
 | ||||
| 	// Unmarshal the server's json response | ||||
| 	var accountInfo AccountUsageInfo | ||||
| 
 | ||||
| 	respBytes, err := ioutil.ReadAll(resp.Body) | ||||
| 	if err != nil { | ||||
| 		return AccountUsageInfo{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	err = json.Unmarshal(respBytes, &accountInfo) | ||||
| 	if err != nil { | ||||
| 		return AccountUsageInfo{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	return accountInfo, nil | ||||
| } | ||||
| 
 | ||||
| // AccountStatus - account status. | ||||
| type AccountStatus string | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user