adding edit service account api/ui (#1545)

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
This commit is contained in:
adfost
2022-02-10 17:18:57 -08:00
committed by GitHub
parent c6f2ddfd7e
commit 2988de4025
14 changed files with 790 additions and 19 deletions

View File

@@ -50,21 +50,6 @@ func TestAddServiceAccount(t *testing.T) {
requestDataAddServiceAccount := map[string]interface{}{
"accessKey": "testuser1",
"secretKey": "password",
"policy": "{" +
"\n \"Version\": \"2012-10-17\"," +
"\n \"Statement\": [" +
"\n {" +
"\n \"Effect\": \"Allow\"," +
"\n \"Action\": [" +
"\n \"s3:GetBucketLocation\"," +
"\n \"s3:GetObject\"" +
"\n ]," +
"\n \"Resource\": [" +
"\n \"arn:aws:s3:::*\"" +
"\n ]" +
"\n }" +
"\n ]" +
"\n}",
}
fmt.Println("..............................TestServiceAccountPolicy(): Prepare the POST")
@@ -95,7 +80,51 @@ func TestAddServiceAccount(t *testing.T) {
assert.Equal(201, response.StatusCode, "Status Code is incorrect")
}
fmt.Println("...................................TestServiceAccountPolicy(): Remove user")
requestDataPolicy := map[string]interface{}{"policy": "{" +
"\n \"Version\": \"2012-10-17\"," +
"\n \"Statement\": [" +
"\n {" +
"\n \"Effect\": \"Allow\"," +
"\n \"Action\": [" +
"\n \"s3:GetBucketLocation\"," +
"\n \"s3:GetObject\"" +
"\n ]," +
"\n \"Resource\": [" +
"\n \"arn:aws:s3:::*\"" +
"\n ]" +
"\n }" +
"\n ]" +
"\n}",
}
fmt.Println("..............................TestServiceAccountPolicy(): Prepare the PUT")
requestDataJSON, _ = json.Marshal(requestDataPolicy)
requestDataBody = bytes.NewReader(requestDataJSON)
request, err = http.NewRequest(
"PUT", "http://localhost:9090/api/v1/service-accounts/testuser1/policy", requestDataBody)
if err != nil {
log.Println(err)
return
}
request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
request.Header.Add("Content-Type", "application/json")
fmt.Println(".................................TestServiceAccountPolicy(): Make the PUT")
response, err = client.Do(request)
if err != nil {
log.Println(err)
return
}
fmt.Println("..................................TestServiceAccountPolicy(): Verification")
fmt.Println(".................................TestServiceAccountPolicy(): PUT response")
fmt.Println(response)
fmt.Println("....................................TestServiceAccountPolicy(): PUT error")
fmt.Println(err)
if response != nil {
fmt.Println("POST StatusCode:", response.StatusCode)
assert.Equal(200, response.StatusCode, "Status Code is incorrect")
}
fmt.Println("...................................TestServiceAccountPolicy(): Check policy")
// Test policy
fmt.Println(".......................TestAddUserServiceAccount(): Create Data to add user")

View File

@@ -0,0 +1,88 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 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 <http://www.gnu.org/licenses/>.
//
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 (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// AddServiceAccountPolicyRequest add service account policy request
//
// swagger:model addServiceAccountPolicyRequest
type AddServiceAccountPolicyRequest struct {
// policy
// Required: true
Policy *string `json:"policy"`
}
// Validate validates this add service account policy request
func (m *AddServiceAccountPolicyRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validatePolicy(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *AddServiceAccountPolicyRequest) validatePolicy(formats strfmt.Registry) error {
if err := validate.Required("policy", "body", m.Policy); err != nil {
return err
}
return nil
}
// ContextValidate validates this add service account policy request based on context it is used
func (m *AddServiceAccountPolicyRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *AddServiceAccountPolicyRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *AddServiceAccountPolicyRequest) UnmarshalBinary(b []byte) error {
var res AddServiceAccountPolicyRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -179,6 +179,7 @@ const Account = ({ classes, displayErrorMessage }: IServiceAccountsProps) => {
const closePolicyModal = () => {
setPolicyOpen(false);
setLoading(true);
};
const confirmDeleteServiceAccount = (selectedServiceAccount: string) => {

View File

@@ -85,6 +85,18 @@ const ServiceAccountPolicy = ({
}
}, [loading, setLoading, setModalErrorSnackMessage, selectedAccessKey]);
const setPolicy = (event: React.FormEvent, newPolicy: string) => {
event.preventDefault();
api
.invoke("PUT", `/api/v1/service-accounts/${selectedAccessKey}/policy`, {policy: newPolicy})
.then((res) => {
closeModalAndRefresh();
})
.catch((err: ErrorResponseHandler) => {
setModalErrorSnackMessage(err);
});
};
return (
<ModalWrapper
title="Service Account Policy"
@@ -94,6 +106,13 @@ const ServiceAccountPolicy = ({
}}
titleIcon={<ChangeAccessPolicyIcon />}
>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
setPolicy(e, policyDefinition);
}}
>
<Grid container>
<Grid item xs={12} className={classes.codeMirrorContainer}>
<CodeMirrorWrapper
@@ -103,7 +122,6 @@ const ServiceAccountPolicy = ({
setPolicyDefinition(value);
}}
editorHeight={"350px"}
readOnly={true}
/>
</Grid>
<Grid item xs={12} className={classes.modalButtonBar}>
@@ -118,8 +136,19 @@ const ServiceAccountPolicy = ({
>
Cancel
</Button>
<Button
type="submit"
variant="contained"
color="primary"
disabled={
loading
}
>
Set
</Button>
</Grid>
</Grid>
</form>
</ModalWrapper>
);
};

View File

@@ -99,6 +99,7 @@ type MinioAdmin interface {
listServiceAccounts(ctx context.Context, user string) (madmin.ListServiceAccountsResp, error)
deleteServiceAccount(ctx context.Context, serviceAccount string) error
infoServiceAccount(ctx context.Context, serviceAccount string) (madmin.InfoServiceAccountResp, error)
updateServiceAccount(ctx context.Context, serviceAccount string, opts madmin.UpdateServiceAccountReq) error
// Remote Buckets
listRemoteBuckets(ctx context.Context, bucket, arnType string) (targets []madmin.BucketTarget, err error)
getRemoteBucket(ctx context.Context, bucket, arnType string) (targets *madmin.BucketTarget, err error)
@@ -312,6 +313,11 @@ func (ac AdminClient) infoServiceAccount(ctx context.Context, serviceAccount str
return ac.Client.InfoServiceAccount(ctx, serviceAccount)
}
// implements madmin.UpdateServiceAccount()
func (ac AdminClient) updateServiceAccount(ctx context.Context, serviceAccount string, opts madmin.UpdateServiceAccountReq) error {
return ac.Client.UpdateServiceAccount(ctx, serviceAccount, opts)
}
// AccountInfo implements madmin.AccountInfo()
func (ac AdminClient) AccountInfo(ctx context.Context) (madmin.AccountInfo, error) {
return ac.Client.AccountInfo(ctx, madmin.AccountOpts{})

View File

@@ -3184,6 +3184,40 @@ func init() {
}
}
}
},
"put": {
"tags": [
"UserAPI"
],
"summary": "Set Service Account Policy",
"operationId": "SetServiceAccountPolicy",
"parameters": [
{
"type": "string",
"name": "access_key",
"in": "path",
"required": true
},
{
"name": "policy",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/addServiceAccountPolicyRequest"
}
}
],
"responses": {
"200": {
"description": "A successful response."
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/service/restart": {
@@ -3918,6 +3952,17 @@ func init() {
}
}
},
"addServiceAccountPolicyRequest": {
"type": "object",
"required": [
"policy"
],
"properties": {
"policy": {
"type": "string"
}
}
},
"addUserRequest": {
"type": "object",
"required": [
@@ -9397,6 +9442,40 @@ func init() {
}
}
}
},
"put": {
"tags": [
"UserAPI"
],
"summary": "Set Service Account Policy",
"operationId": "SetServiceAccountPolicy",
"parameters": [
{
"type": "string",
"name": "access_key",
"in": "path",
"required": true
},
{
"name": "policy",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/addServiceAccountPolicyRequest"
}
}
],
"responses": {
"200": {
"description": "A successful response."
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/service/restart": {
@@ -10249,6 +10328,17 @@ func init() {
}
}
},
"addServiceAccountPolicyRequest": {
"type": "object",
"required": [
"policy"
],
"properties": {
"policy": {
"type": "string"
}
}
},
"addUserRequest": {
"type": "object",
"required": [

View File

@@ -356,6 +356,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
AdminAPISetPolicyMultipleHandler: admin_api.SetPolicyMultipleHandlerFunc(func(params admin_api.SetPolicyMultipleParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.SetPolicyMultiple has not yet been implemented")
}),
UserAPISetServiceAccountPolicyHandler: user_api.SetServiceAccountPolicyHandlerFunc(func(params user_api.SetServiceAccountPolicyParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.SetServiceAccountPolicy has not yet been implemented")
}),
UserAPIShareObjectHandler: user_api.ShareObjectHandlerFunc(func(params user_api.ShareObjectParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.ShareObject has not yet been implemented")
}),
@@ -641,6 +644,8 @@ type ConsoleAPI struct {
AdminAPISetPolicyHandler admin_api.SetPolicyHandler
// AdminAPISetPolicyMultipleHandler sets the operation handler for the set policy multiple operation
AdminAPISetPolicyMultipleHandler admin_api.SetPolicyMultipleHandler
// UserAPISetServiceAccountPolicyHandler sets the operation handler for the set service account policy operation
UserAPISetServiceAccountPolicyHandler user_api.SetServiceAccountPolicyHandler
// UserAPIShareObjectHandler sets the operation handler for the share object operation
UserAPIShareObjectHandler user_api.ShareObjectHandler
// AdminAPISubnetInfoHandler sets the operation handler for the subnet info operation
@@ -1043,6 +1048,9 @@ func (o *ConsoleAPI) Validate() error {
if o.AdminAPISetPolicyMultipleHandler == nil {
unregistered = append(unregistered, "admin_api.SetPolicyMultipleHandler")
}
if o.UserAPISetServiceAccountPolicyHandler == nil {
unregistered = append(unregistered, "user_api.SetServiceAccountPolicyHandler")
}
if o.UserAPIShareObjectHandler == nil {
unregistered = append(unregistered, "user_api.ShareObjectHandler")
}
@@ -1569,6 +1577,10 @@ func (o *ConsoleAPI) initHandlerCache() {
o.handlers["PUT"] = make(map[string]http.Handler)
}
o.handlers["PUT"]["/set-policy-multi"] = admin_api.NewSetPolicyMultiple(o.context, o.AdminAPISetPolicyMultipleHandler)
if o.handlers["PUT"] == nil {
o.handlers["PUT"] = make(map[string]http.Handler)
}
o.handlers["PUT"]["/service-accounts/{access_key}/policy"] = user_api.NewSetServiceAccountPolicy(o.context, o.UserAPISetServiceAccountPolicyHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}

View File

@@ -0,0 +1,88 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 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 <http://www.gnu.org/licenses/>.
//
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/console/models"
)
// SetServiceAccountPolicyHandlerFunc turns a function with the right signature into a set service account policy handler
type SetServiceAccountPolicyHandlerFunc func(SetServiceAccountPolicyParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn SetServiceAccountPolicyHandlerFunc) Handle(params SetServiceAccountPolicyParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// SetServiceAccountPolicyHandler interface for that can handle valid set service account policy params
type SetServiceAccountPolicyHandler interface {
Handle(SetServiceAccountPolicyParams, *models.Principal) middleware.Responder
}
// NewSetServiceAccountPolicy creates a new http.Handler for the set service account policy operation
func NewSetServiceAccountPolicy(ctx *middleware.Context, handler SetServiceAccountPolicyHandler) *SetServiceAccountPolicy {
return &SetServiceAccountPolicy{Context: ctx, Handler: handler}
}
/* SetServiceAccountPolicy swagger:route PUT /service-accounts/{access_key}/policy UserAPI setServiceAccountPolicy
Set Service Account Policy
*/
type SetServiceAccountPolicy struct {
Context *middleware.Context
Handler SetServiceAccountPolicyHandler
}
func (o *SetServiceAccountPolicy) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
*r = *rCtx
}
var Params = NewSetServiceAccountPolicyParams()
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)
}

View File

@@ -0,0 +1,127 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 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 <http://www.gnu.org/licenses/>.
//
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 (
"context"
"io"
"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/validate"
"github.com/minio/console/models"
)
// NewSetServiceAccountPolicyParams creates a new SetServiceAccountPolicyParams object
//
// There are no default values defined in the spec.
func NewSetServiceAccountPolicyParams() SetServiceAccountPolicyParams {
return SetServiceAccountPolicyParams{}
}
// SetServiceAccountPolicyParams contains all the bound params for the set service account policy operation
// typically these are obtained from a http.Request
//
// swagger:parameters SetServiceAccountPolicy
type SetServiceAccountPolicyParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*
Required: true
In: path
*/
AccessKey string
/*
Required: true
In: body
*/
Policy *models.AddServiceAccountPolicyRequest
}
// 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 NewSetServiceAccountPolicyParams() beforehand.
func (o *SetServiceAccountPolicyParams) 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 runtime.HasBody(r) {
defer r.Body.Close()
var body models.AddServiceAccountPolicyRequest
if err := route.Consumer.Consume(r.Body, &body); err != nil {
if err == io.EOF {
res = append(res, errors.Required("policy", "body", ""))
} else {
res = append(res, errors.NewParseError("policy", "body", "", err))
}
} else {
// validate body object
if err := body.Validate(route.Formats); err != nil {
res = append(res, err)
}
ctx := validate.WithOperationRequest(context.Background())
if err := body.ContextValidate(ctx, route.Formats); err != nil {
res = append(res, err)
}
if len(res) == 0 {
o.Policy = &body
}
}
} else {
res = append(res, errors.Required("policy", "body", ""))
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// bindAccessKey binds and validates parameter AccessKey from path.
func (o *SetServiceAccountPolicyParams) 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
}

View File

@@ -0,0 +1,113 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 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 <http://www.gnu.org/licenses/>.
//
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/console/models"
)
// SetServiceAccountPolicyOKCode is the HTTP code returned for type SetServiceAccountPolicyOK
const SetServiceAccountPolicyOKCode int = 200
/*SetServiceAccountPolicyOK A successful response.
swagger:response setServiceAccountPolicyOK
*/
type SetServiceAccountPolicyOK struct {
}
// NewSetServiceAccountPolicyOK creates SetServiceAccountPolicyOK with default headers values
func NewSetServiceAccountPolicyOK() *SetServiceAccountPolicyOK {
return &SetServiceAccountPolicyOK{}
}
// WriteResponse to the client
func (o *SetServiceAccountPolicyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(200)
}
/*SetServiceAccountPolicyDefault Generic error response.
swagger:response setServiceAccountPolicyDefault
*/
type SetServiceAccountPolicyDefault struct {
_statusCode int
/*
In: Body
*/
Payload *models.Error `json:"body,omitempty"`
}
// NewSetServiceAccountPolicyDefault creates SetServiceAccountPolicyDefault with default headers values
func NewSetServiceAccountPolicyDefault(code int) *SetServiceAccountPolicyDefault {
if code <= 0 {
code = 500
}
return &SetServiceAccountPolicyDefault{
_statusCode: code,
}
}
// WithStatusCode adds the status to the set service account policy default response
func (o *SetServiceAccountPolicyDefault) WithStatusCode(code int) *SetServiceAccountPolicyDefault {
o._statusCode = code
return o
}
// SetStatusCode sets the status to the set service account policy default response
func (o *SetServiceAccountPolicyDefault) SetStatusCode(code int) {
o._statusCode = code
}
// WithPayload adds the payload to the set service account policy default response
func (o *SetServiceAccountPolicyDefault) WithPayload(payload *models.Error) *SetServiceAccountPolicyDefault {
o.Payload = payload
return o
}
// SetPayload sets the payload to the set service account policy default response
func (o *SetServiceAccountPolicyDefault) SetPayload(payload *models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *SetServiceAccountPolicyDefault) 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
}
}
}

View File

@@ -0,0 +1,116 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2021 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 <http://www.gnu.org/licenses/>.
//
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"
)
// SetServiceAccountPolicyURL generates an URL for the set service account policy operation
type SetServiceAccountPolicyURL 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 *SetServiceAccountPolicyURL) WithBasePath(bp string) *SetServiceAccountPolicyURL {
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 *SetServiceAccountPolicyURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *SetServiceAccountPolicyURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/service-accounts/{access_key}/policy"
accessKey := o.AccessKey
if accessKey != "" {
_path = strings.Replace(_path, "{access_key}", accessKey, -1)
} else {
return nil, errors.New("accessKey is required on SetServiceAccountPolicyURL")
}
_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 *SetServiceAccountPolicyURL) 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 *SetServiceAccountPolicyURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *SetServiceAccountPolicyURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on SetServiceAccountPolicyURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on SetServiceAccountPolicyURL")
}
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 *SetServiceAccountPolicyURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

View File

@@ -25,12 +25,12 @@ import (
"strings"
"time"
"github.com/minio/console/restapi/operations/admin_api"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/restapi/operations/admin_api"
"github.com/minio/console/restapi/operations/user_api"
"github.com/minio/madmin-go"
iampolicy "github.com/minio/pkg/iam/policy"
)
@@ -100,6 +100,14 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) {
return user_api.NewGetServiceAccountPolicyOK().WithPayload(serviceAccounts)
})
api.UserAPISetServiceAccountPolicyHandler = user_api.SetServiceAccountPolicyHandlerFunc(func(params user_api.SetServiceAccountPolicyParams, session *models.Principal) middleware.Responder {
err := getSetServiceAccountPolicyResponse(session, params.AccessKey, *params.Policy.Policy)
if err != nil {
return user_api.NewSetServiceAccountPolicyDefault(int(err.Code)).WithPayload(err)
}
return user_api.NewSetServiceAccountPolicyOK()
})
// Delete multiple service accounts
api.UserAPIDeleteMultipleServiceAccountsHandler = user_api.DeleteMultipleServiceAccountsHandlerFunc(func(params user_api.DeleteMultipleServiceAccountsParams, session *models.Principal) middleware.Responder {
if err := getDeleteMultipleServiceAccountsResponse(session, params.SelectedSA); err != nil {
@@ -396,6 +404,33 @@ func getServiceAccountPolicyResponse(session *models.Principal, accessKey string
return serviceAccounts, nil
}
// setServiceAccountPolicy sets policy for a service account
func setServiceAccountPolicy(ctx context.Context, userClient MinioAdmin, accessKey string, policy string) error {
err := userClient.updateServiceAccount(ctx, accessKey, madmin.UpdateServiceAccountReq{NewPolicy: json.RawMessage(policy)})
return err
}
// getSetServiceAccountPolicyResponse authenticates the user and calls
// getSetServiceAccountPolicy to set the policy for a service account
func getSetServiceAccountPolicyResponse(session *models.Principal, accessKey string, policy string) *models.Error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
userAdmin, err := NewMinioAdminClient(session)
if err != nil {
return prepareError(err)
}
// create a MinIO user Admin Client interface implementation
// defining the client to be used
userAdminClient := AdminClient{Client: userAdmin}
err = setServiceAccountPolicy(ctx, userAdminClient, accessKey, policy)
if err != nil {
return prepareError(err)
}
return nil
}
// getDeleteMultipleServiceAccountsResponse authenticates the user and calls deleteServiceAccount for each account listed in selectedSAs
func getDeleteMultipleServiceAccountsResponse(session *models.Principal, selectedSAs []string) *models.Error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)

View File

@@ -33,6 +33,7 @@ var minioAddServiceAccountMock func(ctx context.Context, policy *iampolicy.Polic
var minioListServiceAccountsMock func(ctx context.Context, user string) (madmin.ListServiceAccountsResp, error)
var minioDeleteServiceAccountMock func(ctx context.Context, serviceAccount string) error
var minioInfoServiceAccountMock func(ctx context.Context, serviceAccount string) (madmin.InfoServiceAccountResp, error)
var minioUpdateServiceAccountMock func(ctx context.Context, serviceAccount string, opts madmin.UpdateServiceAccountReq) error
// mock function of AddServiceAccount()
func (ac adminClientMock) addServiceAccount(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) {
@@ -54,6 +55,11 @@ func (ac adminClientMock) infoServiceAccount(ctx context.Context, serviceAccount
return minioInfoServiceAccountMock(ctx, serviceAccount)
}
// mock function of UpdateServiceAccount()
func (ac adminClientMock) updateServiceAccount(ctx context.Context, serviceAccount string, opts madmin.UpdateServiceAccountReq) error {
return minioUpdateServiceAccountMock(ctx, serviceAccount, opts)
}
func TestAddServiceAccount(t *testing.T) {
assert := assert.New(t)
// mock minIO client

View File

@@ -1324,6 +1324,28 @@ paths:
$ref: "#/definitions/error"
tags:
- UserAPI
put:
summary: Set Service Account Policy
operationId: SetServiceAccountPolicy
parameters:
- name: access_key
in: path
required: true
type: string
- name: policy
in: body
required: true
schema:
$ref: "#/definitions/addServiceAccountPolicyRequest"
responses:
200:
description: A successful response.
default:
description: Generic error response.
schema:
$ref: "#/definitions/error"
tags:
- UserAPI
/users:
get:
@@ -2892,6 +2914,15 @@ definitions:
type: string
policy:
type: string
addServiceAccountPolicyRequest:
type: object
required:
- policy
properties:
policy:
type: string
listPoliciesResponse:
type: object
properties: