Validate requests to logSearchApi endpoint (#1375)

- Previously any user with a validate session in console could query the
  `/api/v1/logs/search` endpoint which was not ideal, now we are
  limiting that to users with the `admin:OBDInfo` iam action
- Removing deprecated `has-permission` endpoint and backend code

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
This commit is contained in:
Lenin Alevski
2022-01-11 13:08:30 -06:00
committed by GitHub
parent c90094e328
commit 5ee3ef4fe4
15 changed files with 29 additions and 1167 deletions

View File

@@ -1,129 +0,0 @@
// 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"
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// HasPermissionRequest has permission request
//
// swagger:model hasPermissionRequest
type HasPermissionRequest struct {
// actions
Actions []*PolicyArgs `json:"actions"`
}
// Validate validates this has permission request
func (m *HasPermissionRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateActions(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *HasPermissionRequest) validateActions(formats strfmt.Registry) error {
if swag.IsZero(m.Actions) { // not required
return nil
}
for i := 0; i < len(m.Actions); i++ {
if swag.IsZero(m.Actions[i]) { // not required
continue
}
if m.Actions[i] != nil {
if err := m.Actions[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("actions" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// ContextValidate validate this has permission request based on the context it is used
func (m *HasPermissionRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateActions(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *HasPermissionRequest) contextValidateActions(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Actions); i++ {
if m.Actions[i] != nil {
if err := m.Actions[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("actions" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *HasPermissionRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *HasPermissionRequest) UnmarshalBinary(b []byte) error {
var res HasPermissionRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -1,129 +0,0 @@
// 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"
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// HasPermissionResponse has permission response
//
// swagger:model hasPermissionResponse
type HasPermissionResponse struct {
// permissions
Permissions []*PermissionAction `json:"permissions"`
}
// Validate validates this has permission response
func (m *HasPermissionResponse) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validatePermissions(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *HasPermissionResponse) validatePermissions(formats strfmt.Registry) error {
if swag.IsZero(m.Permissions) { // not required
return nil
}
for i := 0; i < len(m.Permissions); i++ {
if swag.IsZero(m.Permissions[i]) { // not required
continue
}
if m.Permissions[i] != nil {
if err := m.Permissions[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("permissions" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// ContextValidate validate this has permission response based on the context it is used
func (m *HasPermissionResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidatePermissions(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *HasPermissionResponse) contextValidatePermissions(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Permissions); i++ {
if m.Permissions[i] != nil {
if err := m.Permissions[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("permissions" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *HasPermissionResponse) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *HasPermissionResponse) UnmarshalBinary(b []byte) error {
var res HasPermissionResponse
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -1,70 +0,0 @@
// 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/strfmt"
"github.com/go-openapi/swag"
)
// PermissionAction permission action
//
// swagger:model permissionAction
type PermissionAction struct {
// can
Can bool `json:"can,omitempty"`
// id
ID string `json:"id,omitempty"`
}
// Validate validates this permission action
func (m *PermissionAction) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this permission action based on context it is used
func (m *PermissionAction) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *PermissionAction) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *PermissionAction) UnmarshalBinary(b []byte) error {
var res PermissionAction
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -45,6 +45,8 @@ var (
// TLSRedirect console tls redirect rule
TLSRedirect = "on"
ConsoleResourceName = "console-ui"
)
func getMinIOServer() string {
@@ -87,12 +89,6 @@ func GetPort() int {
return port
}
// GetTLSHostname gets console tls hostname set on env variable
// or default one
func GetTLSHostname() string {
return strings.ToLower(env.Get(ConsoleTLSHostname, Hostname))
}
// GetTLSPort gets console tls port set on env variable
// or default one
func GetTLSPort() int {

View File

@@ -2326,39 +2326,6 @@ func init() {
}
}
},
"/has-permission": {
"post": {
"tags": [
"UserAPI"
],
"summary": "Checks whether the user can perform a series of actions",
"operationId": "HasPermissionTo",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/hasPermissionRequest"
}
}
],
"responses": {
"201": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/hasPermissionResponse"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/list-external-buckets": {
"post": {
"tags": [
@@ -4235,28 +4202,6 @@ func init() {
}
}
},
"hasPermissionRequest": {
"type": "object",
"properties": {
"actions": {
"type": "array",
"items": {
"$ref": "#/definitions/policyArgs"
}
}
}
},
"hasPermissionResponse": {
"type": "object",
"properties": {
"permissions": {
"type": "array",
"items": {
"$ref": "#/definitions/permissionAction"
}
}
}
},
"iamEntity": {
"type": "string",
"pattern": "^[\\w+=,.@-]{1,64}$"
@@ -4873,17 +4818,6 @@ func init() {
"years"
]
},
"permissionAction": {
"type": "object",
"properties": {
"can": {
"type": "boolean"
},
"id": {
"type": "string"
}
}
},
"policy": {
"type": "object",
"properties": {
@@ -8103,39 +8037,6 @@ func init() {
}
}
},
"/has-permission": {
"post": {
"tags": [
"UserAPI"
],
"summary": "Checks whether the user can perform a series of actions",
"operationId": "HasPermissionTo",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/hasPermissionRequest"
}
}
],
"responses": {
"201": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/hasPermissionResponse"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/error"
}
}
}
}
},
"/list-external-buckets": {
"post": {
"tags": [
@@ -10132,28 +10033,6 @@ func init() {
}
}
},
"hasPermissionRequest": {
"type": "object",
"properties": {
"actions": {
"type": "array",
"items": {
"$ref": "#/definitions/policyArgs"
}
}
}
},
"hasPermissionResponse": {
"type": "object",
"properties": {
"permissions": {
"type": "array",
"items": {
"$ref": "#/definitions/permissionAction"
}
}
}
},
"iamEntity": {
"type": "string",
"pattern": "^[\\w+=,.@-]{1,64}$"
@@ -10770,17 +10649,6 @@ func init() {
"years"
]
},
"permissionAction": {
"type": "object",
"properties": {
"can": {
"type": "boolean"
},
"id": {
"type": "string"
}
}
},
"policy": {
"type": "object",
"properties": {

View File

@@ -203,9 +203,6 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
AdminAPIGroupInfoHandler: admin_api.GroupInfoHandlerFunc(func(params admin_api.GroupInfoParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.GroupInfo has not yet been implemented")
}),
UserAPIHasPermissionToHandler: user_api.HasPermissionToHandlerFunc(func(params user_api.HasPermissionToParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.HasPermissionTo has not yet been implemented")
}),
AdminAPIListAUserServiceAccountsHandler: admin_api.ListAUserServiceAccountsHandlerFunc(func(params admin_api.ListAUserServiceAccountsParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ListAUserServiceAccounts has not yet been implemented")
}),
@@ -515,8 +512,6 @@ type ConsoleAPI struct {
AdminAPIGetUserInfoHandler admin_api.GetUserInfoHandler
// AdminAPIGroupInfoHandler sets the operation handler for the group info operation
AdminAPIGroupInfoHandler admin_api.GroupInfoHandler
// UserAPIHasPermissionToHandler sets the operation handler for the has permission to operation
UserAPIHasPermissionToHandler user_api.HasPermissionToHandler
// AdminAPIListAUserServiceAccountsHandler sets the operation handler for the list a user service accounts operation
AdminAPIListAUserServiceAccountsHandler admin_api.ListAUserServiceAccountsHandler
// AdminAPIListAccessRulesWithBucketHandler sets the operation handler for the list access rules with bucket operation
@@ -850,9 +845,6 @@ func (o *ConsoleAPI) Validate() error {
if o.AdminAPIGroupInfoHandler == nil {
unregistered = append(unregistered, "admin_api.GroupInfoHandler")
}
if o.UserAPIHasPermissionToHandler == nil {
unregistered = append(unregistered, "user_api.HasPermissionToHandler")
}
if o.AdminAPIListAUserServiceAccountsHandler == nil {
unregistered = append(unregistered, "admin_api.ListAUserServiceAccountsHandler")
}
@@ -1301,10 +1293,6 @@ func (o *ConsoleAPI) initHandlerCache() {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/group"] = admin_api.NewGroupInfo(o.context, o.AdminAPIGroupInfoHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
}
o.handlers["POST"]["/has-permission"] = user_api.NewHasPermissionTo(o.context, o.UserAPIHasPermissionToHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}

View File

@@ -1,88 +0,0 @@
// 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"
)
// HasPermissionToHandlerFunc turns a function with the right signature into a has permission to handler
type HasPermissionToHandlerFunc func(HasPermissionToParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn HasPermissionToHandlerFunc) Handle(params HasPermissionToParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// HasPermissionToHandler interface for that can handle valid has permission to params
type HasPermissionToHandler interface {
Handle(HasPermissionToParams, *models.Principal) middleware.Responder
}
// NewHasPermissionTo creates a new http.Handler for the has permission to operation
func NewHasPermissionTo(ctx *middleware.Context, handler HasPermissionToHandler) *HasPermissionTo {
return &HasPermissionTo{Context: ctx, Handler: handler}
}
/* HasPermissionTo swagger:route POST /has-permission UserAPI hasPermissionTo
Checks whether the user can perform a series of actions
*/
type HasPermissionTo struct {
Context *middleware.Context
Handler HasPermissionToHandler
}
func (o *HasPermissionTo) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
*r = *rCtx
}
var Params = NewHasPermissionToParams()
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

@@ -1,102 +0,0 @@
// 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/validate"
"github.com/minio/console/models"
)
// NewHasPermissionToParams creates a new HasPermissionToParams object
//
// There are no default values defined in the spec.
func NewHasPermissionToParams() HasPermissionToParams {
return HasPermissionToParams{}
}
// HasPermissionToParams contains all the bound params for the has permission to operation
// typically these are obtained from a http.Request
//
// swagger:parameters HasPermissionTo
type HasPermissionToParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*
Required: true
In: body
*/
Body *models.HasPermissionRequest
}
// 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 NewHasPermissionToParams() beforehand.
func (o *HasPermissionToParams) 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.HasPermissionRequest
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
}

View File

@@ -1,133 +0,0 @@
// 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"
)
// HasPermissionToCreatedCode is the HTTP code returned for type HasPermissionToCreated
const HasPermissionToCreatedCode int = 201
/*HasPermissionToCreated A successful response.
swagger:response hasPermissionToCreated
*/
type HasPermissionToCreated struct {
/*
In: Body
*/
Payload *models.HasPermissionResponse `json:"body,omitempty"`
}
// NewHasPermissionToCreated creates HasPermissionToCreated with default headers values
func NewHasPermissionToCreated() *HasPermissionToCreated {
return &HasPermissionToCreated{}
}
// WithPayload adds the payload to the has permission to created response
func (o *HasPermissionToCreated) WithPayload(payload *models.HasPermissionResponse) *HasPermissionToCreated {
o.Payload = payload
return o
}
// SetPayload sets the payload to the has permission to created response
func (o *HasPermissionToCreated) SetPayload(payload *models.HasPermissionResponse) {
o.Payload = payload
}
// WriteResponse to the client
func (o *HasPermissionToCreated) 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
}
}
}
/*HasPermissionToDefault Generic error response.
swagger:response hasPermissionToDefault
*/
type HasPermissionToDefault struct {
_statusCode int
/*
In: Body
*/
Payload *models.Error `json:"body,omitempty"`
}
// NewHasPermissionToDefault creates HasPermissionToDefault with default headers values
func NewHasPermissionToDefault(code int) *HasPermissionToDefault {
if code <= 0 {
code = 500
}
return &HasPermissionToDefault{
_statusCode: code,
}
}
// WithStatusCode adds the status to the has permission to default response
func (o *HasPermissionToDefault) WithStatusCode(code int) *HasPermissionToDefault {
o._statusCode = code
return o
}
// SetStatusCode sets the status to the has permission to default response
func (o *HasPermissionToDefault) SetStatusCode(code int) {
o._statusCode = code
}
// WithPayload adds the payload to the has permission to default response
func (o *HasPermissionToDefault) WithPayload(payload *models.Error) *HasPermissionToDefault {
o.Payload = payload
return o
}
// SetPayload sets the payload to the has permission to default response
func (o *HasPermissionToDefault) SetPayload(payload *models.Error) {
o.Payload = payload
}
// WriteResponse to the client
func (o *HasPermissionToDefault) 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

@@ -1,104 +0,0 @@
// 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"
)
// HasPermissionToURL generates an URL for the has permission to operation
type HasPermissionToURL 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 *HasPermissionToURL) WithBasePath(bp string) *HasPermissionToURL {
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 *HasPermissionToURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *HasPermissionToURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/has-permission"
_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 *HasPermissionToURL) 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 *HasPermissionToURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *HasPermissionToURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on HasPermissionToURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on HasPermissionToURL")
}
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 *HasPermissionToURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

View File

@@ -21,8 +21,6 @@ import (
"net/http"
"time"
iampolicy "github.com/minio/pkg/iam/policy"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
@@ -44,15 +42,6 @@ func registerAccountHandlers(api *operations.ConsoleAPI) {
user_api.NewLoginNoContent().WriteResponse(w, p)
})
})
// Checks if user can perform an action
api.UserAPIHasPermissionToHandler = user_api.HasPermissionToHandlerFunc(func(params user_api.HasPermissionToParams, session *models.Principal) middleware.Responder {
hasPermissionRespose, err := getUserHasPermissionsResponse(session, params)
if err != nil {
return user_api.NewHasPermissionToDefault(500).WithPayload(err)
}
// Custom response writer to update the session cookies
return user_api.NewHasPermissionToCreated().WithPayload(hasPermissionRespose)
})
}
// changePassword validate current current user password and if it's correct set the new password
@@ -101,50 +90,3 @@ func getChangePasswordResponse(session *models.Principal, params user_api.Accoun
}
return loginResponse, nil
}
func getUserHasPermissionsResponse(session *models.Principal, params user_api.HasPermissionToParams) (*models.HasPermissionResponse, *models.Error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return nil, prepareError(err)
}
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
userPolicy, err := getAccountPolicy(ctx, adminClient)
if err != nil {
return nil, prepareError(err)
}
var perms []*models.PermissionAction
for _, p := range params.Body.Actions {
canPerform := userCanDo(iampolicy.Args{
Action: iampolicy.Action(p.Action),
}, userPolicy)
perms = append(perms, &models.PermissionAction{
Can: canPerform,
ID: p.ID,
})
}
return &models.HasPermissionResponse{
Permissions: perms,
}, nil
}
func userCanDo(arg iampolicy.Args, userPolicy *iampolicy.Policy) bool {
// check in all the statements if any allows the passed action
for _, stmt := range userPolicy.Statements {
// We only care about actions to match -
// if resources match or not we do not
// care since those are dynamic entities.
if stmt.Actions.Match(arg.Action) {
return true
}
}
return false
}

View File

@@ -18,12 +18,9 @@ package restapi
import (
"context"
"encoding/json"
"errors"
"testing"
iampolicy "github.com/minio/pkg/iam/policy"
"github.com/minio/console/models"
)
@@ -109,152 +106,3 @@ func Test_changePassword(t *testing.T) {
})
}
}
func Test_useCanDo(t *testing.T) {
type args struct {
arg iampolicy.Args
userPolicy string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Create Bucket",
args: args{
arg: iampolicy.Args{
Action: "s3:CreateBucket",
},
userPolicy: `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"admin:*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}`,
},
want: true,
},
{
name: "Create Bucket, No Admin",
args: args{
arg: iampolicy.Args{
Action: "s3:CreateBucket",
},
userPolicy: `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}`,
},
want: true,
},
{
name: "Create Bucket, By Prefix",
args: args{
arg: iampolicy.Args{
Action: "s3:CreateBucket",
},
userPolicy: `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::bucket1"
]
}
]
}`,
},
want: true,
},
{
name: "Create Bucket, With Bucket Name",
args: args{
arg: iampolicy.Args{
Action: "s3:CreateBucket",
BucketName: "bucket2",
},
userPolicy: `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::bucket1"
]
}
]
}`,
},
want: true,
},
{
name: "Can't Create Bucket",
args: args{
arg: iampolicy.Args{
Action: "s3:CreateBucket",
BucketName: "bucket2",
},
userPolicy: `{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": [
"arn:aws:s3:::bucket1",
"arn:aws:s3:::bucket1/*",
"arn:aws:s3:::lkasdkljasd090901",
"arn:aws:s3:::lkasdkljasd090901/*"
]
}
]
}`,
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var pol iampolicy.Policy
if err := json.Unmarshal([]byte(tt.args.userPolicy), &pol); err != nil {
t.Errorf("Policy can't be parsed: %s", err)
}
if got := userCanDo(tt.args.arg, &pol); got != tt.want {
t.Errorf("userCanDo() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -21,19 +21,19 @@ import (
"fmt"
"net/http"
"github.com/go-openapi/swag"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/restapi/operations/user_api"
logsearchServer "github.com/minio/operator/logsearchapi/server"
iampolicy "github.com/minio/pkg/iam/policy"
)
func registerLogSearchHandlers(api *operations.ConsoleAPI) {
// log search
api.UserAPILogSearchHandler = user_api.LogSearchHandlerFunc(func(params user_api.LogSearchParams, session *models.Principal) middleware.Responder {
searchResp, err := getLogSearchResponse(params)
searchResp, err := getLogSearchResponse(session, params)
if err != nil {
return user_api.NewLogSearchDefault(int(err.Code)).WithPayload(err)
}
@@ -42,7 +42,29 @@ func registerLogSearchHandlers(api *operations.ConsoleAPI) {
}
// getLogSearchResponse performs a query to Log Search if Enabled
func getLogSearchResponse(params user_api.LogSearchParams) (*models.LogSearchResponse, *models.Error) {
func getLogSearchResponse(session *models.Principal, params user_api.LogSearchParams) (*models.LogSearchResponse, *models.Error) {
sessionResp, err := getSessionResponse(session)
if err != nil {
return nil, err
}
var allowedToQueryLogSearchAPI bool
if permissions, ok := sessionResp.Permissions[ConsoleResourceName]; ok {
for _, permission := range permissions {
if permission == iampolicy.HealthInfoAdminAction {
allowedToQueryLogSearchAPI = true
break
}
}
}
if !allowedToQueryLogSearchAPI {
return nil, &models.Error{
Code: int32(403),
Message: swag.String("Forbidden"),
DetailedMessage: swag.String("The Log Search API not available."),
}
}
token := getLogSearchAPIToken()
endpoint := fmt.Sprintf("%s/api/query?token=%s&q=reqinfo", getLogSearchURL(), token)
for _, fp := range params.Fp {

View File

@@ -148,10 +148,9 @@ func getSessionResponse(session *models.Principal) (*models.SessionResponse, *mo
}
defaultActions := policy.IsAllowedActions("", "", conditionValues)
consoleResourceName := "console-ui"
permissions := map[string]minioIAMPolicy.ActionSet{
consoleResourceName: defaultActions,
ConsoleResourceName: defaultActions,
}
deniedActions := map[string]minioIAMPolicy.ActionSet{}
for _, statement := range policy.Statements {

View File

@@ -1216,28 +1216,6 @@ paths:
tags:
- UserAPI
/has-permission:
post:
summary: Checks whether the user can perform a series of actions
operationId: HasPermissionTo
parameters:
- name: body
in: body
required: true
schema:
$ref: "#/definitions/hasPermissionRequest"
responses:
201:
description: A successful response.
schema:
$ref: "#/definitions/hasPermissionResponse"
default:
description: Generic error response.
schema:
$ref: "#/definitions/error"
tags:
- UserAPI
/users:
get:
summary: List Users
@@ -3779,30 +3757,6 @@ definitions:
bucket_name:
type: string
hasPermissionRequest:
type: object
properties:
actions:
type: array
items:
$ref: "#/definitions/policyArgs"
permissionAction:
type: object
properties:
id:
type: string
can:
type: boolean
hasPermissionResponse:
type: object
properties:
permissions:
type: array
items:
$ref: "#/definitions/permissionAction"
tier_s3:
type: object
properties: