From 849132fa19d6d902b83bc5ae4b3b8a9a732fe201 Mon Sep 17 00:00:00 2001 From: adfost Date: Wed, 1 Sep 2021 09:54:13 -0700 Subject: [PATCH] Adding accesskey and secretkey for service accounts (#985) * adding accesskey and secretkey for service accounts * simplifying functions Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> Co-authored-by: Adam Stafford --- models/service_account_request_creds.go | 73 ++++++++ .../Console/Account/AddServiceAccount.tsx | 83 +++++++-- .../Console/Users/AddUserServiceAccount.tsx | 83 +++++++-- restapi/client-admin.go | 22 +-- restapi/embedded_spec.go | 174 ++++++++++++++++++ .../create_service_account_credentials.go | 88 +++++++++ ..._service_account_credentials_parameters.go | 127 +++++++++++++ ...e_service_account_credentials_responses.go | 133 +++++++++++++ ..._service_account_credentials_urlbuilder.go | 116 ++++++++++++ .../admin_api/create_service_account_creds.go | 88 +++++++++ ...create_service_account_creds_parameters.go | 102 ++++++++++ .../create_service_account_creds_responses.go | 133 +++++++++++++ ...create_service_account_creds_urlbuilder.go | 104 +++++++++++ restapi/operations/console_api.go | 24 +++ restapi/user_service_accounts.go | 133 ++++++++++++- restapi/user_service_accounts_test.go | 17 +- swagger-console.yml | 58 ++++++ 17 files changed, 1501 insertions(+), 57 deletions(-) create mode 100644 models/service_account_request_creds.go create mode 100644 restapi/operations/admin_api/create_service_account_credentials.go create mode 100644 restapi/operations/admin_api/create_service_account_credentials_parameters.go create mode 100644 restapi/operations/admin_api/create_service_account_credentials_responses.go create mode 100644 restapi/operations/admin_api/create_service_account_credentials_urlbuilder.go create mode 100644 restapi/operations/admin_api/create_service_account_creds.go create mode 100644 restapi/operations/admin_api/create_service_account_creds_parameters.go create mode 100644 restapi/operations/admin_api/create_service_account_creds_responses.go create mode 100644 restapi/operations/admin_api/create_service_account_creds_urlbuilder.go diff --git a/models/service_account_request_creds.go b/models/service_account_request_creds.go new file mode 100644 index 000000000..91510dd22 --- /dev/null +++ b/models/service_account_request_creds.go @@ -0,0 +1,73 @@ +// 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 . +// + +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/strfmt" + "github.com/go-openapi/swag" +) + +// ServiceAccountRequestCreds service account request creds +// +// swagger:model serviceAccountRequestCreds +type ServiceAccountRequestCreds struct { + + // access key + AccessKey string `json:"accessKey,omitempty"` + + // policy to be applied to the Service Account if any + Policy string `json:"policy,omitempty"` + + // secret key + SecretKey string `json:"secretKey,omitempty"` +} + +// Validate validates this service account request creds +func (m *ServiceAccountRequestCreds) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this service account request creds based on context it is used +func (m *ServiceAccountRequestCreds) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *ServiceAccountRequestCreds) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ServiceAccountRequestCreds) UnmarshalBinary(b []byte) error { + var res ServiceAccountRequestCreds + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/portal-ui/src/screens/Console/Account/AddServiceAccount.tsx b/portal-ui/src/screens/Console/Account/AddServiceAccount.tsx index 2f68bac6c..948008616 100644 --- a/portal-ui/src/screens/Console/Account/AddServiceAccount.tsx +++ b/portal-ui/src/screens/Console/Account/AddServiceAccount.tsx @@ -27,6 +27,7 @@ import ModalWrapper from "../Common/ModalWrapper/ModalWrapper"; import api from "../../../common/api"; import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper"; import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; +import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; const styles = (theme: Theme) => createStyles({ @@ -65,23 +66,43 @@ const AddServiceAccount = ({ }: IAddServiceAccountProps) => { const [addSending, setAddSending] = useState(false); const [policyDefinition, setPolicyDefinition] = useState(""); + const [accessKey, setAccessKey] = useState(""); + const [secretKey, setSecretKey] = useState(""); const [isRestrictedByPolicy, setIsRestrictedByPolicy] = useState(false); + const [addCredentials, setAddCredentials] = useState(false); useEffect(() => { if (addSending) { - api - .invoke("POST", "/api/v1/service-accounts", { - policy: policyDefinition, - }) - .then((res) => { - setAddSending(false); - closeModalAndRefresh(res); - }) - .catch((err: ErrorResponseHandler) => { - setAddSending(false); - setModalErrorSnackMessage(err); - }); + if (addCredentials) { + api + .invoke("POST", `/api/v1/service-account-credentials`, { + policy: policyDefinition, + accessKey: accessKey, + secretKey: secretKey + }) + .then((res) => { + setAddSending(false); + closeModalAndRefresh(res); + }) + .catch((err: ErrorResponseHandler) => { + setAddSending(false); + setModalErrorSnackMessage(err); + }); + } else { + api + .invoke("POST", `/api/v1/service-accounts`, { + policy: policyDefinition, + }) + .then((res) => { + setAddSending(false); + closeModalAndRefresh(res); + }) + .catch((err: ErrorResponseHandler) => { + setAddSending(false); + setModalErrorSnackMessage(err); + }); + } } }, [ addSending, @@ -89,6 +110,9 @@ const AddServiceAccount = ({ setModalErrorSnackMessage, policyDefinition, closeModalAndRefresh, + addCredentials, + accessKey, + secretKey, ]); const addServiceAccount = (e: React.FormEvent) => { @@ -139,6 +163,17 @@ const AddServiceAccount = ({ label={"Restrict with policy"} indicatorLabels={["On", "Off"]} /> + ) => { + setAddCredentials(event.target.checked); + }} + label={"Customize Credentials"} + indicatorLabels={["On", "Off"]} + /> {isRestrictedByPolicy && ( @@ -150,6 +185,30 @@ const AddServiceAccount = ({ /> )} + {addCredentials && ( + + { + setAccessKey(e.target.value); + }} + /> + { + setSecretKey(e.target.value); + }} + /> + + )} diff --git a/portal-ui/src/screens/Console/Users/AddUserServiceAccount.tsx b/portal-ui/src/screens/Console/Users/AddUserServiceAccount.tsx index 8ca6b6502..2e6bb305f 100644 --- a/portal-ui/src/screens/Console/Users/AddUserServiceAccount.tsx +++ b/portal-ui/src/screens/Console/Users/AddUserServiceAccount.tsx @@ -27,6 +27,7 @@ import ModalWrapper from "../Common/ModalWrapper/ModalWrapper"; import api from "../../../common/api"; import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper"; import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; +import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; const styles = (theme: Theme) => createStyles({ @@ -67,23 +68,43 @@ const AddUserServiceAccount = ({ }: IAddUserServiceAccountProps) => { const [addSending, setAddSending] = useState(false); const [policyDefinition, setPolicyDefinition] = useState(""); + const [accessKey, setAccessKey] = useState(""); + const [secretKey, setSecretKey] = useState(""); const [isRestrictedByPolicy, setIsRestrictedByPolicy] = useState(false); + const [addCredentials, setAddCredentials] = useState(false); useEffect(() => { if (addSending) { - api - .invoke("POST", `/api/v1/user/${user}/service-accounts`, { - policy: policyDefinition, - }) - .then((res) => { - setAddSending(false); - closeModalAndRefresh(res); - }) - .catch((err: ErrorResponseHandler) => { - setAddSending(false); - setModalErrorSnackMessage(err); - }); + if (addCredentials) { + api + .invoke("POST", `/api/v1/user/${user}/service-account-credentials`, { + policy: policyDefinition, + accessKey: accessKey, + secretKey: secretKey + }) + .then((res) => { + setAddSending(false); + closeModalAndRefresh(res); + }) + .catch((err: ErrorResponseHandler) => { + setAddSending(false); + setModalErrorSnackMessage(err); + }); + } else { + api + .invoke("POST", `/api/v1/user/${user}/service-accounts`, { + policy: policyDefinition, + }) + .then((res) => { + setAddSending(false); + closeModalAndRefresh(res); + }) + .catch((err: ErrorResponseHandler) => { + setAddSending(false); + setModalErrorSnackMessage(err); + }); + } } }, [ addSending, @@ -92,6 +113,9 @@ const AddUserServiceAccount = ({ policyDefinition, closeModalAndRefresh, user, + addCredentials, + accessKey, + secretKey, ]); const addUserServiceAccount = (e: React.FormEvent) => { @@ -142,6 +166,17 @@ const AddUserServiceAccount = ({ label={"Restrict with policy"} indicatorLabels={["On", "Off"]} /> + ) => { + setAddCredentials(event.target.checked); + }} + label={"Customize Credentials"} + indicatorLabels={["On", "Off"]} + /> {isRestrictedByPolicy && ( @@ -153,6 +188,30 @@ const AddUserServiceAccount = ({ /> )} + {addCredentials && ( + + { + setAccessKey(e.target.value); + }} + /> + { + setSecretKey(e.target.value); + }} + /> + + )} diff --git a/restapi/client-admin.go b/restapi/client-admin.go index 423d20ee8..f64353dd9 100644 --- a/restapi/client-admin.go +++ b/restapi/client-admin.go @@ -94,8 +94,7 @@ type MinioAdmin interface { heal(ctx context.Context, bucket, prefix string, healOpts madmin.HealOpts, clientToken string, forceStart, forceStop bool) (healStart madmin.HealStartSuccess, healTaskStatus madmin.HealTaskStatus, err error) // Service Accounts - addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (madmin.Credentials, error) - addServiceAccountWithUser(ctx context.Context, policy *iampolicy.Policy, user string) (madmin.Credentials, error) + addServiceAccount(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) listServiceAccounts(ctx context.Context, user string) (madmin.ListServiceAccountsResp, error) deleteServiceAccount(ctx context.Context, serviceAccount string) error // Remote Buckets @@ -274,20 +273,7 @@ func (ac AdminClient) getLogs(ctx context.Context, node string, lineCnt int, log } // implements madmin.AddServiceAccount() -func (ac AdminClient) addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (madmin.Credentials, error) { - buf, err := json.Marshal(policy) - if err != nil { - return madmin.Credentials{}, err - } - return ac.Client.AddServiceAccount(ctx, madmin.AddServiceAccountReq{ - Policy: buf, - TargetUser: "", - AccessKey: "", - SecretKey: "", - }) -} - -func (ac AdminClient) addServiceAccountWithUser(ctx context.Context, policy *iampolicy.Policy, user string) (madmin.Credentials, error) { +func (ac AdminClient) addServiceAccount(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) { buf, err := json.Marshal(policy) if err != nil { return madmin.Credentials{}, err @@ -295,8 +281,8 @@ func (ac AdminClient) addServiceAccountWithUser(ctx context.Context, policy *iam return ac.Client.AddServiceAccount(ctx, madmin.AddServiceAccountReq{ Policy: buf, TargetUser: user, - AccessKey: "", - SecretKey: "", + AccessKey: accessKey, + SecretKey: secretKey, }) } diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 4ae2bdaa4..f7c062520 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -2813,6 +2813,39 @@ func init() { } } }, + "/service-account-credentials": { + "post": { + "tags": [ + "AdminAPI" + ], + "summary": "Create Service Account With Credentials", + "operationId": "CreateServiceAccountCreds", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/serviceAccountRequestCreds" + } + } + ], + "responses": { + "201": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/serviceAccountCreds" + } + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/service-accounts": { "get": { "tags": [ @@ -3180,6 +3213,45 @@ func init() { } } }, + "/user/{name}/service-account-credentials": { + "post": { + "tags": [ + "AdminAPI" + ], + "summary": "Create Service Account for User With Credentials", + "operationId": "CreateServiceAccountCredentials", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/serviceAccountRequestCreds" + } + } + ], + "responses": { + "201": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/serviceAccountCreds" + } + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/user/{name}/service-accounts": { "get": { "tags": [ @@ -4935,6 +5007,21 @@ func init() { } } }, + "serviceAccountRequestCreds": { + "type": "object", + "properties": { + "accessKey": { + "type": "string" + }, + "policy": { + "type": "string", + "title": "policy to be applied to the Service Account if any" + }, + "secretKey": { + "type": "string" + } + } + }, "serviceAccounts": { "type": "array", "items": { @@ -8237,6 +8324,39 @@ func init() { } } }, + "/service-account-credentials": { + "post": { + "tags": [ + "AdminAPI" + ], + "summary": "Create Service Account With Credentials", + "operationId": "CreateServiceAccountCreds", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/serviceAccountRequestCreds" + } + } + ], + "responses": { + "201": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/serviceAccountCreds" + } + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/service-accounts": { "get": { "tags": [ @@ -8604,6 +8724,45 @@ func init() { } } }, + "/user/{name}/service-account-credentials": { + "post": { + "tags": [ + "AdminAPI" + ], + "summary": "Create Service Account for User With Credentials", + "operationId": "CreateServiceAccountCredentials", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/serviceAccountRequestCreds" + } + } + ], + "responses": { + "201": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/serviceAccountCreds" + } + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/user/{name}/service-accounts": { "get": { "tags": [ @@ -10413,6 +10572,21 @@ func init() { } } }, + "serviceAccountRequestCreds": { + "type": "object", + "properties": { + "accessKey": { + "type": "string" + }, + "policy": { + "type": "string", + "title": "policy to be applied to the Service Account if any" + }, + "secretKey": { + "type": "string" + } + } + }, "serviceAccounts": { "type": "array", "items": { diff --git a/restapi/operations/admin_api/create_service_account_credentials.go b/restapi/operations/admin_api/create_service_account_credentials.go new file mode 100644 index 000000000..85caf77cb --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_credentials.go @@ -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 . +// + +package admin_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" +) + +// CreateServiceAccountCredentialsHandlerFunc turns a function with the right signature into a create service account credentials handler +type CreateServiceAccountCredentialsHandlerFunc func(CreateServiceAccountCredentialsParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn CreateServiceAccountCredentialsHandlerFunc) Handle(params CreateServiceAccountCredentialsParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// CreateServiceAccountCredentialsHandler interface for that can handle valid create service account credentials params +type CreateServiceAccountCredentialsHandler interface { + Handle(CreateServiceAccountCredentialsParams, *models.Principal) middleware.Responder +} + +// NewCreateServiceAccountCredentials creates a new http.Handler for the create service account credentials operation +func NewCreateServiceAccountCredentials(ctx *middleware.Context, handler CreateServiceAccountCredentialsHandler) *CreateServiceAccountCredentials { + return &CreateServiceAccountCredentials{Context: ctx, Handler: handler} +} + +/* CreateServiceAccountCredentials swagger:route POST /user/{name}/service-account-credentials AdminAPI createServiceAccountCredentials + +Create Service Account for User With Credentials + +*/ +type CreateServiceAccountCredentials struct { + Context *middleware.Context + Handler CreateServiceAccountCredentialsHandler +} + +func (o *CreateServiceAccountCredentials) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewCreateServiceAccountCredentialsParams() + 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/admin_api/create_service_account_credentials_parameters.go b/restapi/operations/admin_api/create_service_account_credentials_parameters.go new file mode 100644 index 000000000..46f57dc27 --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_credentials_parameters.go @@ -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 . +// + +package admin_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" +) + +// NewCreateServiceAccountCredentialsParams creates a new CreateServiceAccountCredentialsParams object +// +// There are no default values defined in the spec. +func NewCreateServiceAccountCredentialsParams() CreateServiceAccountCredentialsParams { + + return CreateServiceAccountCredentialsParams{} +} + +// CreateServiceAccountCredentialsParams contains all the bound params for the create service account credentials operation +// typically these are obtained from a http.Request +// +// swagger:parameters CreateServiceAccountCredentials +type CreateServiceAccountCredentialsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: body + */ + Body *models.ServiceAccountRequestCreds + /* + Required: true + In: path + */ + Name 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 NewCreateServiceAccountCredentialsParams() beforehand. +func (o *CreateServiceAccountCredentialsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ServiceAccountRequestCreds + if err := route.Consumer.Consume(r.Body, &body); err != nil { + if err == io.EOF { + res = append(res, errors.Required("body", "body", "")) + } else { + res = append(res, errors.NewParseError("body", "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.Body = &body + } + } + } else { + res = append(res, errors.Required("body", "body", "")) + } + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *CreateServiceAccountCredentialsParams) bindName(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.Name = raw + + return nil +} diff --git a/restapi/operations/admin_api/create_service_account_credentials_responses.go b/restapi/operations/admin_api/create_service_account_credentials_responses.go new file mode 100644 index 000000000..c0d81b631 --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_credentials_responses.go @@ -0,0 +1,133 @@ +// 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 . +// + +package admin_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" +) + +// CreateServiceAccountCredentialsCreatedCode is the HTTP code returned for type CreateServiceAccountCredentialsCreated +const CreateServiceAccountCredentialsCreatedCode int = 201 + +/*CreateServiceAccountCredentialsCreated A successful response. + +swagger:response createServiceAccountCredentialsCreated +*/ +type CreateServiceAccountCredentialsCreated struct { + + /* + In: Body + */ + Payload *models.ServiceAccountCreds `json:"body,omitempty"` +} + +// NewCreateServiceAccountCredentialsCreated creates CreateServiceAccountCredentialsCreated with default headers values +func NewCreateServiceAccountCredentialsCreated() *CreateServiceAccountCredentialsCreated { + + return &CreateServiceAccountCredentialsCreated{} +} + +// WithPayload adds the payload to the create service account credentials created response +func (o *CreateServiceAccountCredentialsCreated) WithPayload(payload *models.ServiceAccountCreds) *CreateServiceAccountCredentialsCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the create service account credentials created response +func (o *CreateServiceAccountCredentialsCreated) SetPayload(payload *models.ServiceAccountCreds) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *CreateServiceAccountCredentialsCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +/*CreateServiceAccountCredentialsDefault Generic error response. + +swagger:response createServiceAccountCredentialsDefault +*/ +type CreateServiceAccountCredentialsDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewCreateServiceAccountCredentialsDefault creates CreateServiceAccountCredentialsDefault with default headers values +func NewCreateServiceAccountCredentialsDefault(code int) *CreateServiceAccountCredentialsDefault { + if code <= 0 { + code = 500 + } + + return &CreateServiceAccountCredentialsDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the create service account credentials default response +func (o *CreateServiceAccountCredentialsDefault) WithStatusCode(code int) *CreateServiceAccountCredentialsDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the create service account credentials default response +func (o *CreateServiceAccountCredentialsDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the create service account credentials default response +func (o *CreateServiceAccountCredentialsDefault) WithPayload(payload *models.Error) *CreateServiceAccountCredentialsDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the create service account credentials default response +func (o *CreateServiceAccountCredentialsDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *CreateServiceAccountCredentialsDefault) 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/admin_api/create_service_account_credentials_urlbuilder.go b/restapi/operations/admin_api/create_service_account_credentials_urlbuilder.go new file mode 100644 index 000000000..e67f0fb12 --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_credentials_urlbuilder.go @@ -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 . +// + +package admin_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" +) + +// CreateServiceAccountCredentialsURL generates an URL for the create service account credentials operation +type CreateServiceAccountCredentialsURL struct { + Name 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 *CreateServiceAccountCredentialsURL) WithBasePath(bp string) *CreateServiceAccountCredentialsURL { + 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 *CreateServiceAccountCredentialsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *CreateServiceAccountCredentialsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/user/{name}/service-account-credentials" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on CreateServiceAccountCredentialsURL") + } + + _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 *CreateServiceAccountCredentialsURL) 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 *CreateServiceAccountCredentialsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *CreateServiceAccountCredentialsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on CreateServiceAccountCredentialsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on CreateServiceAccountCredentialsURL") + } + + 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 *CreateServiceAccountCredentialsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/operations/admin_api/create_service_account_creds.go b/restapi/operations/admin_api/create_service_account_creds.go new file mode 100644 index 000000000..083aa36e0 --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_creds.go @@ -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 . +// + +package admin_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" +) + +// CreateServiceAccountCredsHandlerFunc turns a function with the right signature into a create service account creds handler +type CreateServiceAccountCredsHandlerFunc func(CreateServiceAccountCredsParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn CreateServiceAccountCredsHandlerFunc) Handle(params CreateServiceAccountCredsParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// CreateServiceAccountCredsHandler interface for that can handle valid create service account creds params +type CreateServiceAccountCredsHandler interface { + Handle(CreateServiceAccountCredsParams, *models.Principal) middleware.Responder +} + +// NewCreateServiceAccountCreds creates a new http.Handler for the create service account creds operation +func NewCreateServiceAccountCreds(ctx *middleware.Context, handler CreateServiceAccountCredsHandler) *CreateServiceAccountCreds { + return &CreateServiceAccountCreds{Context: ctx, Handler: handler} +} + +/* CreateServiceAccountCreds swagger:route POST /service-account-credentials AdminAPI createServiceAccountCreds + +Create Service Account With Credentials + +*/ +type CreateServiceAccountCreds struct { + Context *middleware.Context + Handler CreateServiceAccountCredsHandler +} + +func (o *CreateServiceAccountCreds) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewCreateServiceAccountCredsParams() + 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/admin_api/create_service_account_creds_parameters.go b/restapi/operations/admin_api/create_service_account_creds_parameters.go new file mode 100644 index 000000000..69bc8d759 --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_creds_parameters.go @@ -0,0 +1,102 @@ +// 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 . +// + +package admin_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/validate" + + "github.com/minio/console/models" +) + +// NewCreateServiceAccountCredsParams creates a new CreateServiceAccountCredsParams object +// +// There are no default values defined in the spec. +func NewCreateServiceAccountCredsParams() CreateServiceAccountCredsParams { + + return CreateServiceAccountCredsParams{} +} + +// CreateServiceAccountCredsParams contains all the bound params for the create service account creds operation +// typically these are obtained from a http.Request +// +// swagger:parameters CreateServiceAccountCreds +type CreateServiceAccountCredsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: body + */ + Body *models.ServiceAccountRequestCreds +} + +// 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 NewCreateServiceAccountCredsParams() beforehand. +func (o *CreateServiceAccountCredsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ServiceAccountRequestCreds + if err := route.Consumer.Consume(r.Body, &body); err != nil { + if err == io.EOF { + res = append(res, errors.Required("body", "body", "")) + } else { + res = append(res, errors.NewParseError("body", "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.Body = &body + } + } + } else { + res = append(res, errors.Required("body", "body", "")) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/restapi/operations/admin_api/create_service_account_creds_responses.go b/restapi/operations/admin_api/create_service_account_creds_responses.go new file mode 100644 index 000000000..6832a6b41 --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_creds_responses.go @@ -0,0 +1,133 @@ +// 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 . +// + +package admin_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" +) + +// CreateServiceAccountCredsCreatedCode is the HTTP code returned for type CreateServiceAccountCredsCreated +const CreateServiceAccountCredsCreatedCode int = 201 + +/*CreateServiceAccountCredsCreated A successful response. + +swagger:response createServiceAccountCredsCreated +*/ +type CreateServiceAccountCredsCreated struct { + + /* + In: Body + */ + Payload *models.ServiceAccountCreds `json:"body,omitempty"` +} + +// NewCreateServiceAccountCredsCreated creates CreateServiceAccountCredsCreated with default headers values +func NewCreateServiceAccountCredsCreated() *CreateServiceAccountCredsCreated { + + return &CreateServiceAccountCredsCreated{} +} + +// WithPayload adds the payload to the create service account creds created response +func (o *CreateServiceAccountCredsCreated) WithPayload(payload *models.ServiceAccountCreds) *CreateServiceAccountCredsCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the create service account creds created response +func (o *CreateServiceAccountCredsCreated) SetPayload(payload *models.ServiceAccountCreds) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *CreateServiceAccountCredsCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +/*CreateServiceAccountCredsDefault Generic error response. + +swagger:response createServiceAccountCredsDefault +*/ +type CreateServiceAccountCredsDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewCreateServiceAccountCredsDefault creates CreateServiceAccountCredsDefault with default headers values +func NewCreateServiceAccountCredsDefault(code int) *CreateServiceAccountCredsDefault { + if code <= 0 { + code = 500 + } + + return &CreateServiceAccountCredsDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the create service account creds default response +func (o *CreateServiceAccountCredsDefault) WithStatusCode(code int) *CreateServiceAccountCredsDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the create service account creds default response +func (o *CreateServiceAccountCredsDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the create service account creds default response +func (o *CreateServiceAccountCredsDefault) WithPayload(payload *models.Error) *CreateServiceAccountCredsDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the create service account creds default response +func (o *CreateServiceAccountCredsDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *CreateServiceAccountCredsDefault) 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/admin_api/create_service_account_creds_urlbuilder.go b/restapi/operations/admin_api/create_service_account_creds_urlbuilder.go new file mode 100644 index 000000000..178817518 --- /dev/null +++ b/restapi/operations/admin_api/create_service_account_creds_urlbuilder.go @@ -0,0 +1,104 @@ +// 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 . +// + +package admin_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" +) + +// CreateServiceAccountCredsURL generates an URL for the create service account creds operation +type CreateServiceAccountCredsURL struct { + _basePath string +} + +// 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 *CreateServiceAccountCredsURL) WithBasePath(bp string) *CreateServiceAccountCredsURL { + 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 *CreateServiceAccountCredsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *CreateServiceAccountCredsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/service-account-credentials" + + _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 *CreateServiceAccountCredsURL) 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 *CreateServiceAccountCredsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *CreateServiceAccountCredsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on CreateServiceAccountCredsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on CreateServiceAccountCredsURL") + } + + 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 *CreateServiceAccountCredsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/operations/console_api.go b/restapi/operations/console_api.go index 4d00ad0e9..c479387d6 100644 --- a/restapi/operations/console_api.go +++ b/restapi/operations/console_api.go @@ -119,6 +119,12 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI { UserAPICreateServiceAccountHandler: user_api.CreateServiceAccountHandlerFunc(func(params user_api.CreateServiceAccountParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation user_api.CreateServiceAccount has not yet been implemented") }), + AdminAPICreateServiceAccountCredentialsHandler: admin_api.CreateServiceAccountCredentialsHandlerFunc(func(params admin_api.CreateServiceAccountCredentialsParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation admin_api.CreateServiceAccountCredentials has not yet been implemented") + }), + AdminAPICreateServiceAccountCredsHandler: admin_api.CreateServiceAccountCredsHandlerFunc(func(params admin_api.CreateServiceAccountCredsParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation admin_api.CreateServiceAccountCreds has not yet been implemented") + }), AdminAPIDashboardWidgetDetailsHandler: admin_api.DashboardWidgetDetailsHandlerFunc(func(params admin_api.DashboardWidgetDetailsParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation admin_api.DashboardWidgetDetails has not yet been implemented") }), @@ -444,6 +450,10 @@ type ConsoleAPI struct { UserAPICreateBucketEventHandler user_api.CreateBucketEventHandler // UserAPICreateServiceAccountHandler sets the operation handler for the create service account operation UserAPICreateServiceAccountHandler user_api.CreateServiceAccountHandler + // AdminAPICreateServiceAccountCredentialsHandler sets the operation handler for the create service account credentials operation + AdminAPICreateServiceAccountCredentialsHandler admin_api.CreateServiceAccountCredentialsHandler + // AdminAPICreateServiceAccountCredsHandler sets the operation handler for the create service account creds operation + AdminAPICreateServiceAccountCredsHandler admin_api.CreateServiceAccountCredsHandler // AdminAPIDashboardWidgetDetailsHandler sets the operation handler for the dashboard widget details operation AdminAPIDashboardWidgetDetailsHandler admin_api.DashboardWidgetDetailsHandler // AdminAPIDeleteAccessRuleWithBucketHandler sets the operation handler for the delete access rule with bucket operation @@ -741,6 +751,12 @@ func (o *ConsoleAPI) Validate() error { if o.UserAPICreateServiceAccountHandler == nil { unregistered = append(unregistered, "user_api.CreateServiceAccountHandler") } + if o.AdminAPICreateServiceAccountCredentialsHandler == nil { + unregistered = append(unregistered, "admin_api.CreateServiceAccountCredentialsHandler") + } + if o.AdminAPICreateServiceAccountCredsHandler == nil { + unregistered = append(unregistered, "admin_api.CreateServiceAccountCredsHandler") + } if o.AdminAPIDashboardWidgetDetailsHandler == nil { unregistered = append(unregistered, "admin_api.DashboardWidgetDetailsHandler") } @@ -1149,6 +1165,14 @@ func (o *ConsoleAPI) initHandlerCache() { o.handlers["POST"] = make(map[string]http.Handler) } o.handlers["POST"]["/service-accounts"] = user_api.NewCreateServiceAccount(o.context, o.UserAPICreateServiceAccountHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/user/{name}/service-account-credentials"] = admin_api.NewCreateServiceAccountCredentials(o.context, o.AdminAPICreateServiceAccountCredentialsHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/service-account-credentials"] = admin_api.NewCreateServiceAccountCreds(o.context, o.AdminAPICreateServiceAccountCredsHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } diff --git a/restapi/user_service_accounts.go b/restapi/user_service_accounts.go index e196ff019..1faf666f5 100644 --- a/restapi/user_service_accounts.go +++ b/restapi/user_service_accounts.go @@ -19,6 +19,7 @@ package restapi import ( "bytes" "context" + "errors" "strings" "time" @@ -48,6 +49,21 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) { } return admin_api.NewCreateAUserServiceAccountCreated().WithPayload(creds) }) + // Create User Service Account + api.AdminAPICreateServiceAccountCredentialsHandler = admin_api.CreateServiceAccountCredentialsHandlerFunc(func(params admin_api.CreateServiceAccountCredentialsParams, session *models.Principal) middleware.Responder { + creds, err := getCreateAUserServiceAccountCredsResponse(session, params.Body, params.Name) + if err != nil { + return user_api.NewCreateServiceAccountDefault(int(err.Code)).WithPayload(err) + } + return admin_api.NewCreateServiceAccountCredentialsCreated().WithPayload(creds) + }) + api.AdminAPICreateServiceAccountCredsHandler = admin_api.CreateServiceAccountCredsHandlerFunc(func(params admin_api.CreateServiceAccountCredsParams, session *models.Principal) middleware.Responder { + creds, err := getCreateServiceAccountCredsResponse(session, params.Body) + if err != nil { + return user_api.NewCreateServiceAccountDefault(int(err.Code)).WithPayload(err) + } + return admin_api.NewCreateServiceAccountCredentialsCreated().WithPayload(creds) + }) // List Service Accounts for User api.UserAPIListUserServiceAccountsHandler = user_api.ListUserServiceAccountsHandlerFunc(func(params user_api.ListUserServiceAccountsParams, session *models.Principal) middleware.Responder { serviceAccounts, err := getUserServiceAccountsResponse(session, "") @@ -89,7 +105,27 @@ func createServiceAccount(ctx context.Context, userClient MinioAdmin, policy str iamPolicy = iamp } - creds, err := userClient.addServiceAccount(ctx, iamPolicy) + creds, err := userClient.addServiceAccount(ctx, iamPolicy, "", "", "") + if err != nil { + return nil, err + } + return &models.ServiceAccountCreds{AccessKey: creds.AccessKey, SecretKey: creds.SecretKey}, nil +} + +// createServiceAccount adds a service account with the given credentials to the userClient and assigns a policy to him if defined. +func createServiceAccountCreds(ctx context.Context, userClient MinioAdmin, policy string, accessKey string, secretKey string) (*models.ServiceAccountCreds, error) { + // By default a nil policy will be used so the service account inherit the parent account policy, otherwise + // we override with the user provided iam policy + var iamPolicy *iampolicy.Policy + if strings.TrimSpace(policy) != "" { + iamp, err := iampolicy.ParseConfig(bytes.NewReader([]byte(policy))) + if err != nil { + return nil, err + } + iamPolicy = iamp + } + + creds, err := userClient.addServiceAccount(ctx, iamPolicy, "", accessKey, secretKey) if err != nil { return nil, err } @@ -118,7 +154,7 @@ func getCreateServiceAccountResponse(session *models.Principal, serviceAccount * return saCreds, nil } -// createServiceAccount adds a service account to the userClient and assigns a policy to him if defined. +// createServiceAccount adds a service account to a given user and assigns a policy to him if defined. func createAUserServiceAccount(ctx context.Context, userClient MinioAdmin, policy string, user string) (*models.ServiceAccountCreds, error) { // By default a nil policy will be used so the service account inherit the parent account policy, otherwise // we override with the user provided iam policy @@ -131,7 +167,26 @@ func createAUserServiceAccount(ctx context.Context, userClient MinioAdmin, polic iamPolicy = iamp } - creds, err := userClient.addServiceAccountWithUser(ctx, iamPolicy, user) + creds, err := userClient.addServiceAccount(ctx, iamPolicy, user, "", "") + if err != nil { + return nil, err + } + return &models.ServiceAccountCreds{AccessKey: creds.AccessKey, SecretKey: creds.SecretKey}, nil +} + +func createAUserServiceAccountCreds(ctx context.Context, userClient MinioAdmin, policy string, user string, accessKey string, secretKey string) (*models.ServiceAccountCreds, error) { + // By default a nil policy will be used so the service account inherit the parent account policy, otherwise + // we override with the user provided iam policy + var iamPolicy *iampolicy.Policy + if strings.TrimSpace(policy) != "" { + iamp, err := iampolicy.ParseConfig(bytes.NewReader([]byte(policy))) + if err != nil { + return nil, err + } + iamPolicy = iamp + } + + creds, err := userClient.addServiceAccount(ctx, iamPolicy, user, accessKey, secretKey) if err != nil { return nil, err } @@ -139,7 +194,7 @@ func createAUserServiceAccount(ctx context.Context, userClient MinioAdmin, polic } // 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 +// is requesting it ,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 getCreateAUserServiceAccountResponse(session *models.Principal, serviceAccount *models.ServiceAccountRequest, user string) (*models.ServiceAccountCreds, *models.Error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) @@ -160,6 +215,76 @@ func getCreateAUserServiceAccountResponse(session *models.Principal, serviceAcco return saCreds, nil } +// getCreateServiceAccountCredsResponse creates a service account with the defined policy for the user that +// is requesting it, and with the credentials provided +func getCreateAUserServiceAccountCredsResponse(session *models.Principal, serviceAccount *models.ServiceAccountRequestCreds, user string) (*models.ServiceAccountCreds, *models.Error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + + userAdmin, err := NewMinioAdminClient(session) + if err != nil { + return nil, prepareError(err) + } + // create a MinIO user Admin Client interface implementation + // defining the client to be used + userAdminClient := AdminClient{Client: userAdmin} + + if user == serviceAccount.AccessKey { + return nil, prepareError(errors.New("Access Key already in use")) + } + + accounts, err := userAdminClient.listServiceAccounts(ctx, user) + if err != nil { + return nil, prepareError(err) + } + + for i := 0; i < len(accounts.Accounts); i++ { + if accounts.Accounts[i] == serviceAccount.AccessKey { + return nil, prepareError(errors.New("Access Key already in use")) + } + } + + saCreds, err := createAUserServiceAccountCreds(ctx, userAdminClient, serviceAccount.Policy, user, serviceAccount.AccessKey, serviceAccount.SecretKey) + if err != nil { + return nil, prepareError(err) + } + return saCreds, nil +} + +func getCreateServiceAccountCredsResponse(session *models.Principal, serviceAccount *models.ServiceAccountRequestCreds) (*models.ServiceAccountCreds, *models.Error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + + userAdmin, err := NewMinioAdminClient(session) + if err != nil { + return nil, prepareError(err) + } + // create a MinIO user Admin Client interface implementation + // defining the client to be used + userAdminClient := AdminClient{Client: userAdmin} + + if session.AccountAccessKey == serviceAccount.AccessKey { + return nil, prepareError(errors.New("Access Key already in use")) + } + + accounts, err := userAdminClient.listServiceAccounts(ctx, "") + if err != nil { + return nil, prepareError(err) + } + + for i := 0; i < len(accounts.Accounts); i++ { + if accounts.Accounts[i] == serviceAccount.AccessKey { + return nil, prepareError(errors.New("Access Key already in use")) + } + } + + saCreds, err := createServiceAccountCreds(ctx, userAdminClient, serviceAccount.Policy, serviceAccount.AccessKey, serviceAccount.SecretKey) + if err != nil { + return nil, prepareError(err) + } + return saCreds, nil +} + // getUserServiceAccount gets list of the user's service accounts func getUserServiceAccounts(ctx context.Context, userClient MinioAdmin, user string) (models.ServiceAccounts, error) { listServAccs, err := userClient.listServiceAccounts(ctx, user) diff --git a/restapi/user_service_accounts_test.go b/restapi/user_service_accounts_test.go index 6509efae5..b8cc00819 100644 --- a/restapi/user_service_accounts_test.go +++ b/restapi/user_service_accounts_test.go @@ -29,18 +29,13 @@ import ( ) // assigning mock at runtime instead of compile time -var minioAddServiceAccountMock func(ctx context.Context, policy *iampolicy.Policy) (madmin.Credentials, error) -var minioAddServiceAccountWithUserMock func(ctx context.Context, policy *iampolicy.Policy, user string) (madmin.Credentials, error) +var minioAddServiceAccountMock func(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) var minioListServiceAccountsMock func(ctx context.Context, user string) (madmin.ListServiceAccountsResp, error) var minioDeleteServiceAccountMock func(ctx context.Context, serviceAccount string) error // mock function of AddServiceAccount() -func (ac adminClientMock) addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (madmin.Credentials, error) { - return minioAddServiceAccountMock(ctx, policy) -} - -func (ac adminClientMock) addServiceAccountWithUser(ctx context.Context, policy *iampolicy.Policy, user string) (madmin.Credentials, error) { - return minioAddServiceAccountWithUserMock(ctx, policy, user) +func (ac adminClientMock) addServiceAccount(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) { + return minioAddServiceAccountMock(ctx, policy, user, accessKey, secretKey) } // mock function of ListServiceAccounts() @@ -65,7 +60,7 @@ func TestAddServiceAccount(t *testing.T) { AccessKey: "minio", SecretKey: "minio123", } - minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy) (madmin.Credentials, error) { + minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) { return mockResponse, nil } saCreds, err := createServiceAccount(ctx, client, policyDefinition) @@ -81,7 +76,7 @@ func TestAddServiceAccount(t *testing.T) { AccessKey: "minio", SecretKey: "minio123", } - minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy) (madmin.Credentials, error) { + minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) { return mockResponse, nil } saCreds, err = createServiceAccount(ctx, client, policyDefinition) @@ -93,7 +88,7 @@ func TestAddServiceAccount(t *testing.T) { AccessKey: "minio", SecretKey: "minio123", } - minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy) (madmin.Credentials, error) { + minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string) (madmin.Credentials, error) { return madmin.Credentials{}, errors.New("error") } _, err = createServiceAccount(ctx, client, policyDefinition) diff --git a/swagger-console.yml b/swagger-console.yml index d028d63b6..031cfaa61 100644 --- a/swagger-console.yml +++ b/swagger-console.yml @@ -1123,6 +1123,28 @@ paths: tags: - UserAPI + /service-account-credentials: + post: + summary: Create Service Account With Credentials + operationId: CreateServiceAccountCreds + parameters: + - name: body + in: body + required: true + schema: + $ref: "#/definitions/serviceAccountRequestCreds" + responses: + 201: + description: A successful response. + schema: + $ref: "#/definitions/serviceAccountCreds" + default: + description: Generic error response. + schema: + $ref: "#/definitions/error" + tags: + - AdminAPI + /service-accounts/{access_key}: delete: summary: Delete Service Account @@ -1344,6 +1366,32 @@ paths: tags: - AdminAPI + /user/{name}/service-account-credentials: + post: + summary: Create Service Account for User With Credentials + operationId: CreateServiceAccountCredentials + parameters: + - name: name + in: path + required: true + type: string + - name: body + in: body + required: true + schema: + $ref: "#/definitions/serviceAccountRequestCreds" + responses: + 201: + description: A successful response. + schema: + $ref: "#/definitions/serviceAccountCreds" + default: + description: Generic error response. + schema: + $ref: "#/definitions/error" + tags: + - AdminAPI + /users-groups-bulk: put: summary: Bulk functionality to Add Users to Groups @@ -3230,6 +3278,16 @@ definitions: policy: type: string title: "policy to be applied to the Service Account if any" + serviceAccountRequestCreds: + type: object + properties: + policy: + type: string + title: "policy to be applied to the Service Account if any" + accessKey: + type: string + secretKey: + type: string serviceAccountCreds: type: object properties: