diff --git a/go.mod b/go.mod
index bc684cbf68..2cbd12f5ff 100644
--- a/go.mod
+++ b/go.mod
@@ -18,7 +18,7 @@ require (
github.com/json-iterator/go v1.1.9
github.com/minio/cli v1.22.0
github.com/minio/mc v0.0.0-20200415193718-68b638f2f96c
- github.com/minio/minio v0.0.0-20200428222040-c3c3e9087bc1
+ github.com/minio/minio v0.0.0-20200501193630-d1c8e9f31ba0
github.com/minio/minio-go/v6 v6.0.55-0.20200424204115-7506d2996b22
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/satori/go.uuid v1.2.0
diff --git a/go.sum b/go.sum
index b7d4677ca2..96d519812d 100644
--- a/go.sum
+++ b/go.sum
@@ -30,7 +30,6 @@ github.com/alecthomas/participle v0.2.1 h1:4AVLj1viSGa4LG5HDXKXrm5xRx19SB/rS/skP
github.com/alecthomas/participle v0.2.1/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 h1:nWDRPCyCltiTsANwC/n3QZH7Vww33Npq9MKqlwRzI/c=
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -42,7 +41,6 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/aws/aws-sdk-go v1.20.21/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
-github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2 h1:M+TYzBcNIRyzPRg66ndEqUMd7oWDmhvdQmaPC6EZNwM=
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2/go.mod h1:RDu/qcrnpEdJC/p8tx34+YBFqqX71lB7dOX9QE+ZC4M=
@@ -403,10 +401,9 @@ github.com/minio/lsync v1.0.1 h1:AVvILxA976xc27hstd1oR+X9PQG0sPSom1MNb1ImfUs=
github.com/minio/lsync v1.0.1/go.mod h1:tCFzfo0dlvdGl70IT4IAK/5Wtgb0/BrTmo/jE8pArKA=
github.com/minio/mc v0.0.0-20200415193718-68b638f2f96c h1:JLr0fYpCleodj9nGB5hfsJU2zPdnNQKqa2bYsIvPhVw=
github.com/minio/mc v0.0.0-20200415193718-68b638f2f96c/go.mod h1:l9PuOY62zT7AQJqopDjfo/T22AIBJSb2yXPVZf4RlhM=
-github.com/minio/minio v0.0.0-20200415191640-bde0f444dbab h1:9hlqghJl3e3HorXa6ADWsz6ECq790t4iQs07VD9JctM=
github.com/minio/minio v0.0.0-20200415191640-bde0f444dbab/go.mod h1:v8oQPMMaTkjDwp5cOz1WCElA4Ik+X+0y4On+VMk0fis=
-github.com/minio/minio v0.0.0-20200428222040-c3c3e9087bc1 h1:DQjH/653WCerOeZCp3BxAgkmRiQybHYiprbTFs+brgA=
-github.com/minio/minio v0.0.0-20200428222040-c3c3e9087bc1/go.mod h1:HxnN5FYGIii8ZH6d+LH5UNOSSIonbJkYPqP6gWelVO0=
+github.com/minio/minio v0.0.0-20200501193630-d1c8e9f31ba0 h1:QxIz36O01LbKqJiz6HKeKCOC2afgydspkpahQ807msY=
+github.com/minio/minio v0.0.0-20200501193630-d1c8e9f31ba0/go.mod h1:Vhlqz7Se0EgpgFiVxpvzF4Zz/h2LMx+EPKH96Aera5U=
github.com/minio/minio-go/v6 v6.0.53 h1:8jzpwiOzZ5Iz7/goFWqNZRICbyWYShbb5rARjrnSCNI=
github.com/minio/minio-go/v6 v6.0.53/go.mod h1:DIvC/IApeHX8q1BAMVCXSXwpmrmM+I+iBvhvztQorfI=
github.com/minio/minio-go/v6 v6.0.55-0.20200424204115-7506d2996b22 h1:nZEve4vdUhwHBoV18zRvPDgjL6NYyDJE5QJvz3l9bRs=
@@ -555,6 +552,7 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRN
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -596,6 +594,7 @@ github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -626,6 +625,7 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f h1:kz4KIr+xcPUsI3VMoqWfPMvtnJ6MGfiVwsWSVzphMO4=
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 h1:Sy5bstxEqwwbYs6n0/pBuxKENqOeZUgD45Gp3Q3pqLg=
@@ -635,6 +635,8 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -665,6 +667,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -713,7 +717,13 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190914235951-31e00f45c22e h1:nOOVVcLC+/3MeovP40q5lCiWmP1Z1DaN8yn8ngU63hw=
golang.org/x/tools v0.0.0-20190914235951-31e00f45c22e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200428211428-0c9eba77bc32 h1:Xvf3ZQTm5bjXPxhI7g+dwqsCqadK1rcNtwtszuatetk=
+golang.org/x/tools v0.0.0-20200428211428-0c9eba77bc32/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.5.0 h1:lj9SyhMzyoa38fgFF0oO2T6pjs5IzkLPKfVtxpyCRMM=
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
diff --git a/models/service_account.go b/models/service_account_request.go
similarity index 77%
rename from models/service_account.go
rename to models/service_account_request.go
index 25ef80c891..a8ca885f4c 100644
--- a/models/service_account.go
+++ b/models/service_account_request.go
@@ -27,22 +27,22 @@ import (
"github.com/go-openapi/swag"
)
-// ServiceAccount service account
+// ServiceAccountRequest service account request
//
-// swagger:model serviceAccount
-type ServiceAccount struct {
+// swagger:model serviceAccountRequest
+type ServiceAccountRequest struct {
// policy to be applied to the Service Account if any
Policy string `json:"policy,omitempty"`
}
-// Validate validates this service account
-func (m *ServiceAccount) Validate(formats strfmt.Registry) error {
+// Validate validates this service account request
+func (m *ServiceAccountRequest) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
-func (m *ServiceAccount) MarshalBinary() ([]byte, error) {
+func (m *ServiceAccountRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
@@ -50,8 +50,8 @@ func (m *ServiceAccount) MarshalBinary() ([]byte, error) {
}
// UnmarshalBinary interface implementation
-func (m *ServiceAccount) UnmarshalBinary(b []byte) error {
- var res ServiceAccount
+func (m *ServiceAccountRequest) UnmarshalBinary(b []byte) error {
+ var res ServiceAccountRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
diff --git a/models/service_accounts.go b/models/service_accounts.go
new file mode 100644
index 0000000000..ed282fafcd
--- /dev/null
+++ b/models/service_accounts.go
@@ -0,0 +1,37 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package models
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "github.com/go-openapi/strfmt"
+)
+
+// ServiceAccounts service accounts
+//
+// swagger:model serviceAccounts
+type ServiceAccounts []string
+
+// Validate validates this service accounts
+func (m ServiceAccounts) Validate(formats strfmt.Registry) error {
+ return nil
+}
diff --git a/restapi/admin_info.go b/restapi/admin_info.go
index 952aa938c4..d030dfc67f 100644
--- a/restapi/admin_info.go
+++ b/restapi/admin_info.go
@@ -41,21 +41,21 @@ func registerAdminInfoHandlers(api *operations.McsAPI) {
}
-type UsageInfo struct {
+type usageInfo struct {
Buckets int64
Objects int64
Usage int64
}
-// getAdminInfo invokes admin info and returns a parsed `UsageInfo` structure
-func getAdminInfo(ctx context.Context, client MinioAdmin) (*UsageInfo, error) {
+// getAdminInfo invokes admin info and returns a parsed `usageInfo` structure
+func getAdminInfo(ctx context.Context, client MinioAdmin) (*usageInfo, error) {
serverInfo, err := client.serverInfo(ctx)
if err != nil {
return nil, err
}
// we are trimming uint64 to int64 this will report an incorrect measurement for numbers greater than
// 9,223,372,036,854,775,807
- return &UsageInfo{
+ return &usageInfo{
Buckets: int64(serverInfo.Buckets.Count),
Objects: int64(serverInfo.Objects.Count),
Usage: int64(serverInfo.Usage.Size),
diff --git a/restapi/client-admin.go b/restapi/client-admin.go
index 54ed2ed2a7..81ccef5b6e 100644
--- a/restapi/client-admin.go
+++ b/restapi/client-admin.go
@@ -83,6 +83,8 @@ type MinioAdmin interface {
serviceTrace(ctx context.Context, allTrace, errTrace bool) <-chan madmin.ServiceTraceInfo
// Service Accounts
addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (mauth.Credentials, error)
+ listServiceAccounts(ctx context.Context) (madmin.ListServiceAccountsResp, error)
+ deleteServiceAccount(ctx context.Context, serviceAccount string) error
}
// Interface implementation
@@ -208,11 +210,30 @@ func (ac adminClient) addServiceAccount(ctx context.Context, policy *iampolicy.P
return ac.client.AddServiceAccount(ctx, policy)
}
+// implements madmin.ListServiceAccounts()
+func (ac adminClient) listServiceAccounts(ctx context.Context) (madmin.ListServiceAccountsResp, error) {
+ return ac.client.ListServiceAccounts(ctx)
+}
+
+// implements madmin.DeleteServiceAccount()
+func (ac adminClient) deleteServiceAccount(ctx context.Context, serviceAccount string) error {
+ return ac.client.DeleteServiceAccount(ctx, serviceAccount)
+}
+
func newMAdminClient(jwt string) (*madmin.AdminClient, error) {
claims, err := auth.JWTAuthenticate(jwt)
if err != nil {
return nil, err
}
+ adminClient, err := newAdminFromClaims(claims)
+ if err != nil {
+ return nil, err
+ }
+ return adminClient, nil
+}
+
+// newAdminFromClaims creates a minio admin from Decrypted claims using Assume role credentials
+func newAdminFromClaims(claims *auth.DecryptedClaims) (*madmin.AdminClient, error) {
adminClient, err := madmin.NewWithOptions(getMinIOEndpoint(), &madmin.Options{
Creds: credentials.NewStaticV4(claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken),
Secure: getMinIOEndpointIsSecure(),
diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go
index 1dacc48a34..1394c24ab2 100644
--- a/restapi/embedded_spec.go
+++ b/restapi/embedded_spec.go
@@ -993,6 +993,41 @@ func init() {
}
},
"/service-accounts": {
+ "get": {
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "List User's Service Accounts",
+ "operationId": "ListUserServiceAccounts",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int32",
+ "name": "offset",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int32",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/serviceAccounts"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ },
"post": {
"tags": [
"UserAPI"
@@ -1005,7 +1040,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
- "$ref": "#/definitions/serviceAccount"
+ "$ref": "#/definitions/serviceAccountRequest"
}
}
],
@@ -1025,6 +1060,34 @@ func init() {
}
}
},
+ "/service-accounts/{access_key}": {
+ "delete": {
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Delete Service Account",
+ "operationId": "DeleteServiceAccount",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "access_key",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "A successful response."
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/service/restart": {
"post": {
"tags": [
@@ -1883,15 +1946,6 @@ func init() {
}
}
},
- "serviceAccount": {
- "type": "object",
- "properties": {
- "policy": {
- "type": "string",
- "title": "policy to be applied to the Service Account if any"
- }
- }
- },
"serviceAccountCreds": {
"type": "object",
"properties": {
@@ -1903,6 +1957,21 @@ func init() {
}
}
},
+ "serviceAccountRequest": {
+ "type": "object",
+ "properties": {
+ "policy": {
+ "type": "string",
+ "title": "policy to be applied to the Service Account if any"
+ }
+ }
+ },
+ "serviceAccounts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"sessionResponse": {
"type": "object",
"properties": {
@@ -3033,6 +3102,41 @@ func init() {
}
},
"/service-accounts": {
+ "get": {
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "List User's Service Accounts",
+ "operationId": "ListUserServiceAccounts",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int32",
+ "name": "offset",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int32",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/serviceAccounts"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ },
"post": {
"tags": [
"UserAPI"
@@ -3045,7 +3149,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
- "$ref": "#/definitions/serviceAccount"
+ "$ref": "#/definitions/serviceAccountRequest"
}
}
],
@@ -3065,6 +3169,34 @@ func init() {
}
}
},
+ "/service-accounts/{access_key}": {
+ "delete": {
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Delete Service Account",
+ "operationId": "DeleteServiceAccount",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "access_key",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "A successful response."
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/service/restart": {
"post": {
"tags": [
@@ -3923,15 +4055,6 @@ func init() {
}
}
},
- "serviceAccount": {
- "type": "object",
- "properties": {
- "policy": {
- "type": "string",
- "title": "policy to be applied to the Service Account if any"
- }
- }
- },
"serviceAccountCreds": {
"type": "object",
"properties": {
@@ -3943,6 +4066,21 @@ func init() {
}
}
},
+ "serviceAccountRequest": {
+ "type": "object",
+ "properties": {
+ "policy": {
+ "type": "string",
+ "title": "policy to be applied to the Service Account if any"
+ }
+ }
+ },
+ "serviceAccounts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"sessionResponse": {
"type": "object",
"properties": {
diff --git a/restapi/operations/mcs_api.go b/restapi/operations/mcs_api.go
index d60e825156..c57c0ae649 100644
--- a/restapi/operations/mcs_api.go
+++ b/restapi/operations/mcs_api.go
@@ -105,6 +105,9 @@ func NewMcsAPI(spec *loads.Document) *McsAPI {
UserAPIDeleteBucketEventHandler: user_api.DeleteBucketEventHandlerFunc(func(params user_api.DeleteBucketEventParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.DeleteBucketEvent has not yet been implemented")
}),
+ UserAPIDeleteServiceAccountHandler: user_api.DeleteServiceAccountHandlerFunc(func(params user_api.DeleteServiceAccountParams, principal *models.Principal) middleware.Responder {
+ return middleware.NotImplemented("operation user_api.DeleteServiceAccount has not yet been implemented")
+ }),
AdminAPIGetUserInfoHandler: admin_api.GetUserInfoHandlerFunc(func(params admin_api.GetUserInfoParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.GetUserInfo has not yet been implemented")
}),
@@ -126,6 +129,9 @@ func NewMcsAPI(spec *loads.Document) *McsAPI {
AdminAPIListPoliciesHandler: admin_api.ListPoliciesHandlerFunc(func(params admin_api.ListPoliciesParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ListPolicies has not yet been implemented")
}),
+ UserAPIListUserServiceAccountsHandler: user_api.ListUserServiceAccountsHandlerFunc(func(params user_api.ListUserServiceAccountsParams, principal *models.Principal) middleware.Responder {
+ return middleware.NotImplemented("operation user_api.ListUserServiceAccounts has not yet been implemented")
+ }),
AdminAPIListUsersHandler: admin_api.ListUsersHandlerFunc(func(params admin_api.ListUsersParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ListUsers has not yet been implemented")
}),
@@ -263,6 +269,8 @@ type McsAPI struct {
UserAPIDeleteBucketHandler user_api.DeleteBucketHandler
// UserAPIDeleteBucketEventHandler sets the operation handler for the delete bucket event operation
UserAPIDeleteBucketEventHandler user_api.DeleteBucketEventHandler
+ // UserAPIDeleteServiceAccountHandler sets the operation handler for the delete service account operation
+ UserAPIDeleteServiceAccountHandler user_api.DeleteServiceAccountHandler
// AdminAPIGetUserInfoHandler sets the operation handler for the get user info operation
AdminAPIGetUserInfoHandler admin_api.GetUserInfoHandler
// AdminAPIGroupInfoHandler sets the operation handler for the group info operation
@@ -277,6 +285,8 @@ type McsAPI struct {
AdminAPIListGroupsHandler admin_api.ListGroupsHandler
// AdminAPIListPoliciesHandler sets the operation handler for the list policies operation
AdminAPIListPoliciesHandler admin_api.ListPoliciesHandler
+ // UserAPIListUserServiceAccountsHandler sets the operation handler for the list user service accounts operation
+ UserAPIListUserServiceAccountsHandler user_api.ListUserServiceAccountsHandler
// AdminAPIListUsersHandler sets the operation handler for the list users operation
AdminAPIListUsersHandler admin_api.ListUsersHandler
// UserAPILoginHandler sets the operation handler for the login operation
@@ -432,6 +442,9 @@ func (o *McsAPI) Validate() error {
if o.UserAPIDeleteBucketEventHandler == nil {
unregistered = append(unregistered, "user_api.DeleteBucketEventHandler")
}
+ if o.UserAPIDeleteServiceAccountHandler == nil {
+ unregistered = append(unregistered, "user_api.DeleteServiceAccountHandler")
+ }
if o.AdminAPIGetUserInfoHandler == nil {
unregistered = append(unregistered, "admin_api.GetUserInfoHandler")
}
@@ -453,6 +466,9 @@ func (o *McsAPI) Validate() error {
if o.AdminAPIListPoliciesHandler == nil {
unregistered = append(unregistered, "admin_api.ListPoliciesHandler")
}
+ if o.UserAPIListUserServiceAccountsHandler == nil {
+ unregistered = append(unregistered, "user_api.ListUserServiceAccountsHandler")
+ }
if o.AdminAPIListUsersHandler == nil {
unregistered = append(unregistered, "admin_api.ListUsersHandler")
}
@@ -669,6 +685,10 @@ func (o *McsAPI) initHandlerCache() {
o.handlers["DELETE"] = make(map[string]http.Handler)
}
o.handlers["DELETE"]["/buckets/{bucket_name}/events/{arn}"] = user_api.NewDeleteBucketEvent(o.context, o.UserAPIDeleteBucketEventHandler)
+ if o.handlers["DELETE"] == nil {
+ o.handlers["DELETE"] = make(map[string]http.Handler)
+ }
+ o.handlers["DELETE"]["/service-accounts/{access_key}"] = user_api.NewDeleteServiceAccount(o.context, o.UserAPIDeleteServiceAccountHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
@@ -700,6 +720,10 @@ func (o *McsAPI) initHandlerCache() {
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
+ o.handlers["GET"]["/service-accounts"] = user_api.NewListUserServiceAccounts(o.context, o.UserAPIListUserServiceAccountsHandler)
+ if o.handlers["GET"] == nil {
+ o.handlers["GET"] = make(map[string]http.Handler)
+ }
o.handlers["GET"]["/users"] = admin_api.NewListUsers(o.context, o.AdminAPIListUsersHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
diff --git a/restapi/operations/user_api/create_service_account_parameters.go b/restapi/operations/user_api/create_service_account_parameters.go
index d082bcb788..67d424fdde 100644
--- a/restapi/operations/user_api/create_service_account_parameters.go
+++ b/restapi/operations/user_api/create_service_account_parameters.go
@@ -53,7 +53,7 @@ type CreateServiceAccountParams struct {
Required: true
In: body
*/
- Body *models.ServiceAccount
+ Body *models.ServiceAccountRequest
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
@@ -67,7 +67,7 @@ func (o *CreateServiceAccountParams) BindRequest(r *http.Request, route *middlew
if runtime.HasBody(r) {
defer r.Body.Close()
- var body models.ServiceAccount
+ var body models.ServiceAccountRequest
if err := route.Consumer.Consume(r.Body, &body); err != nil {
if err == io.EOF {
res = append(res, errors.Required("body", "body"))
diff --git a/restapi/operations/user_api/delete_service_account.go b/restapi/operations/user_api/delete_service_account.go
new file mode 100644
index 0000000000..42227df0b4
--- /dev/null
+++ b/restapi/operations/user_api/delete_service_account.go
@@ -0,0 +1,90 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime/middleware"
+
+ "github.com/minio/mcs/models"
+)
+
+// DeleteServiceAccountHandlerFunc turns a function with the right signature into a delete service account handler
+type DeleteServiceAccountHandlerFunc func(DeleteServiceAccountParams, *models.Principal) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn DeleteServiceAccountHandlerFunc) Handle(params DeleteServiceAccountParams, principal *models.Principal) middleware.Responder {
+ return fn(params, principal)
+}
+
+// DeleteServiceAccountHandler interface for that can handle valid delete service account params
+type DeleteServiceAccountHandler interface {
+ Handle(DeleteServiceAccountParams, *models.Principal) middleware.Responder
+}
+
+// NewDeleteServiceAccount creates a new http.Handler for the delete service account operation
+func NewDeleteServiceAccount(ctx *middleware.Context, handler DeleteServiceAccountHandler) *DeleteServiceAccount {
+ return &DeleteServiceAccount{Context: ctx, Handler: handler}
+}
+
+/*DeleteServiceAccount swagger:route DELETE /service-accounts/{access_key} UserAPI deleteServiceAccount
+
+Delete Service Account
+
+*/
+type DeleteServiceAccount struct {
+ Context *middleware.Context
+ Handler DeleteServiceAccountHandler
+}
+
+func (o *DeleteServiceAccount) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+ var Params = NewDeleteServiceAccountParams()
+
+ uprinc, aCtx, err := o.Context.Authorize(r, route)
+ if err != nil {
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+ if aCtx != nil {
+ r = aCtx
+ }
+ var principal *models.Principal
+ if uprinc != nil {
+ principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
+ }
+
+ if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+
+ res := o.Handler.Handle(Params, principal) // actually handle the request
+
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/restapi/operations/user_api/delete_service_account_parameters.go b/restapi/operations/user_api/delete_service_account_parameters.go
new file mode 100644
index 0000000000..d05cc9368a
--- /dev/null
+++ b/restapi/operations/user_api/delete_service_account_parameters.go
@@ -0,0 +1,89 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/strfmt"
+)
+
+// NewDeleteServiceAccountParams creates a new DeleteServiceAccountParams object
+// no default values defined in spec.
+func NewDeleteServiceAccountParams() DeleteServiceAccountParams {
+
+ return DeleteServiceAccountParams{}
+}
+
+// DeleteServiceAccountParams contains all the bound params for the delete service account operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters DeleteServiceAccount
+type DeleteServiceAccountParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+
+ /*
+ Required: true
+ In: path
+ */
+ AccessKey string
+}
+
+// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
+// for simple values it will use straight method calls.
+//
+// To ensure default values, the struct must have been initialized with NewDeleteServiceAccountParams() beforehand.
+func (o *DeleteServiceAccountParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ rAccessKey, rhkAccessKey, _ := route.Params.GetOK("access_key")
+ if err := o.bindAccessKey(rAccessKey, rhkAccessKey, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+// bindAccessKey binds and validates parameter AccessKey from path.
+func (o *DeleteServiceAccountParams) bindAccessKey(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: true
+ // Parameter is provided by construction from the route
+
+ o.AccessKey = raw
+
+ return nil
+}
diff --git a/restapi/operations/user_api/delete_service_account_responses.go b/restapi/operations/user_api/delete_service_account_responses.go
new file mode 100644
index 0000000000..3049d36e68
--- /dev/null
+++ b/restapi/operations/user_api/delete_service_account_responses.go
@@ -0,0 +1,113 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+
+ "github.com/minio/mcs/models"
+)
+
+// DeleteServiceAccountNoContentCode is the HTTP code returned for type DeleteServiceAccountNoContent
+const DeleteServiceAccountNoContentCode int = 204
+
+/*DeleteServiceAccountNoContent A successful response.
+
+swagger:response deleteServiceAccountNoContent
+*/
+type DeleteServiceAccountNoContent struct {
+}
+
+// NewDeleteServiceAccountNoContent creates DeleteServiceAccountNoContent with default headers values
+func NewDeleteServiceAccountNoContent() *DeleteServiceAccountNoContent {
+
+ return &DeleteServiceAccountNoContent{}
+}
+
+// WriteResponse to the client
+func (o *DeleteServiceAccountNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
+
+ rw.WriteHeader(204)
+}
+
+/*DeleteServiceAccountDefault Generic error response.
+
+swagger:response deleteServiceAccountDefault
+*/
+type DeleteServiceAccountDefault struct {
+ _statusCode int
+
+ /*
+ In: Body
+ */
+ Payload *models.Error `json:"body,omitempty"`
+}
+
+// NewDeleteServiceAccountDefault creates DeleteServiceAccountDefault with default headers values
+func NewDeleteServiceAccountDefault(code int) *DeleteServiceAccountDefault {
+ if code <= 0 {
+ code = 500
+ }
+
+ return &DeleteServiceAccountDefault{
+ _statusCode: code,
+ }
+}
+
+// WithStatusCode adds the status to the delete service account default response
+func (o *DeleteServiceAccountDefault) WithStatusCode(code int) *DeleteServiceAccountDefault {
+ o._statusCode = code
+ return o
+}
+
+// SetStatusCode sets the status to the delete service account default response
+func (o *DeleteServiceAccountDefault) SetStatusCode(code int) {
+ o._statusCode = code
+}
+
+// WithPayload adds the payload to the delete service account default response
+func (o *DeleteServiceAccountDefault) WithPayload(payload *models.Error) *DeleteServiceAccountDefault {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the delete service account default response
+func (o *DeleteServiceAccountDefault) SetPayload(payload *models.Error) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DeleteServiceAccountDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(o._statusCode)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/restapi/operations/user_api/delete_service_account_urlbuilder.go b/restapi/operations/user_api/delete_service_account_urlbuilder.go
new file mode 100644
index 0000000000..a112d60609
--- /dev/null
+++ b/restapi/operations/user_api/delete_service_account_urlbuilder.go
@@ -0,0 +1,116 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "errors"
+ "net/url"
+ golangswaggerpaths "path"
+ "strings"
+)
+
+// DeleteServiceAccountURL generates an URL for the delete service account operation
+type DeleteServiceAccountURL struct {
+ AccessKey string
+
+ _basePath string
+ // avoid unkeyed usage
+ _ struct{}
+}
+
+// WithBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *DeleteServiceAccountURL) WithBasePath(bp string) *DeleteServiceAccountURL {
+ o.SetBasePath(bp)
+ return o
+}
+
+// SetBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *DeleteServiceAccountURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *DeleteServiceAccountURL) Build() (*url.URL, error) {
+ var _result url.URL
+
+ var _path = "/service-accounts/{access_key}"
+
+ accessKey := o.AccessKey
+ if accessKey != "" {
+ _path = strings.Replace(_path, "{access_key}", accessKey, -1)
+ } else {
+ return nil, errors.New("accessKey is required on DeleteServiceAccountURL")
+ }
+
+ _basePath := o._basePath
+ if _basePath == "" {
+ _basePath = "/api/v1"
+ }
+ _result.Path = golangswaggerpaths.Join(_basePath, _path)
+
+ return &_result, nil
+}
+
+// Must is a helper function to panic when the url builder returns an error
+func (o *DeleteServiceAccountURL) Must(u *url.URL, err error) *url.URL {
+ if err != nil {
+ panic(err)
+ }
+ if u == nil {
+ panic("url can't be nil")
+ }
+ return u
+}
+
+// String returns the string representation of the path with query string
+func (o *DeleteServiceAccountURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *DeleteServiceAccountURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on DeleteServiceAccountURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on DeleteServiceAccountURL")
+ }
+
+ base, err := o.Build()
+ if err != nil {
+ return nil, err
+ }
+
+ base.Scheme = scheme
+ base.Host = host
+ return base, nil
+}
+
+// StringFull returns the string representation of a complete url
+func (o *DeleteServiceAccountURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/restapi/operations/user_api/list_user_service_accounts.go b/restapi/operations/user_api/list_user_service_accounts.go
new file mode 100644
index 0000000000..7d86709a7c
--- /dev/null
+++ b/restapi/operations/user_api/list_user_service_accounts.go
@@ -0,0 +1,90 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime/middleware"
+
+ "github.com/minio/mcs/models"
+)
+
+// ListUserServiceAccountsHandlerFunc turns a function with the right signature into a list user service accounts handler
+type ListUserServiceAccountsHandlerFunc func(ListUserServiceAccountsParams, *models.Principal) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn ListUserServiceAccountsHandlerFunc) Handle(params ListUserServiceAccountsParams, principal *models.Principal) middleware.Responder {
+ return fn(params, principal)
+}
+
+// ListUserServiceAccountsHandler interface for that can handle valid list user service accounts params
+type ListUserServiceAccountsHandler interface {
+ Handle(ListUserServiceAccountsParams, *models.Principal) middleware.Responder
+}
+
+// NewListUserServiceAccounts creates a new http.Handler for the list user service accounts operation
+func NewListUserServiceAccounts(ctx *middleware.Context, handler ListUserServiceAccountsHandler) *ListUserServiceAccounts {
+ return &ListUserServiceAccounts{Context: ctx, Handler: handler}
+}
+
+/*ListUserServiceAccounts swagger:route GET /service-accounts UserAPI listUserServiceAccounts
+
+List User's Service Accounts
+
+*/
+type ListUserServiceAccounts struct {
+ Context *middleware.Context
+ Handler ListUserServiceAccountsHandler
+}
+
+func (o *ListUserServiceAccounts) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+ var Params = NewListUserServiceAccountsParams()
+
+ uprinc, aCtx, err := o.Context.Authorize(r, route)
+ if err != nil {
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+ if aCtx != nil {
+ r = aCtx
+ }
+ var principal *models.Principal
+ if uprinc != nil {
+ principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
+ }
+
+ if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+
+ res := o.Handler.Handle(Params, principal) // actually handle the request
+
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/restapi/operations/user_api/list_user_service_accounts_parameters.go b/restapi/operations/user_api/list_user_service_accounts_parameters.go
new file mode 100644
index 0000000000..d930490928
--- /dev/null
+++ b/restapi/operations/user_api/list_user_service_accounts_parameters.go
@@ -0,0 +1,130 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag"
+)
+
+// NewListUserServiceAccountsParams creates a new ListUserServiceAccountsParams object
+// no default values defined in spec.
+func NewListUserServiceAccountsParams() ListUserServiceAccountsParams {
+
+ return ListUserServiceAccountsParams{}
+}
+
+// ListUserServiceAccountsParams contains all the bound params for the list user service accounts operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters ListUserServiceAccounts
+type ListUserServiceAccountsParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+
+ /*
+ In: query
+ */
+ Limit *int32
+ /*
+ In: query
+ */
+ Offset *int32
+}
+
+// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
+// for simple values it will use straight method calls.
+//
+// To ensure default values, the struct must have been initialized with NewListUserServiceAccountsParams() beforehand.
+func (o *ListUserServiceAccountsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ qs := runtime.Values(r.URL.Query())
+
+ qLimit, qhkLimit, _ := qs.GetOK("limit")
+ if err := o.bindLimit(qLimit, qhkLimit, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ qOffset, qhkOffset, _ := qs.GetOK("offset")
+ if err := o.bindOffset(qOffset, qhkOffset, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+// bindLimit binds and validates parameter Limit from query.
+func (o *ListUserServiceAccountsParams) bindLimit(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: false
+ // AllowEmptyValue: false
+ if raw == "" { // empty values pass all other validations
+ return nil
+ }
+
+ value, err := swag.ConvertInt32(raw)
+ if err != nil {
+ return errors.InvalidType("limit", "query", "int32", raw)
+ }
+ o.Limit = &value
+
+ return nil
+}
+
+// bindOffset binds and validates parameter Offset from query.
+func (o *ListUserServiceAccountsParams) bindOffset(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: false
+ // AllowEmptyValue: false
+ if raw == "" { // empty values pass all other validations
+ return nil
+ }
+
+ value, err := swag.ConvertInt32(raw)
+ if err != nil {
+ return errors.InvalidType("offset", "query", "int32", raw)
+ }
+ o.Offset = &value
+
+ return nil
+}
diff --git a/restapi/operations/user_api/list_user_service_accounts_responses.go b/restapi/operations/user_api/list_user_service_accounts_responses.go
new file mode 100644
index 0000000000..8e2b8ebd35
--- /dev/null
+++ b/restapi/operations/user_api/list_user_service_accounts_responses.go
@@ -0,0 +1,136 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+
+ "github.com/minio/mcs/models"
+)
+
+// ListUserServiceAccountsOKCode is the HTTP code returned for type ListUserServiceAccountsOK
+const ListUserServiceAccountsOKCode int = 200
+
+/*ListUserServiceAccountsOK A successful response.
+
+swagger:response listUserServiceAccountsOK
+*/
+type ListUserServiceAccountsOK struct {
+
+ /*
+ In: Body
+ */
+ Payload models.ServiceAccounts `json:"body,omitempty"`
+}
+
+// NewListUserServiceAccountsOK creates ListUserServiceAccountsOK with default headers values
+func NewListUserServiceAccountsOK() *ListUserServiceAccountsOK {
+
+ return &ListUserServiceAccountsOK{}
+}
+
+// WithPayload adds the payload to the list user service accounts o k response
+func (o *ListUserServiceAccountsOK) WithPayload(payload models.ServiceAccounts) *ListUserServiceAccountsOK {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list user service accounts o k response
+func (o *ListUserServiceAccountsOK) SetPayload(payload models.ServiceAccounts) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListUserServiceAccountsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(200)
+ payload := o.Payload
+ if payload == nil {
+ // return empty array
+ payload = models.ServiceAccounts{}
+ }
+
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+}
+
+/*ListUserServiceAccountsDefault Generic error response.
+
+swagger:response listUserServiceAccountsDefault
+*/
+type ListUserServiceAccountsDefault struct {
+ _statusCode int
+
+ /*
+ In: Body
+ */
+ Payload *models.Error `json:"body,omitempty"`
+}
+
+// NewListUserServiceAccountsDefault creates ListUserServiceAccountsDefault with default headers values
+func NewListUserServiceAccountsDefault(code int) *ListUserServiceAccountsDefault {
+ if code <= 0 {
+ code = 500
+ }
+
+ return &ListUserServiceAccountsDefault{
+ _statusCode: code,
+ }
+}
+
+// WithStatusCode adds the status to the list user service accounts default response
+func (o *ListUserServiceAccountsDefault) WithStatusCode(code int) *ListUserServiceAccountsDefault {
+ o._statusCode = code
+ return o
+}
+
+// SetStatusCode sets the status to the list user service accounts default response
+func (o *ListUserServiceAccountsDefault) SetStatusCode(code int) {
+ o._statusCode = code
+}
+
+// WithPayload adds the payload to the list user service accounts default response
+func (o *ListUserServiceAccountsDefault) WithPayload(payload *models.Error) *ListUserServiceAccountsDefault {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list user service accounts default response
+func (o *ListUserServiceAccountsDefault) SetPayload(payload *models.Error) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListUserServiceAccountsDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(o._statusCode)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/restapi/operations/user_api/list_user_service_accounts_urlbuilder.go b/restapi/operations/user_api/list_user_service_accounts_urlbuilder.go
new file mode 100644
index 0000000000..0ca2063729
--- /dev/null
+++ b/restapi/operations/user_api/list_user_service_accounts_urlbuilder.go
@@ -0,0 +1,131 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "errors"
+ "net/url"
+ golangswaggerpaths "path"
+
+ "github.com/go-openapi/swag"
+)
+
+// ListUserServiceAccountsURL generates an URL for the list user service accounts operation
+type ListUserServiceAccountsURL struct {
+ Limit *int32
+ Offset *int32
+
+ _basePath string
+ // avoid unkeyed usage
+ _ struct{}
+}
+
+// WithBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *ListUserServiceAccountsURL) WithBasePath(bp string) *ListUserServiceAccountsURL {
+ o.SetBasePath(bp)
+ return o
+}
+
+// SetBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *ListUserServiceAccountsURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *ListUserServiceAccountsURL) Build() (*url.URL, error) {
+ var _result url.URL
+
+ var _path = "/service-accounts"
+
+ _basePath := o._basePath
+ if _basePath == "" {
+ _basePath = "/api/v1"
+ }
+ _result.Path = golangswaggerpaths.Join(_basePath, _path)
+
+ qs := make(url.Values)
+
+ var limitQ string
+ if o.Limit != nil {
+ limitQ = swag.FormatInt32(*o.Limit)
+ }
+ if limitQ != "" {
+ qs.Set("limit", limitQ)
+ }
+
+ var offsetQ string
+ if o.Offset != nil {
+ offsetQ = swag.FormatInt32(*o.Offset)
+ }
+ if offsetQ != "" {
+ qs.Set("offset", offsetQ)
+ }
+
+ _result.RawQuery = qs.Encode()
+
+ return &_result, nil
+}
+
+// Must is a helper function to panic when the url builder returns an error
+func (o *ListUserServiceAccountsURL) Must(u *url.URL, err error) *url.URL {
+ if err != nil {
+ panic(err)
+ }
+ if u == nil {
+ panic("url can't be nil")
+ }
+ return u
+}
+
+// String returns the string representation of the path with query string
+func (o *ListUserServiceAccountsURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *ListUserServiceAccountsURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on ListUserServiceAccountsURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on ListUserServiceAccountsURL")
+ }
+
+ base, err := o.Build()
+ if err != nil {
+ return nil, err
+ }
+
+ base.Scheme = scheme
+ base.Host = host
+ return base, nil
+}
+
+// StringFull returns the string representation of a complete url
+func (o *ListUserServiceAccountsURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/restapi/user_service_accounts.go b/restapi/user_service_accounts.go
index 3dba3016fa..0122fa4f53 100644
--- a/restapi/user_service_accounts.go
+++ b/restapi/user_service_accounts.go
@@ -41,6 +41,24 @@ func registerServiceAccountsHandlers(api *operations.McsAPI) {
}
return user_api.NewCreateServiceAccountCreated().WithPayload(creds)
})
+ // List Service Accounts for User
+ api.UserAPIListUserServiceAccountsHandler = user_api.ListUserServiceAccountsHandlerFunc(func(params user_api.ListUserServiceAccountsParams, principal *models.Principal) middleware.Responder {
+ sessionID := string(*principal)
+ serviceAccounts, err := getUserServiceAccountsResponse(sessionID)
+ if err != nil {
+ return user_api.NewListUserServiceAccountsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
+ }
+ return user_api.NewListUserServiceAccountsOK().WithPayload(serviceAccounts)
+ })
+
+ // Delete a User's service account
+ api.UserAPIDeleteServiceAccountHandler = user_api.DeleteServiceAccountHandlerFunc(func(params user_api.DeleteServiceAccountParams, principal *models.Principal) middleware.Responder {
+ sessionID := string(*principal)
+ if err := getDeleteServiceAccountResponse(sessionID, params.AccessKey); err != nil {
+ return user_api.NewDeleteServiceAccountDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
+ }
+ return user_api.NewDeleteServiceAccountNoContent()
+ })
}
// createServiceAccount adds a service account to the userClient and assigns a policy to him if defined.
@@ -64,7 +82,7 @@ func createServiceAccount(ctx context.Context, userClient MinioAdmin, policy str
// getCreateServiceAccountResponse creates a service account with the defined policy for the user that
// is requestingit ,it first gets the credentials of the user and creates a client which is going to
// make the call to create the Service Account
-func getCreateServiceAccountResponse(userSessionID string, serviceAccount *models.ServiceAccount) (*models.ServiceAccountCreds, error) {
+func getCreateServiceAccountResponse(userSessionID string, serviceAccount *models.ServiceAccountRequest) (*models.ServiceAccountCreds, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
@@ -84,3 +102,66 @@ func getCreateServiceAccountResponse(userSessionID string, serviceAccount *model
}
return saCreds, nil
}
+
+// getUserServiceAccount gets list of the user's service accounts
+func getUserServiceAccounts(ctx context.Context, userClient MinioAdmin) (models.ServiceAccounts, error) {
+ listServAccs, err := userClient.listServiceAccounts(ctx)
+ if err != nil {
+ return nil, err
+ }
+ serviceAccounts := models.ServiceAccounts{}
+ for _, acc := range listServAccs.Accounts {
+ serviceAccounts = append(serviceAccounts, acc)
+ }
+ return serviceAccounts, nil
+}
+
+// getUserServiceAccountsResponse authenticates the user and calls
+// getUserServiceAccounts to list the user's service accounts
+func getUserServiceAccountsResponse(userSessionID string) (models.ServiceAccounts, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
+ defer cancel()
+
+ userAdmin, err := newMAdminClient(userSessionID)
+ if err != nil {
+ log.Println("error creating user Client:", err)
+ return nil, err
+ }
+ // create a MinIO user Admin Client interface implementation
+ // defining the client to be used
+ userAdminClient := adminClient{client: userAdmin}
+
+ serviceAccounts, err := getUserServiceAccounts(ctx, userAdminClient)
+ if err != nil {
+ log.Println("error listing user's service account:", err)
+ return nil, err
+ }
+ return serviceAccounts, nil
+
+}
+
+// deleteServiceAccount calls delete service account api
+func deleteServiceAccount(ctx context.Context, userClient MinioAdmin, accessKey string) error {
+ return userClient.deleteServiceAccount(ctx, accessKey)
+}
+
+// getDeleteServiceAccountResponse authenticates the user and calls deleteServiceAccount
+func getDeleteServiceAccountResponse(userSessionID, accessKey string) error {
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
+ defer cancel()
+
+ userAdmin, err := newMAdminClient(userSessionID)
+ if err != nil {
+ log.Println("error creating user Client:", err)
+ return err
+ }
+ // create a MinIO user Admin Client interface implementation
+ // defining the client to be used
+ userAdminClient := adminClient{client: userAdmin}
+
+ if err := deleteServiceAccount(ctx, userAdminClient, accessKey); err != nil {
+ log.Println("error deleting user's service account:", err)
+ return err
+ }
+ return nil
+}
diff --git a/restapi/user_service_accounts_test.go b/restapi/user_service_accounts_test.go
index 6755b0c2ed..23bd62193f 100644
--- a/restapi/user_service_accounts_test.go
+++ b/restapi/user_service_accounts_test.go
@@ -25,17 +25,30 @@ import (
"github.com/minio/minio/pkg/auth"
iampolicy "github.com/minio/minio/pkg/iam/policy"
+ "github.com/minio/minio/pkg/madmin"
"github.com/stretchr/testify/assert"
)
// assigning mock at runtime instead of compile time
var minioAddServiceAccountMock func(ctx context.Context, policy *iampolicy.Policy) (auth.Credentials, error)
+var minioListServiceAccountsMock func(ctx context.Context) (madmin.ListServiceAccountsResp, error)
+var minioDeleteServiceAccountMock func(ctx context.Context, serviceAccount string) error
-// mock function of listUsers()
+// mock function of AddServiceAccount()
func (ac adminClientMock) addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (auth.Credentials, error) {
return minioAddServiceAccountMock(ctx, policy)
}
+// mock function of ListServiceAccounts()
+func (ac adminClientMock) listServiceAccounts(ctx context.Context) (madmin.ListServiceAccountsResp, error) {
+ return minioListServiceAccountsMock(ctx)
+}
+
+// mock function of DeleteServiceAccount()
+func (ac adminClientMock) deleteServiceAccount(ctx context.Context, serviceAccount string) error {
+ return minioDeleteServiceAccountMock(ctx, serviceAccount)
+}
+
func TestAddServiceAccount(t *testing.T) {
assert := assert.New(t)
// mock minIO client
@@ -84,3 +97,61 @@ func TestAddServiceAccount(t *testing.T) {
assert.Equal("error", err.Error())
}
}
+
+func TestListServiceAccounts(t *testing.T) {
+ assert := assert.New(t)
+ // mock minIO client
+ client := adminClientMock{}
+ function := "getUserServiceAccounts()"
+
+ // Test-1: getUserServiceAccounts list serviceaccounts for a user
+ ctx := context.Background()
+ mockResponse := madmin.ListServiceAccountsResp{
+ Accounts: []string{"accesskey1", "accesskey2"},
+ }
+ minioListServiceAccountsMock = func(ctx context.Context) (madmin.ListServiceAccountsResp, error) {
+ return mockResponse, nil
+ }
+ serviceAccounts, err := getUserServiceAccounts(ctx, client)
+ if err != nil {
+ t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
+ }
+ for i, sa := range serviceAccounts {
+ assert.Equal(mockResponse.Accounts[i], sa)
+ }
+
+ // Test-2: getUserServiceAccounts returns an error, handle it properly
+ minioListServiceAccountsMock = func(ctx context.Context) (madmin.ListServiceAccountsResp, error) {
+ return madmin.ListServiceAccountsResp{}, errors.New("error")
+ }
+ _, err = getUserServiceAccounts(ctx, client)
+ if assert.Error(err) {
+ assert.Equal("error", err.Error())
+ }
+}
+
+func TestDeleteServiceAccount(t *testing.T) {
+ assert := assert.New(t)
+ // mock minIO client
+ client := adminClientMock{}
+ function := "deleteServiceAccount()"
+ ctx := context.Background()
+
+ // Test-1: deleteServiceAccount receive a service account to delete
+ testServiceAccount := "accesskeytest"
+ minioDeleteServiceAccountMock = func(ctx context.Context, serviceAccount string) error {
+ return nil
+ }
+ if err := deleteServiceAccount(ctx, client, testServiceAccount); err != nil {
+ t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
+ }
+
+ // Test-2: if an invalid policy is assigned to the service account, this will raise an error
+ minioDeleteServiceAccountMock = func(ctx context.Context, serviceAccount string) error {
+ return errors.New("error")
+ }
+
+ if err := deleteServiceAccount(ctx, client, testServiceAccount); assert.Error(err) {
+ assert.Equal("error", err.Error())
+ }
+}
diff --git a/swagger.yml b/swagger.yml
index 4d28a79249..0081d27231 100644
--- a/swagger.yml
+++ b/swagger.yml
@@ -309,6 +309,31 @@ paths:
- UserAPI
/service-accounts:
+ get:
+ summary: List User's Service Accounts
+ operationId: ListUserServiceAccounts
+ parameters:
+ - name: offset
+ in: query
+ required: false
+ type: integer
+ format: int32
+ - name: limit
+ in: query
+ required: false
+ type: integer
+ format: int32
+ responses:
+ 200:
+ description: A successful response.
+ schema:
+ $ref: "#/definitions/serviceAccounts"
+ default:
+ description: Generic error response.
+ schema:
+ $ref: "#/definitions/error"
+ tags:
+ - UserAPI
post:
summary: Create Service Account
operationId: CreateServiceAccount
@@ -317,7 +342,7 @@ paths:
in: body
required: true
schema:
- $ref: '#/definitions/serviceAccount'
+ $ref: '#/definitions/serviceAccountRequest'
responses:
201:
description: A successful response.
@@ -329,6 +354,25 @@ paths:
$ref: "#/definitions/error"
tags:
- UserAPI
+
+ /service-accounts/{access_key}:
+ delete:
+ summary: Delete Service Account
+ operationId: DeleteServiceAccount
+ parameters:
+ - name: access_key
+ in: path
+ required: true
+ type: string
+ responses:
+ 204:
+ description: A successful response.
+ default:
+ description: Generic error response.
+ schema:
+ $ref: "#/definitions/error"
+ tags:
+ - UserAPI
/users:
get:
@@ -1367,7 +1411,11 @@ definitions:
type: array
items:
type: string
- serviceAccount:
+ serviceAccounts:
+ type: array
+ items:
+ type: string
+ serviceAccountRequest:
type: object
properties:
policy: