Refactor for session management (#193)

Previously every Handler function was receiving the session token in the
form of a jwt string, in consequence every time we want to access the
encrypted claims of the jwt we needed to run a decryption process,
additionally we were decrypting the jwt twice, first at the session
validation then inside each handler function, this was also causing a
lot of using related to the merge between m3 and mcs

What changed:

Now we validate and decrypt the jwt once in `configure_mcs.go`, this
works for both, mcs (console) and operator sessions, and then pass the
decrypted claims to all the functions that need it, so no further token
validation or decryption is need it.
This commit is contained in:
Lenin Alevski
2020-07-10 19:14:28 -07:00
committed by GitHub
parent 93e1168141
commit 697bc4cd1d
34 changed files with 618 additions and 605 deletions

View File

@@ -59,3 +59,6 @@ clean:
@find . -name '*.test' | xargs rm -fv
@find . -name '*~' | xargs rm -fv
@rm -vf mcs
docker:
@docker build -t $(TAG) --build-arg build_version=$(BUILD_VERSION) --build-arg build_time='$(BUILD_TIME)' .

View File

@@ -23,15 +23,28 @@ import (
certutil "k8s.io/client-go/util/cert"
)
func GetK8sConfig(token string) *rest.Config {
// if console is running inside k8s by default he will have access to the ca cert from the k8s local authority
const (
rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
)
tlsClientConfig := rest.TLSClientConfig{Insecure: getK8sAPIServerInsecure()}
if _, err := certutil.NewPool(rootCAFile); err == nil {
tlsClientConfig.CAFile = rootCAFile
// getTLSClientConfig will return the right TLS configuration for the K8S client based on the configured TLS certificate
func getTLSClientConfig() rest.TLSClientConfig {
var defaultRootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
var customRootCAFile = getK8sAPIServerTLSRootCA()
tlsClientConfig := rest.TLSClientConfig{}
// if console is running inside k8s by default he will have access to the CA Cert from the k8s local authority
if _, err := certutil.NewPool(defaultRootCAFile); err == nil {
tlsClientConfig.CAFile = defaultRootCAFile
}
// if the user explicitly define a custom CA certificate, instead, we will use that
if customRootCAFile != "" {
if _, err := certutil.NewPool(customRootCAFile); err == nil {
tlsClientConfig.CAFile = customRootCAFile
}
}
return tlsClientConfig
}
// This operation will run only once at console startup
var tlsClientConfig = getTLSClientConfig()
func GetK8sConfig(token string) *rest.Config {
config := &rest.Config{
Host: GetK8sAPIServer(),
TLSClientConfig: tlsClientConfig,

View File

@@ -48,10 +48,10 @@ func GetK8sAPIServer() string {
return env.Get(McsK8sAPIServer, apiServerAddress)
}
// getK8sAPIServerInsecure allow to tell the k8s client to skip TLS certificate verification, ie: when connecting to a k8s cluster
// that uses certificate not trusted by your machine
func getK8sAPIServerInsecure() bool {
return strings.ToLower(env.Get(McsK8SAPIServerInsecure, "off")) == "on"
// If MCS_K8S_API_SERVER_TLS_ROOT_CA is true mcs will load the certificate into the
// http.client rootCAs pool, this is useful for testing an k8s ApiServer or when working with self-signed certificates
func getK8sAPIServerTLSRootCA() string {
return strings.TrimSpace(env.Get(McsK8SAPIServerTLSRootCA, ""))
}
// GetNsFromFile assumes console is running inside a k8s pod and extract the current namespace from the

View File

@@ -17,9 +17,9 @@
package cluster
const (
McsK8sAPIServer = "MCS_K8S_API_SERVER"
McsK8SAPIServerInsecure = "MCS_K8S_API_SERVER_INSECURE"
McsMinioImage = "MCS_MINIO_IMAGE"
McsMCImage = "MCS_MC_IMAGE"
McsNamespace = "MCS_NAMESPACE"
McsK8sAPIServer = "MCS_K8S_API_SERVER"
McsK8SAPIServerTLSRootCA = "MCS_K8S_API_SERVER_TLS_ROOT_CA"
McsMinioImage = "MCS_MINIO_IMAGE"
McsMCImage = "MCS_MC_IMAGE"
McsNamespace = "MCS_NAMESPACE"
)

39
docs/mcs_operator_mode.md Normal file
View File

@@ -0,0 +1,39 @@
# Running MCS in Operator mode
`MCS` will authenticate against `Kubernetes`using bearer tokens via HTTP `Authorization` header. The user will provide this token once
in the login form, MCS will validate it against Kubernetes (list apis) and if valid will generate and return a new MCS sessions
with encrypted claims (the user Service account token will be inside the JWT in the data field)
# Kubernetes
The provided `JWT token` corresponds to the `Kubernetes service account` that `MCS` will use to run tasks on behalf of the
user, ie: list, create, edit, delete tenants, storage class, etc.
# Development
If console is running inside a k8s pod `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` will contain the k8s api server apiServerAddress
if console is not running inside k8s by default will look for the k8s api server on `localhost:8001` (kubectl proxy)
If you are running mcs in your local environment and wish to make request to `Kubernetes` you can set `MCS_K8S_API_SERVER`, if
the environment variable is not present by default `MCS` will use `"http://localhost:8001"`, additionally you will need to set the
`MCS_OPERATOR_MODE=on` variable to make MCS display the Operator UI.
NOTE: using `kubectl` proxy is for local development only, since every request send to localhost:8001 will bypass service account authentication
more info here: https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#directly-accessing-the-rest-api
you can override this using `MCS_K8S_API_SERVER`, ie use the k8s cluster from `kubectl config view`
## Extract the Service account token and use it with MCS
For local development you can use the jwt associated to the `m3-sa` service account, you can get the token running
the following command in your terminal:
```
kubectl get secret $(kubectl get serviceaccount mcs-sa -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64 --decode
```
Then run the mcs server
```
MCS_OPERATOR_MODE=on ./mcs server
```

View File

@@ -1,40 +0,0 @@
# MCS service account authentication with Mkube
`MCS` will authenticate against `Mkube`using bearer tokens via HTTP `Authorization` header. The user will provide this token once
in the login form, MCS will validate it against Mkube (list tenants) and if valid will generate and return a new MCS sessions
with encrypted claims (the user Service account token will be inside the JWT in the data field)
# Kubernetes
The provided `JWT token` corresponds to the `Kubernetes service account` that `Mkube` will use to run tasks on behalf of the
user, ie: list, create, edit, delete tenants, storage class, etc.
# Development
If you are running mcs in your local environment and wish to make request to `Mkube` you can set `MCS_M3_HOSTNAME`, if
the environment variable is not present by default `MCS` will use `"http://m3:8787"`, additionally you will need to set the
`MCS_MKUBE_ADMIN_ONLY=on` variable to make MCS display the Mkube UI
## Extract the Service account token and use it with MCS
For local development you can use the jwt associated to the `m3-sa` service account, you can get the token running
the following command in your terminal:
```
kubectl get secret $(kubectl get serviceaccount m3-sa -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64 --decode
```
Then run the mcs server
```
MCS_M3_HOSTNAME=http://localhost:8787 MCS_MKUBE_ADMIN_ONLY=on ./mcs server
```
# Self-signed certificates and Custom certificate authority for Mkube
If Mkube uses TLS with a self-signed certificate, or a certificate issued by a custom certificate authority you can add those
certificates usinng the `MCS_M3_SERVER_TLS_CA_CERTIFICATE` env variable
````
MCS_M3_SERVER_TLS_CA_CERTIFICATE=cert1.pem,cert2.pem,cert3.pem ./mcs server
````

View File

@@ -24,14 +24,46 @@ package models
import (
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// Principal principal
//
// swagger:model principal
type Principal string
type Principal struct {
// access key ID
AccessKeyID string `json:"accessKeyID,omitempty"`
// actions
Actions []string `json:"actions"`
// secret access key
SecretAccessKey string `json:"secretAccessKey,omitempty"`
// session token
SessionToken string `json:"sessionToken,omitempty"`
}
// Validate validates this principal
func (m Principal) Validate(formats strfmt.Registry) error {
func (m *Principal) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *Principal) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *Principal) UnmarshalBinary(b []byte) error {
var res Principal
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -32,6 +32,7 @@ import (
jwtgo "github.com/dgrijalva/jwt-go"
"github.com/go-openapi/swag"
"github.com/minio/mcs/models"
xjwt "github.com/minio/mcs/pkg/auth/jwt"
"github.com/minio/minio-go/v6/pkg/credentials"
uuid "github.com/satori/go.uuid"
@@ -210,7 +211,7 @@ func GetTokenFromRequest(r *http.Request) (*string, error) {
return swag.String(reqToken), nil
}
func GetClaimsFromTokenInRequest(req *http.Request) (*DecryptedClaims, error) {
func GetClaimsFromTokenInRequest(req *http.Request) (*models.Principal, error) {
sessionID, err := GetTokenFromRequest(req)
if err != nil {
return nil, err
@@ -221,5 +222,10 @@ func GetClaimsFromTokenInRequest(req *http.Request) (*DecryptedClaims, error) {
if err != nil {
return nil, err
}
return claims, nil
return &models.Principal{
AccessKeyID: claims.AccessKeyID,
Actions: claims.Actions,
SecretAccessKey: claims.SecretAccessKey,
SessionToken: claims.SessionToken,
}, nil
}

View File

@@ -1,77 +0,0 @@
package auth
import (
"bytes"
"errors"
"io/ioutil"
"net/http"
"testing"
)
// RoundTripFunc .
type RoundTripFunc func(req *http.Request) (*http.Response, error)
// RoundTrip .
func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req)
}
//NewTestClient returns *http.Client with Transport replaced to avoid making real calls
func NewTestClient(fn RoundTripFunc) *http.Client {
return &http.Client{
Transport: fn,
}
}
func Test_isServiceAccountTokenValid(t *testing.T) {
successResponse := NewTestClient(func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString(`OK`)),
Header: make(http.Header),
}, nil
})
failResponse := NewTestClient(func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 500,
Body: ioutil.NopCloser(bytes.NewBufferString(`NOTOK`)),
Header: make(http.Header),
}, errors.New("something wrong")
})
type args struct {
client *http.Client
jwt string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Success authentication - correct jwt (service account token)",
args: args{
client: successResponse,
jwt: "GOODTOKEN",
},
want: true,
},
{
name: "Fail authentication - incorrect jwt (service account token)",
args: args{
client: failResponse,
jwt: "BADTOKEN",
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := isServiceAccountTokenValid(tt.args.client, tt.args.jwt); got != tt.want {
t.Errorf("isServiceAccountTokenValid() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -17,12 +17,12 @@
package auth
import (
"fmt"
"context"
"log"
"net/http"
"github.com/minio/mcs/cluster"
"github.com/minio/minio-go/v6/pkg/credentials"
operatorClientset "github.com/minio/minio-operator/pkg/client/clientset/versioned"
)
// operatorCredentialsProvider is an struct to hold the JWT (service account token)
@@ -44,16 +44,31 @@ func (s operatorCredentialsProvider) IsExpired() bool {
return false
}
// isServiceAccountTokenValid will make an authenticated request (using bearer token) against kubernetes api, if the
// OperatorClient interface with all functions to be implemented
// by mock when testing, it should include all OperatorClient respective api calls
// that are used within this project.
type OperatorClient interface {
Authenticate(context.Context) ([]byte, error)
}
// Interface implementation
//
// Define the structure of a operator client and define the functions that are actually used
// from the minio-operator.
type operatorClient struct {
client *operatorClientset.Clientset
}
// Authenticate implements the operator authenticate function via REST /api
func (c *operatorClient) Authenticate(ctx context.Context) ([]byte, error) {
return c.client.RESTClient().Verb("GET").RequestURI("/api").DoRaw(ctx)
}
// isServiceAccountTokenValid will make an authenticated request against kubernetes api, if the
// request success means the provided jwt its a valid service account token and the MCS user can use it for future
// requests until it fails
func isServiceAccountTokenValid(client *http.Client, jwt string) bool {
//# Explore the API with TOKEN
//curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
apiURL := fmt.Sprintf("%s/api", cluster.GetK8sAPIServer())
req, _ := http.NewRequest("GET", apiURL, nil)
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", jwt))
_, err := client.Do(req)
// requests until it expires
func isServiceAccountTokenValid(ctx context.Context, operatorClient OperatorClient) bool {
_, err := operatorClient.Authenticate(ctx)
if err != nil {
log.Println(err)
return false
@@ -63,8 +78,15 @@ func isServiceAccountTokenValid(client *http.Client, jwt string) bool {
// GetMcsCredentialsForOperator will validate the provided JWT (service account token) and return it in the form of credentials.Credentials
func GetMcsCredentialsForOperator(jwt string) (*credentials.Credentials, error) {
client := http.Client{}
if isServiceAccountTokenValid(&client, jwt) {
ctx := context.Background()
opClientClientSet, err := cluster.OperatorClient(jwt)
if err != nil {
return nil, err
}
opClient := &operatorClient{
client: opClientClientSet,
}
if isServiceAccountTokenValid(ctx, opClient) {
return credentials.New(operatorCredentialsProvider{serviceAccountJWT: jwt}), nil
}
return nil, errInvalidCredentials

82
pkg/auth/operator_test.go Normal file
View File

@@ -0,0 +1,82 @@
package auth
import (
"context"
"errors"
"testing"
"github.com/minio/mcs/cluster"
operatorClientset "github.com/minio/minio-operator/pkg/client/clientset/versioned"
)
type operatorClientTest struct {
client *operatorClientset.Clientset
}
var operatorAuthenticateMock func(ctx context.Context) ([]byte, error)
// MinIOInstanceDelete implements the minio instance delete action from minio-operator
func (c *operatorClientTest) Authenticate(ctx context.Context) ([]byte, error) {
return operatorAuthenticateMock(ctx)
}
func Test_isServiceAccountTokenValid(t *testing.T) {
successResponse := func() {
operatorAuthenticateMock = func(ctx context.Context) ([]byte, error) {
return nil, nil
}
}
failResponse := func() {
operatorAuthenticateMock = func(ctx context.Context) ([]byte, error) {
return nil, errors.New("something went wrong")
}
}
opClientClientSet, _ := cluster.OperatorClient("")
opClient := &operatorClientTest{
client: opClientClientSet,
}
type args struct {
ctx context.Context
operatorClient *operatorClientTest
mockFunction func()
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Success authentication - correct jwt (service account token)",
args: args{
ctx: context.Background(),
operatorClient: opClient,
mockFunction: successResponse,
},
want: true,
},
{
name: "Fail authentication - incorrect jwt (service account token)",
args: args{
ctx: context.Background(),
operatorClient: opClient,
mockFunction: failResponse,
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.mockFunction != nil {
tt.args.mockFunction()
}
if got := isServiceAccountTokenValid(tt.args.ctx, tt.args.operatorClient); got != tt.want {
t.Errorf("isServiceAccountTokenValid() = %v, want %v", got, tt.want)
}
})
}
}

File diff suppressed because one or more lines are too long

View File

@@ -30,9 +30,8 @@ import (
func registerAdminArnsHandlers(api *operations.McsAPI) {
// return a list of arns
api.AdminAPIArnListHandler = admin_api.ArnListHandlerFunc(func(params admin_api.ArnListParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
arnsResp, err := getArnsResponse(sessionID)
api.AdminAPIArnListHandler = admin_api.ArnListHandlerFunc(func(params admin_api.ArnListParams, session *models.Principal) middleware.Responder {
arnsResp, err := getArnsResponse(session)
if err != nil {
return admin_api.NewArnListDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -54,8 +53,8 @@ func getArns(ctx context.Context, client MinioAdmin) (*models.ArnsResponse, erro
}
// getArnsResponse returns a list of active arns in the instance
func getArnsResponse(sessionID string) (*models.ArnsResponse, error) {
mAdmin, err := newMAdminClient(sessionID)
func getArnsResponse(session *models.Principal) (*models.ArnsResponse, error) {
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err

View File

@@ -33,27 +33,24 @@ import (
func registerConfigHandlers(api *operations.McsAPI) {
// List Configurations
api.AdminAPIListConfigHandler = admin_api.ListConfigHandlerFunc(func(params admin_api.ListConfigParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
configListResp, err := getListConfigResponse(sessionID)
api.AdminAPIListConfigHandler = admin_api.ListConfigHandlerFunc(func(params admin_api.ListConfigParams, session *models.Principal) middleware.Responder {
configListResp, err := getListConfigResponse(session)
if err != nil {
return admin_api.NewListConfigDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewListConfigOK().WithPayload(configListResp)
})
// Configuration Info
api.AdminAPIConfigInfoHandler = admin_api.ConfigInfoHandlerFunc(func(params admin_api.ConfigInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
config, err := getConfigResponse(sessionID, params)
api.AdminAPIConfigInfoHandler = admin_api.ConfigInfoHandlerFunc(func(params admin_api.ConfigInfoParams, session *models.Principal) middleware.Responder {
config, err := getConfigResponse(session, params)
if err != nil {
return admin_api.NewConfigInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewConfigInfoOK().WithPayload(config)
})
// Set Configuration
api.AdminAPISetConfigHandler = admin_api.SetConfigHandlerFunc(func(params admin_api.SetConfigParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := setConfigResponse(sessionID, params.Name, params.Body); err != nil {
api.AdminAPISetConfigHandler = admin_api.SetConfigHandlerFunc(func(params admin_api.SetConfigParams, session *models.Principal) middleware.Responder {
if err := setConfigResponse(session, params.Name, params.Body); err != nil {
return admin_api.NewSetConfigDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewSetConfigNoContent()
@@ -79,8 +76,8 @@ func listConfig(client MinioAdmin) ([]*models.ConfigDescription, error) {
}
// getListConfigResponse performs listConfig() and serializes it to the handler's output
func getListConfigResponse(sessionID string) (*models.ListConfigResponse, error) {
mAdmin, err := newMAdminClient(sessionID)
func getListConfigResponse(session *models.Principal) (*models.ListConfigResponse, error) {
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -130,8 +127,8 @@ func getConfig(client MinioAdmin, name string) ([]*models.ConfigurationKV, error
}
// getConfigResponse performs getConfig() and serializes it to the handler's output
func getConfigResponse(sessionID string, params admin_api.ConfigInfoParams) (*models.Configuration, error) {
mAdmin, err := newMAdminClient(sessionID)
func getConfigResponse(session *models.Principal, params admin_api.ConfigInfoParams) (*models.Configuration, error) {
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -183,8 +180,8 @@ func buildConfig(configName *string, kvs []*models.ConfigurationKV) *string {
}
// setConfigResponse implements setConfig() to be used by handler
func setConfigResponse(sessionID string, name string, configRequest *models.SetConfigRequest) error {
mAdmin, err := newMAdminClient(sessionID)
func setConfigResponse(session *models.Principal, name string, configRequest *models.SetConfigRequest) error {
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err

View File

@@ -33,43 +33,38 @@ import (
func registerGroupsHandlers(api *operations.McsAPI) {
// List Groups
api.AdminAPIListGroupsHandler = admin_api.ListGroupsHandlerFunc(func(params admin_api.ListGroupsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
listGroupsResponse, err := getListGroupsResponse(sessionID)
api.AdminAPIListGroupsHandler = admin_api.ListGroupsHandlerFunc(func(params admin_api.ListGroupsParams, session *models.Principal) middleware.Responder {
listGroupsResponse, err := getListGroupsResponse(session)
if err != nil {
return admin_api.NewListGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewListGroupsOK().WithPayload(listGroupsResponse)
})
// Group Info
api.AdminAPIGroupInfoHandler = admin_api.GroupInfoHandlerFunc(func(params admin_api.GroupInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
groupInfo, err := getGroupInfoResponse(sessionID, params)
api.AdminAPIGroupInfoHandler = admin_api.GroupInfoHandlerFunc(func(params admin_api.GroupInfoParams, session *models.Principal) middleware.Responder {
groupInfo, err := getGroupInfoResponse(session, params)
if err != nil {
return admin_api.NewGroupInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewGroupInfoOK().WithPayload(groupInfo)
})
// Add Group
api.AdminAPIAddGroupHandler = admin_api.AddGroupHandlerFunc(func(params admin_api.AddGroupParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getAddGroupResponse(sessionID, params.Body); err != nil {
api.AdminAPIAddGroupHandler = admin_api.AddGroupHandlerFunc(func(params admin_api.AddGroupParams, session *models.Principal) middleware.Responder {
if err := getAddGroupResponse(session, params.Body); err != nil {
return admin_api.NewAddGroupDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewAddGroupCreated()
})
// Remove Group
api.AdminAPIRemoveGroupHandler = admin_api.RemoveGroupHandlerFunc(func(params admin_api.RemoveGroupParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getRemoveGroupResponse(sessionID, params); err != nil {
api.AdminAPIRemoveGroupHandler = admin_api.RemoveGroupHandlerFunc(func(params admin_api.RemoveGroupParams, session *models.Principal) middleware.Responder {
if err := getRemoveGroupResponse(session, params); err != nil {
return admin_api.NewRemoveGroupDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewRemoveGroupNoContent()
})
// Update Group
api.AdminAPIUpdateGroupHandler = admin_api.UpdateGroupHandlerFunc(func(params admin_api.UpdateGroupParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
groupUpdateResp, err := getUpdateGroupResponse(sessionID, params)
api.AdminAPIUpdateGroupHandler = admin_api.UpdateGroupHandlerFunc(func(params admin_api.UpdateGroupParams, session *models.Principal) middleware.Responder {
groupUpdateResp, err := getUpdateGroupResponse(session, params)
if err != nil {
return admin_api.NewUpdateGroupDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -87,9 +82,9 @@ func listGroups(ctx context.Context, client MinioAdmin) (*[]string, error) {
}
// getListGroupsResponse performs listGroups() and serializes it to the handler's output
func getListGroupsResponse(sessionID string) (*models.ListGroupsResponse, error) {
func getListGroupsResponse(session *models.Principal) (*models.ListGroupsResponse, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -121,9 +116,9 @@ func groupInfo(ctx context.Context, client MinioAdmin, group string) (*madmin.Gr
}
// getGroupInfoResponse performs groupInfo() and serializes it to the handler's output
func getGroupInfoResponse(sessionID string, params admin_api.GroupInfoParams) (*models.Group, error) {
func getGroupInfoResponse(session *models.Principal, params admin_api.GroupInfoParams) (*models.Group, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -162,7 +157,7 @@ func addGroup(ctx context.Context, client MinioAdmin, group string, members []st
}
// getAddGroupResponse performs addGroup() and serializes it to the handler's output
func getAddGroupResponse(sessionID string, params *models.AddGroupRequest) error {
func getAddGroupResponse(session *models.Principal, params *models.AddGroupRequest) error {
ctx := context.Background()
// AddGroup request needed to proceed
if params == nil {
@@ -170,7 +165,7 @@ func getAddGroupResponse(sessionID string, params *models.AddGroupRequest) error
return errors.New(500, "error AddGroup body not in request")
}
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err
@@ -201,14 +196,14 @@ func removeGroup(ctx context.Context, client MinioAdmin, group string) error {
}
// getRemoveGroupResponse performs removeGroup() and serializes it to the handler's output
func getRemoveGroupResponse(sessionID string, params admin_api.RemoveGroupParams) error {
func getRemoveGroupResponse(session *models.Principal, params admin_api.RemoveGroupParams) error {
ctx := context.Background()
if params.Name == "" {
log.Println("error group name not in request")
return errors.New(500, "error group name not in request")
}
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err
@@ -281,7 +276,7 @@ func setGroupStatus(ctx context.Context, client MinioAdmin, group, status string
// getUpdateGroupResponse updates a group by adding or removing it's members depending on the request,
// also sets the group's status if status in the request is different than the current one.
// Then serializes the output to be used by the handler.
func getUpdateGroupResponse(sessionID string, params admin_api.UpdateGroupParams) (*models.Group, error) {
func getUpdateGroupResponse(session *models.Principal, params admin_api.UpdateGroupParams) (*models.Group, error) {
ctx := context.Background()
if params.Name == "" {
log.Println("error group name not in request")
@@ -294,7 +289,7 @@ func getUpdateGroupResponse(sessionID string, params admin_api.UpdateGroupParams
expectedGroupUpdate := params.Body
groupName := params.Name
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err

View File

@@ -30,9 +30,8 @@ import (
func registerAdminInfoHandlers(api *operations.McsAPI) {
// return usage stats
api.AdminAPIAdminInfoHandler = admin_api.AdminInfoHandlerFunc(func(params admin_api.AdminInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
infoResp, err := getAdminInfoResponse(sessionID)
api.AdminAPIAdminInfoHandler = admin_api.AdminInfoHandlerFunc(func(params admin_api.AdminInfoParams, session *models.Principal) middleware.Responder {
infoResp, err := getAdminInfoResponse(session)
if err != nil {
return admin_api.NewAdminInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -73,8 +72,8 @@ func getAdminInfo(ctx context.Context, client MinioAdmin) (*usageInfo, error) {
}
// getAdminInfoResponse returns the response containing total buckets, objects and usage.
func getAdminInfoResponse(sessionID string) (*models.AdminInfoResponse, error) {
mAdmin, err := newMAdminClient(sessionID)
func getAdminInfoResponse(session *models.Principal) (*models.AdminInfoResponse, error) {
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err

View File

@@ -31,18 +31,16 @@ import (
func registerAdminNotificationEndpointsHandlers(api *operations.McsAPI) {
// return a list of notification endpoints
api.AdminAPINotificationEndpointListHandler = admin_api.NotificationEndpointListHandlerFunc(func(params admin_api.NotificationEndpointListParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
notifEndpoints, err := getNotificationEndpointsResponse(sessionID)
api.AdminAPINotificationEndpointListHandler = admin_api.NotificationEndpointListHandlerFunc(func(params admin_api.NotificationEndpointListParams, session *models.Principal) middleware.Responder {
notifEndpoints, err := getNotificationEndpointsResponse(session)
if err != nil {
return admin_api.NewNotificationEndpointListDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewNotificationEndpointListOK().WithPayload(notifEndpoints)
})
// add a new notification endpoints
api.AdminAPIAddNotificationEndpointHandler = admin_api.AddNotificationEndpointHandlerFunc(func(params admin_api.AddNotificationEndpointParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
notifEndpoints, err := getAddNotificationEndpointResponse(sessionID, &params)
api.AdminAPIAddNotificationEndpointHandler = admin_api.AddNotificationEndpointHandlerFunc(func(params admin_api.AddNotificationEndpointParams, session *models.Principal) middleware.Responder {
notifEndpoints, err := getAddNotificationEndpointResponse(session, &params)
if err != nil {
return admin_api.NewAddNotificationEndpointDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -80,8 +78,8 @@ func getNotificationEndpoints(ctx context.Context, client MinioAdmin) (*models.N
}
// getNotificationEndpointsResponse returns a list of notification endpoints in the instance
func getNotificationEndpointsResponse(sessionID string) (*models.NotifEndpointResponse, error) {
mAdmin, err := newMAdminClient(sessionID)
func getNotificationEndpointsResponse(session *models.Principal) (*models.NotifEndpointResponse, error) {
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -152,8 +150,8 @@ func addNotificationEndpoint(ctx context.Context, client MinioAdmin, params *adm
}
// getNotificationEndpointsResponse returns a list of notification endpoints in the instance
func getAddNotificationEndpointResponse(sessionID string, params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, error) {
mAdmin, err := newMAdminClient(sessionID)
func getAddNotificationEndpointResponse(session *models.Principal, params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, error) {
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err

View File

@@ -34,27 +34,24 @@ import (
func registersPoliciesHandler(api *operations.McsAPI) {
// List Policies
api.AdminAPIListPoliciesHandler = admin_api.ListPoliciesHandlerFunc(func(params admin_api.ListPoliciesParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
listPoliciesResponse, err := getListPoliciesResponse(sessionID)
api.AdminAPIListPoliciesHandler = admin_api.ListPoliciesHandlerFunc(func(params admin_api.ListPoliciesParams, session *models.Principal) middleware.Responder {
listPoliciesResponse, err := getListPoliciesResponse(session)
if err != nil {
return admin_api.NewListPoliciesDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewListPoliciesOK().WithPayload(listPoliciesResponse)
})
// Policy Info
api.AdminAPIPolicyInfoHandler = admin_api.PolicyInfoHandlerFunc(func(params admin_api.PolicyInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
policyInfo, err := getPolicyInfoResponse(sessionID, params)
api.AdminAPIPolicyInfoHandler = admin_api.PolicyInfoHandlerFunc(func(params admin_api.PolicyInfoParams, session *models.Principal) middleware.Responder {
policyInfo, err := getPolicyInfoResponse(session, params)
if err != nil {
return admin_api.NewPolicyInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewPolicyInfoOK().WithPayload(policyInfo)
})
// Add Policy
api.AdminAPIAddPolicyHandler = admin_api.AddPolicyHandlerFunc(func(params admin_api.AddPolicyParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
policyResponse, err := getAddPolicyResponse(sessionID, params.Body)
api.AdminAPIAddPolicyHandler = admin_api.AddPolicyHandlerFunc(func(params admin_api.AddPolicyParams, session *models.Principal) middleware.Responder {
policyResponse, err := getAddPolicyResponse(session, params.Body)
if err != nil {
return admin_api.NewAddPolicyDefault(500).WithPayload(&models.Error{
Code: 500,
@@ -64,17 +61,15 @@ func registersPoliciesHandler(api *operations.McsAPI) {
return admin_api.NewAddPolicyCreated().WithPayload(policyResponse)
})
// Remove Policy
api.AdminAPIRemovePolicyHandler = admin_api.RemovePolicyHandlerFunc(func(params admin_api.RemovePolicyParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getRemovePolicyResponse(sessionID, params); err != nil {
api.AdminAPIRemovePolicyHandler = admin_api.RemovePolicyHandlerFunc(func(params admin_api.RemovePolicyParams, session *models.Principal) middleware.Responder {
if err := getRemovePolicyResponse(session, params); err != nil {
return admin_api.NewRemovePolicyDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewRemovePolicyNoContent()
})
// Set Policy
api.AdminAPISetPolicyHandler = admin_api.SetPolicyHandlerFunc(func(params admin_api.SetPolicyParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getSetPolicyResponse(sessionID, params.Name, params.Body); err != nil {
api.AdminAPISetPolicyHandler = admin_api.SetPolicyHandlerFunc(func(params admin_api.SetPolicyParams, session *models.Principal) middleware.Responder {
if err := getSetPolicyResponse(session, params.Name, params.Body); err != nil {
return admin_api.NewSetPolicyDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewSetPolicyNoContent()
@@ -102,9 +97,9 @@ func listPolicies(ctx context.Context, client MinioAdmin) ([]*models.Policy, err
}
// getListPoliciesResponse performs listPolicies() and serializes it to the handler's output
func getListPoliciesResponse(sessionID string) (*models.ListPoliciesResponse, error) {
func getListPoliciesResponse(session *models.Principal) (*models.ListPoliciesResponse, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -136,13 +131,13 @@ func removePolicy(ctx context.Context, client MinioAdmin, name string) error {
}
// getRemovePolicyResponse() performs removePolicy() and serializes it to the handler's output
func getRemovePolicyResponse(sessionID string, params admin_api.RemovePolicyParams) error {
func getRemovePolicyResponse(session *models.Principal, params admin_api.RemovePolicyParams) error {
ctx := context.Background()
if params.Name == "" {
log.Println("error policy name not in request")
return errors.New(500, "error policy name not in request")
}
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err
@@ -178,14 +173,14 @@ func addPolicy(ctx context.Context, client MinioAdmin, name, policy string) (*mo
}
// getAddPolicyResponse performs addPolicy() and serializes it to the handler's output
func getAddPolicyResponse(sessionID string, params *models.AddPolicyRequest) (*models.Policy, error) {
func getAddPolicyResponse(session *models.Principal, params *models.AddPolicyRequest) (*models.Policy, error) {
ctx := context.Background()
if params == nil {
log.Println("error AddPolicy body not in request")
return nil, errors.New(500, "error AddPolicy body not in request")
}
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -218,9 +213,9 @@ func policyInfo(ctx context.Context, client MinioAdmin, name string) (*models.Po
}
// getPolicyInfoResponse performs policyInfo() and serializes it to the handler's output
func getPolicyInfoResponse(sessionID string, params admin_api.PolicyInfoParams) (*models.Policy, error) {
func getPolicyInfoResponse(session *models.Principal, params admin_api.PolicyInfoParams) (*models.Policy, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -249,13 +244,13 @@ func setPolicy(ctx context.Context, client MinioAdmin, name, entityName string,
}
// getSetPolicyResponse() performs setPolicy() and serializes it to the handler's output
func getSetPolicyResponse(sessionID string, name string, params *models.SetPolicyRequest) error {
func getSetPolicyResponse(session *models.Principal, name string, params *models.SetPolicyRequest) error {
ctx := context.Background()
if name == "" {
log.Println("error policy name not in request")
return errors.New(500, "error policy name not in request")
}
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err

View File

@@ -34,18 +34,16 @@ import (
func registerProfilingHandler(api *operations.McsAPI) {
// Start Profiling
api.AdminAPIProfilingStartHandler = admin_api.ProfilingStartHandlerFunc(func(params admin_api.ProfilingStartParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
profilingStartResponse, err := getProfilingStartResponse(sessionID, params.Body)
api.AdminAPIProfilingStartHandler = admin_api.ProfilingStartHandlerFunc(func(params admin_api.ProfilingStartParams, session *models.Principal) middleware.Responder {
profilingStartResponse, err := getProfilingStartResponse(session, params.Body)
if err != nil {
return admin_api.NewProfilingStartDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewProfilingStartCreated().WithPayload(profilingStartResponse)
})
// Stop and download profiling data
api.AdminAPIProfilingStopHandler = admin_api.ProfilingStopHandlerFunc(func(params admin_api.ProfilingStopParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
profilingStopResponse, err := getProfilingStopResponse(sessionID)
api.AdminAPIProfilingStopHandler = admin_api.ProfilingStopHandlerFunc(func(params admin_api.ProfilingStopParams, session *models.Principal) middleware.Responder {
profilingStopResponse, err := getProfilingStopResponse(session)
if err != nil {
return admin_api.NewProfilingStopDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -92,13 +90,13 @@ func startProfiling(ctx context.Context, client MinioAdmin, profilerType models.
}
// getProfilingStartResponse performs startProfiling() and serializes it to the handler's output
func getProfilingStartResponse(sessionID string, params *models.ProfilingStartRequest) (*models.StartProfilingList, error) {
func getProfilingStartResponse(session *models.Principal, params *models.ProfilingStartRequest) (*models.StartProfilingList, error) {
ctx := context.Background()
if params == nil {
log.Println("error profiling type not in body request")
return nil, errors.New(500, "error AddPolicy body not in request")
}
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -129,9 +127,9 @@ func stopProfiling(ctx context.Context, client MinioAdmin) (io.ReadCloser, error
}
// getProfilingStopResponse() performs setPolicy() and serializes it to the handler's output
func getProfilingStopResponse(sessionID string) (io.ReadCloser, error) {
func getProfilingStopResponse(session *models.Principal) (io.ReadCloser, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err

View File

@@ -31,9 +31,8 @@ import (
func registerServiceHandlers(api *operations.McsAPI) {
// Restart Service
api.AdminAPIRestartServiceHandler = admin_api.RestartServiceHandlerFunc(func(params admin_api.RestartServiceParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getRestartServiceResponse(sessionID); err != nil {
api.AdminAPIRestartServiceHandler = admin_api.RestartServiceHandlerFunc(func(params admin_api.RestartServiceParams, session *models.Principal) middleware.Responder {
if err := getRestartServiceResponse(session); err != nil {
return admin_api.NewRestartServiceDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewRestartServiceNoContent()
@@ -62,9 +61,9 @@ func serviceRestart(ctx context.Context, client MinioAdmin) error {
}
// getRestartServiceResponse performs serviceRestart()
func getRestartServiceResponse(sessionID string) error {
func getRestartServiceResponse(session *models.Principal) error {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err

View File

@@ -47,18 +47,16 @@ import (
func registerTenantHandlers(api *operations.McsAPI) {
// Add Tenant
api.AdminAPICreateTenantHandler = admin_api.CreateTenantHandlerFunc(func(params admin_api.CreateTenantParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
resp, err := getTenantCreatedResponse(sessionID, params)
api.AdminAPICreateTenantHandler = admin_api.CreateTenantHandlerFunc(func(params admin_api.CreateTenantParams, session *models.Principal) middleware.Responder {
resp, err := getTenantCreatedResponse(session, params)
if err != nil {
return admin_api.NewCreateTenantDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewCreateTenantOK().WithPayload(resp)
})
// List All Tenants of all namespaces
api.AdminAPIListAllTenantsHandler = admin_api.ListAllTenantsHandlerFunc(func(params admin_api.ListAllTenantsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
resp, err := getListAllTenantsResponse(sessionID, params)
api.AdminAPIListAllTenantsHandler = admin_api.ListAllTenantsHandlerFunc(func(params admin_api.ListAllTenantsParams, session *models.Principal) middleware.Responder {
resp, err := getListAllTenantsResponse(session, params)
if err != nil {
return admin_api.NewListTenantsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -66,9 +64,8 @@ func registerTenantHandlers(api *operations.McsAPI) {
})
// List Tenants by namespace
api.AdminAPIListTenantsHandler = admin_api.ListTenantsHandlerFunc(func(params admin_api.ListTenantsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
resp, err := getListTenantsResponse(sessionID, params)
api.AdminAPIListTenantsHandler = admin_api.ListTenantsHandlerFunc(func(params admin_api.ListTenantsParams, session *models.Principal) middleware.Responder {
resp, err := getListTenantsResponse(session, params)
if err != nil {
return admin_api.NewListTenantsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -76,9 +73,8 @@ func registerTenantHandlers(api *operations.McsAPI) {
})
// Detail Tenant
api.AdminAPITenantInfoHandler = admin_api.TenantInfoHandlerFunc(func(params admin_api.TenantInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
resp, err := getTenantInfoResponse(sessionID, params)
api.AdminAPITenantInfoHandler = admin_api.TenantInfoHandlerFunc(func(params admin_api.TenantInfoParams, session *models.Principal) middleware.Responder {
resp, err := getTenantInfoResponse(session, params)
if err != nil {
return admin_api.NewTenantInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -87,9 +83,8 @@ func registerTenantHandlers(api *operations.McsAPI) {
})
// Delete Tenant
api.AdminAPIDeleteTenantHandler = admin_api.DeleteTenantHandlerFunc(func(params admin_api.DeleteTenantParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
err := getDeleteTenantResponse(sessionID, params)
api.AdminAPIDeleteTenantHandler = admin_api.DeleteTenantHandlerFunc(func(params admin_api.DeleteTenantParams, session *models.Principal) middleware.Responder {
err := getDeleteTenantResponse(session, params)
if err != nil {
log.Println(err)
return admin_api.NewTenantInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String("Unable to delete tenant")})
@@ -99,9 +94,8 @@ func registerTenantHandlers(api *operations.McsAPI) {
})
// Update Tenant
api.AdminAPIUpdateTenantHandler = admin_api.UpdateTenantHandlerFunc(func(params admin_api.UpdateTenantParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
err := getUpdateTenantResponse(sessionID, params)
api.AdminAPIUpdateTenantHandler = admin_api.UpdateTenantHandlerFunc(func(params admin_api.UpdateTenantParams, session *models.Principal) middleware.Responder {
err := getUpdateTenantResponse(session, params)
if err != nil {
log.Println(err)
return admin_api.NewUpdateTenantDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String("Unable to update tenant")})
@@ -120,8 +114,8 @@ func deleteTenantAction(ctx context.Context, operatorClient OperatorClient, name
}
// getDeleteTenantResponse gets the output of deleting a minio instance
func getDeleteTenantResponse(token string, params admin_api.DeleteTenantParams) error {
opClientClientSet, err := cluster.OperatorClient(token)
func getDeleteTenantResponse(session *models.Principal, params admin_api.DeleteTenantParams) error {
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
if err != nil {
return err
}
@@ -208,16 +202,16 @@ func getTenantInfo(minioInstance *operator.MinIOInstance, tenantInfo *usageInfo)
}
}
func getTenantInfoResponse(token string, params admin_api.TenantInfoParams) (*models.Tenant, error) {
func getTenantInfoResponse(session *models.Principal, params admin_api.TenantInfoParams) (*models.Tenant, error) {
// 20 seconds timeout
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
opClientClientSet, err := cluster.OperatorClient(token)
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
if err != nil {
return nil, err
}
clientset, err := cluster.K8sClient(token)
clientset, err := cluster.K8sClient(session.SessionToken)
if err != nil {
log.Println("error getting k8sClient:", err)
return nil, err
@@ -297,9 +291,9 @@ func listTenants(ctx context.Context, operatorClient OperatorClient, namespace s
}, nil
}
func getListAllTenantsResponse(token string, params admin_api.ListAllTenantsParams) (*models.ListTenantsResponse, error) {
func getListAllTenantsResponse(session *models.Principal, params admin_api.ListAllTenantsParams) (*models.ListTenantsResponse, error) {
ctx := context.Background()
opClientClientSet, err := cluster.OperatorClient(token)
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
if err != nil {
log.Println("error getting operator client:", err)
return nil, err
@@ -316,9 +310,9 @@ func getListAllTenantsResponse(token string, params admin_api.ListAllTenantsPara
}
// getListTenantsResponse list tenants by namespace
func getListTenantsResponse(token string, params admin_api.ListTenantsParams) (*models.ListTenantsResponse, error) {
func getListTenantsResponse(session *models.Principal, params admin_api.ListTenantsParams) (*models.ListTenantsResponse, error) {
ctx := context.Background()
opClientClientSet, err := cluster.OperatorClient(token)
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
if err != nil {
log.Println("error getting operator client:", err)
return nil, err
@@ -334,7 +328,7 @@ func getListTenantsResponse(token string, params admin_api.ListTenantsParams) (*
return listT, nil
}
func getTenantCreatedResponse(token string, params admin_api.CreateTenantParams) (*models.CreateTenantResponse, error) {
func getTenantCreatedResponse(session *models.Principal, params admin_api.CreateTenantParams) (*models.CreateTenantResponse, error) {
minioImage := params.Body.Image
if minioImage == "" {
minImg, err := cluster.GetMinioImage()
@@ -366,7 +360,7 @@ func getTenantCreatedResponse(token string, params admin_api.CreateTenantParams)
},
}
clientset, err := cluster.K8sClient(token)
clientset, err := cluster.K8sClient(session.SessionToken)
if err != nil {
return nil, err
}
@@ -494,7 +488,7 @@ func getTenantCreatedResponse(token string, params admin_api.CreateTenantParams)
minInst.Spec.Metadata.Annotations = params.Body.Annotations
}
opClient, err := cluster.OperatorClient(token)
opClient, err := cluster.OperatorClient(session.SessionToken)
if err != nil {
return nil, err
}
@@ -506,7 +500,7 @@ func getTenantCreatedResponse(token string, params admin_api.CreateTenantParams)
// Integratrions
if os.Getenv("GKE_INTEGRATION") != "" {
err := gkeIntegration(clientset, *params.Body.Name, ns, token)
err := gkeIntegration(clientset, *params.Body.Name, ns, session.SessionToken)
if err != nil {
return nil, err
}
@@ -548,12 +542,12 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClient, http
return nil
}
func getUpdateTenantResponse(token string, params admin_api.UpdateTenantParams) error {
func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateTenantParams) error {
ctx := context.Background()
// TODO: use namespace of the tenant not from the controller
currentNamespace := cluster.GetNs()
opClientClientSet, err := cluster.OperatorClient(token)
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
if err != nil {
log.Println("error getting operator client:", err)
return err

View File

@@ -33,36 +33,32 @@ import (
func registerUsersHandlers(api *operations.McsAPI) {
// List Users
api.AdminAPIListUsersHandler = admin_api.ListUsersHandlerFunc(func(params admin_api.ListUsersParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
listUsersResponse, err := getListUsersResponse(sessionID)
api.AdminAPIListUsersHandler = admin_api.ListUsersHandlerFunc(func(params admin_api.ListUsersParams, session *models.Principal) middleware.Responder {
listUsersResponse, err := getListUsersResponse(session)
if err != nil {
return admin_api.NewListUsersDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewListUsersOK().WithPayload(listUsersResponse)
})
// Add User
api.AdminAPIAddUserHandler = admin_api.AddUserHandlerFunc(func(params admin_api.AddUserParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
userResponse, err := getUserAddResponse(sessionID, params)
api.AdminAPIAddUserHandler = admin_api.AddUserHandlerFunc(func(params admin_api.AddUserParams, session *models.Principal) middleware.Responder {
userResponse, err := getUserAddResponse(session, params)
if err != nil {
return admin_api.NewAddUserDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewAddUserCreated().WithPayload(userResponse)
})
// Remove User
api.AdminAPIRemoveUserHandler = admin_api.RemoveUserHandlerFunc(func(params admin_api.RemoveUserParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
err := getRemoveUserResponse(sessionID, params)
api.AdminAPIRemoveUserHandler = admin_api.RemoveUserHandlerFunc(func(params admin_api.RemoveUserParams, session *models.Principal) middleware.Responder {
err := getRemoveUserResponse(session, params)
if err != nil {
return admin_api.NewRemoveUserDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return admin_api.NewRemoveUserNoContent()
})
// Update User-Groups
api.AdminAPIUpdateUserGroupsHandler = admin_api.UpdateUserGroupsHandlerFunc(func(params admin_api.UpdateUserGroupsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
userUpdateResponse, err := getUpdateUserGroupsResponse(sessionID, params)
api.AdminAPIUpdateUserGroupsHandler = admin_api.UpdateUserGroupsHandlerFunc(func(params admin_api.UpdateUserGroupsParams, session *models.Principal) middleware.Responder {
userUpdateResponse, err := getUpdateUserGroupsResponse(session, params)
if err != nil {
return admin_api.NewUpdateUserGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -70,9 +66,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
return admin_api.NewUpdateUserGroupsOK().WithPayload(userUpdateResponse)
})
// Get User
api.AdminAPIGetUserInfoHandler = admin_api.GetUserInfoHandlerFunc(func(params admin_api.GetUserInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
userInfoResponse, err := getUserInfoResponse(sessionID, params)
api.AdminAPIGetUserInfoHandler = admin_api.GetUserInfoHandlerFunc(func(params admin_api.GetUserInfoParams, session *models.Principal) middleware.Responder {
userInfoResponse, err := getUserInfoResponse(session, params)
if err != nil {
return admin_api.NewGetUserInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -80,9 +75,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
return admin_api.NewGetUserInfoOK().WithPayload(userInfoResponse)
})
// Update User
api.AdminAPIUpdateUserInfoHandler = admin_api.UpdateUserInfoHandlerFunc(func(params admin_api.UpdateUserInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
userUpdateResponse, err := getUpdateUserResponse(sessionID, params)
api.AdminAPIUpdateUserInfoHandler = admin_api.UpdateUserInfoHandlerFunc(func(params admin_api.UpdateUserInfoParams, session *models.Principal) middleware.Responder {
userUpdateResponse, err := getUpdateUserResponse(session, params)
if err != nil {
return admin_api.NewUpdateUserInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -90,9 +84,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
return admin_api.NewUpdateUserInfoOK().WithPayload(userUpdateResponse)
})
// Update User-Groups Bulk
api.AdminAPIBulkUpdateUsersGroupsHandler = admin_api.BulkUpdateUsersGroupsHandlerFunc(func(params admin_api.BulkUpdateUsersGroupsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
err := getAddUsersListToGroupsResponse(sessionID, params)
api.AdminAPIBulkUpdateUsersGroupsHandler = admin_api.BulkUpdateUsersGroupsHandlerFunc(func(params admin_api.BulkUpdateUsersGroupsParams, session *models.Principal) middleware.Responder {
err := getAddUsersListToGroupsResponse(session, params)
if err != nil {
return admin_api.NewBulkUpdateUsersGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -126,9 +119,9 @@ func listUsers(ctx context.Context, client MinioAdmin) ([]*models.User, error) {
}
// getListUsersResponse performs listUsers() and serializes it to the handler's output
func getListUsersResponse(sessionID string) (*models.ListUsersResponse, error) {
func getListUsersResponse(session *models.Principal) (*models.ListUsersResponse, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -174,9 +167,9 @@ func addUser(ctx context.Context, client MinioAdmin, accessKey, secretKey *strin
return userRet, nil
}
func getUserAddResponse(sessionID string, params admin_api.AddUserParams) (*models.User, error) {
func getUserAddResponse(session *models.Principal, params admin_api.AddUserParams) (*models.User, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -201,10 +194,10 @@ func removeUser(ctx context.Context, client MinioAdmin, accessKey string) error
return nil
}
func getRemoveUserResponse(sessionID string, params admin_api.RemoveUserParams) error {
func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUserParams) error {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err
@@ -233,10 +226,10 @@ func getUserInfo(ctx context.Context, client MinioAdmin, accessKey string) (*mad
return &userInfo, nil
}
func getUserInfoResponse(sessionID string, params admin_api.GetUserInfoParams) (*models.User, error) {
func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfoParams) (*models.User, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -348,10 +341,10 @@ func updateUserGroups(ctx context.Context, client MinioAdmin, user string, group
return userReturn, nil
}
func getUpdateUserGroupsResponse(sessionID string, params admin_api.UpdateUserGroupsParams) (*models.User, error) {
func getUpdateUserGroupsResponse(session *models.Principal, params admin_api.UpdateUserGroupsParams) (*models.User, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -389,10 +382,10 @@ func setUserStatus(ctx context.Context, client MinioAdmin, user string, status s
return nil
}
func getUpdateUserResponse(sessionID string, params admin_api.UpdateUserInfoParams) (*models.User, error) {
func getUpdateUserResponse(session *models.Principal, params admin_api.UpdateUserInfoParams) (*models.User, error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -462,10 +455,10 @@ func addUsersListToGroups(ctx context.Context, client MinioAdmin, usersToUpdate
return nil
}
func getAddUsersListToGroupsResponse(sessionID string, params admin_api.BulkUpdateUsersGroupsParams) error {
func getAddUsersListToGroupsResponse(session *models.Principal, params admin_api.BulkUpdateUsersGroupsParams) error {
ctx := context.Background()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return err

View File

@@ -24,7 +24,7 @@ import (
mcCmd "github.com/minio/mc/cmd"
"github.com/minio/mc/pkg/probe"
"github.com/minio/mcs/pkg/auth"
"github.com/minio/mcs/models"
"github.com/minio/minio-go/v6/pkg/credentials"
mauth "github.com/minio/minio/pkg/auth"
iampolicy "github.com/minio/minio/pkg/iam/policy"
@@ -241,12 +241,8 @@ func (ac adminClient) heal(ctx context.Context, bucket, prefix string, healOpts
return ac.client.Heal(ctx, bucket, prefix, healOpts, clientToken, forceStart, forceStop)
}
func newMAdminClient(jwt string) (*madmin.AdminClient, error) {
claims, err := auth.JWTAuthenticate(jwt)
if err != nil {
return nil, err
}
adminClient, err := newAdminFromClaims(claims)
func newMAdminClient(sessionClaims *models.Principal) (*madmin.AdminClient, error) {
adminClient, err := newAdminFromClaims(sessionClaims)
if err != nil {
return nil, err
}
@@ -254,7 +250,7 @@ func newMAdminClient(jwt string) (*madmin.AdminClient, error) {
}
// newAdminFromClaims creates a minio admin from Decrypted claims using Assume role credentials
func newAdminFromClaims(claims *auth.DecryptedClaims) (*madmin.AdminClient, error) {
func newAdminFromClaims(claims *models.Principal) (*madmin.AdminClient, error) {
tlsEnabled := getMinIOEndpointIsSecure()
endpoint := getMinIOEndpoint()

View File

@@ -25,6 +25,7 @@ import (
mc "github.com/minio/mc/cmd"
"github.com/minio/mc/pkg/probe"
"github.com/minio/mcs/models"
"github.com/minio/mcs/pkg/acl"
"github.com/minio/mcs/pkg/auth"
xjwt "github.com/minio/mcs/pkg/auth/jwt"
@@ -218,24 +219,16 @@ func GetClaimsFromJWT(jwt string) (*auth.DecryptedClaims, error) {
return claims, nil
}
// getMcsCredentialsFromJWT returns the *mcsCredentials.Credentials associated to the
// getMcsCredentialsFromSession returns the *mcsCredentials.Credentials associated to the
// provided jwt, this is useful for running the Expire() or IsExpired() operations
func getMcsCredentialsFromJWT(jwt string) (*credentials.Credentials, error) {
claims, err := GetClaimsFromJWT(jwt)
if err != nil {
return nil, err
}
creds := credentials.NewStaticV4(claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken)
return creds, nil
func getMcsCredentialsFromSession(claims *models.Principal) *credentials.Credentials {
return credentials.NewStaticV4(claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken)
}
// newMinioClient creates a new MinIO client based on the mcsCredentials extracted
// from the provided jwt
func newMinioClient(jwt string) (*minio.Client, error) {
creds, err := getMcsCredentialsFromJWT(jwt)
if err != nil {
return nil, err
}
func newMinioClient(claims *models.Principal) (*minio.Client, error) {
creds := getMcsCredentialsFromSession(claims)
minioClient, err := minio.NewWithOptions(getMinIOEndpoint(), &minio.Options{
Creds: creds,
Secure: getMinIOEndpointIsSecure(),
@@ -248,7 +241,7 @@ func newMinioClient(jwt string) (*minio.Client, error) {
}
// newS3BucketClient creates a new mc S3Client to talk to the server based on a bucket
func newS3BucketClient(claims *auth.DecryptedClaims, bucketName string) (*mc.S3Client, error) {
func newS3BucketClient(claims *models.Principal, bucketName string) (*mc.S3Client, error) {
endpoint := getMinIOServer()
useSSL := getMinIOEndpointIsSecure()

View File

@@ -24,7 +24,6 @@ import (
"net/http"
"strings"
"github.com/minio/mcs/pkg/acl"
"github.com/minio/mcs/pkg/auth"
"github.com/minio/mcs/models"
@@ -62,21 +61,19 @@ func configureAPI(api *operations.McsAPI) http.Handler {
// Applies when the "x-token" header is set
api.KeyAuth = func(token string, scopes []string) (*models.Principal, error) {
if acl.GetOperatorMode() {
// here we just check the token is present on the request, authentication will be done
// by kubernetes api server
if token != "" {
prin := models.Principal(token)
return &prin, nil
}
} else {
if auth.IsJWTValid(token) {
prin := models.Principal(token)
return &prin, nil
}
// we are validating the jwt by decrypting the claims inside, if the operation succed that means the jwt
// was generated and signed by us in the first place
claims, err := auth.JWTAuthenticate(token)
if err != nil {
log.Println(err)
return nil, errors.New(401, "incorrect api key auth")
}
log.Printf("Access attempt with incorrect api key auth: %s", token)
return nil, errors.New(401, "incorrect api key auth")
return &models.Principal{
AccessKeyID: claims.AccessKeyID,
Actions: claims.Actions,
SecretAccessKey: claims.SecretAccessKey,
SessionToken: claims.SessionToken,
}, nil
}
// Register login handlers

View File

@@ -2331,7 +2331,24 @@ func init() {
]
},
"principal": {
"type": "string"
"type": "object",
"properties": {
"accessKeyID": {
"type": "string"
},
"actions": {
"type": "array",
"items": {
"type": "string"
}
},
"secretAccessKey": {
"type": "string"
},
"sessionToken": {
"type": "string"
}
}
},
"profilerType": {
"type": "string",
@@ -4999,7 +5016,24 @@ func init() {
]
},
"principal": {
"type": "string"
"type": "object",
"properties": {
"accessKeyID": {
"type": "string"
},
"actions": {
"type": "array",
"items": {
"type": "string"
}
},
"secretAccessKey": {
"type": "string"
},
"sessionToken": {
"type": "string"
}
}
},
"profilerType": {
"type": "string",

View File

@@ -32,9 +32,8 @@ import (
func registerResourceQuotaHandlers(api *operations.McsAPI) {
// Get Resource Quota
api.AdminAPIGetResourceQuotaHandler = admin_api.GetResourceQuotaHandlerFunc(func(params admin_api.GetResourceQuotaParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
resp, err := getResourceQuotaResponse(sessionID, params)
api.AdminAPIGetResourceQuotaHandler = admin_api.GetResourceQuotaHandlerFunc(func(params admin_api.GetResourceQuotaParams, session *models.Principal) middleware.Responder {
resp, err := getResourceQuotaResponse(session, params)
if err != nil {
return admin_api.NewGetResourceQuotaDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -69,9 +68,9 @@ func getResourceQuota(ctx context.Context, client K8sClient, namespace, resource
return &rq, nil
}
func getResourceQuotaResponse(token string, params admin_api.GetResourceQuotaParams) (*models.ResourceQuota, error) {
func getResourceQuotaResponse(session *models.Principal, params admin_api.GetResourceQuotaParams) (*models.ResourceQuota, error) {
ctx := context.Background()
client, err := cluster.K8sClient(token)
client, err := cluster.K8sClient(session.SessionToken)
if err != nil {
log.Println("error getting k8sClient:", err)
return nil, err

View File

@@ -36,35 +36,31 @@ import (
func registerBucketsHandlers(api *operations.McsAPI) {
// list buckets
api.UserAPIListBucketsHandler = user_api.ListBucketsHandlerFunc(func(params user_api.ListBucketsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
listBucketsResponse, err := getListBucketsResponse(sessionID)
api.UserAPIListBucketsHandler = user_api.ListBucketsHandlerFunc(func(params user_api.ListBucketsParams, session *models.Principal) middleware.Responder {
listBucketsResponse, err := getListBucketsResponse(session)
if err != nil {
return user_api.NewListBucketsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewListBucketsOK().WithPayload(listBucketsResponse)
})
// make bucket
api.UserAPIMakeBucketHandler = user_api.MakeBucketHandlerFunc(func(params user_api.MakeBucketParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getMakeBucketResponse(sessionID, params.Body); err != nil {
api.UserAPIMakeBucketHandler = user_api.MakeBucketHandlerFunc(func(params user_api.MakeBucketParams, session *models.Principal) middleware.Responder {
if err := getMakeBucketResponse(session, params.Body); err != nil {
return user_api.NewMakeBucketDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewMakeBucketCreated()
})
// delete bucket
api.UserAPIDeleteBucketHandler = user_api.DeleteBucketHandlerFunc(func(params user_api.DeleteBucketParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getDeleteBucketResponse(sessionID, params); err != nil {
api.UserAPIDeleteBucketHandler = user_api.DeleteBucketHandlerFunc(func(params user_api.DeleteBucketParams, session *models.Principal) middleware.Responder {
if err := getDeleteBucketResponse(session, params); err != nil {
return user_api.NewMakeBucketDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewDeleteBucketNoContent()
})
// get bucket info
api.UserAPIBucketInfoHandler = user_api.BucketInfoHandlerFunc(func(params user_api.BucketInfoParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
bucketInfoResp, err := getBucketInfoResponse(sessionID, params)
api.UserAPIBucketInfoHandler = user_api.BucketInfoHandlerFunc(func(params user_api.BucketInfoParams, session *models.Principal) middleware.Responder {
bucketInfoResp, err := getBucketInfoResponse(session, params)
if err != nil {
return user_api.NewBucketInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -72,9 +68,8 @@ func registerBucketsHandlers(api *operations.McsAPI) {
return user_api.NewBucketInfoOK().WithPayload(bucketInfoResp)
})
// set bucket policy
api.UserAPIBucketSetPolicyHandler = user_api.BucketSetPolicyHandlerFunc(func(params user_api.BucketSetPolicyParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
bucketSetPolicyResp, err := getBucketSetPolicyResponse(sessionID, params.Name, params.Body)
api.UserAPIBucketSetPolicyHandler = user_api.BucketSetPolicyHandlerFunc(func(params user_api.BucketSetPolicyParams, session *models.Principal) middleware.Responder {
bucketSetPolicyResp, err := getBucketSetPolicyResponse(session, params.Name, params.Body)
if err != nil {
return user_api.NewBucketSetPolicyDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -97,11 +92,11 @@ func getaAcountUsageInfo(ctx context.Context, client MinioAdmin) ([]*models.Buck
}
// getListBucketsResponse performs listBuckets() and serializes it to the handler's output
func getListBucketsResponse(sessionID string) (*models.ListBucketsResponse, error) {
func getListBucketsResponse(session *models.Principal) (*models.ListBucketsResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
mAdmin, err := newMAdminClient(sessionID)
mAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating Madmin Client:", err)
return nil, err
@@ -133,7 +128,7 @@ func makeBucket(ctx context.Context, client MinioClient, bucketName string) erro
}
// getMakeBucketResponse performs makeBucket() to create a bucket with its access policy
func getMakeBucketResponse(sessionID string, br *models.MakeBucketRequest) error {
func getMakeBucketResponse(session *models.Principal, br *models.MakeBucketRequest) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
// bucket request needed to proceed
@@ -141,7 +136,7 @@ func getMakeBucketResponse(sessionID string, br *models.MakeBucketRequest) error
log.Println("error bucket body not in request")
return errors.New(500, "error bucket body not in request")
}
mClient, err := newMinioClient(sessionID)
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return err
@@ -187,11 +182,11 @@ func setBucketAccessPolicy(ctx context.Context, client MinioClient, bucketName s
// getBucketSetPolicyResponse calls setBucketAccessPolicy() to set a access policy to a bucket
// and returns the serialized output.
func getBucketSetPolicyResponse(sessionID string, bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, error) {
func getBucketSetPolicyResponse(session *models.Principal, bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
mClient, err := newMinioClient(sessionID)
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return nil, err
@@ -223,14 +218,14 @@ func removeBucket(client MinioClient, bucketName string) error {
}
// getDeleteBucketResponse performs removeBucket() to delete a bucket
func getDeleteBucketResponse(sessionID string, params user_api.DeleteBucketParams) error {
func getDeleteBucketResponse(session *models.Principal, params user_api.DeleteBucketParams) error {
if params.Name == "" {
log.Println("error bucket name not in request")
return errors.New(500, "error bucket name not in request")
}
bucketName := params.Name
mClient, err := newMinioClient(sessionID)
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return err
@@ -272,8 +267,8 @@ func getBucketInfo(client MinioClient, bucketName string) (*models.Bucket, error
}
// getBucketInfoResponse calls getBucketInfo() to get the bucket's info
func getBucketInfoResponse(sessionID string, params user_api.BucketInfoParams) (*models.Bucket, error) {
mClient, err := newMinioClient(sessionID)
func getBucketInfoResponse(session *models.Principal, params user_api.BucketInfoParams) (*models.Bucket, error) {
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return nil, err

View File

@@ -23,7 +23,6 @@ import (
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
"github.com/minio/mcs/models"
"github.com/minio/mcs/pkg/auth"
"github.com/minio/mcs/restapi/operations"
"github.com/minio/mcs/restapi/operations/user_api"
"github.com/minio/minio-go/v6"
@@ -31,26 +30,23 @@ import (
func registerBucketEventsHandlers(api *operations.McsAPI) {
// list bucket events
api.UserAPIListBucketEventsHandler = user_api.ListBucketEventsHandlerFunc(func(params user_api.ListBucketEventsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
listBucketEventsResponse, err := getListBucketEventsResponse(sessionID, params)
api.UserAPIListBucketEventsHandler = user_api.ListBucketEventsHandlerFunc(func(params user_api.ListBucketEventsParams, session *models.Principal) middleware.Responder {
listBucketEventsResponse, err := getListBucketEventsResponse(session, params)
if err != nil {
return user_api.NewListBucketEventsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewListBucketEventsOK().WithPayload(listBucketEventsResponse)
})
// create bucket event
api.UserAPICreateBucketEventHandler = user_api.CreateBucketEventHandlerFunc(func(params user_api.CreateBucketEventParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getCreateBucketEventsResponse(sessionID, params.BucketName, params.Body); err != nil {
api.UserAPICreateBucketEventHandler = user_api.CreateBucketEventHandlerFunc(func(params user_api.CreateBucketEventParams, session *models.Principal) middleware.Responder {
if err := getCreateBucketEventsResponse(session, params.BucketName, params.Body); err != nil {
return user_api.NewCreateBucketEventDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewCreateBucketEventCreated()
})
// delete bucket event
api.UserAPIDeleteBucketEventHandler = user_api.DeleteBucketEventHandlerFunc(func(params user_api.DeleteBucketEventParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getDeleteBucketEventsResponse(sessionID, params.BucketName, params.Arn, params.Body.Events, params.Body.Prefix, params.Body.Suffix); err != nil {
api.UserAPIDeleteBucketEventHandler = user_api.DeleteBucketEventHandlerFunc(func(params user_api.DeleteBucketEventParams, session *models.Principal) middleware.Responder {
if err := getDeleteBucketEventsResponse(session, params.BucketName, params.Arn, params.Body.Events, params.Body.Prefix, params.Body.Suffix); err != nil {
return user_api.NewDeleteBucketEventDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewDeleteBucketEventNoContent()
@@ -128,8 +124,8 @@ func listBucketEvents(client MinioClient, bucketName string) ([]*models.Notifica
}
// getListBucketsResponse performs listBucketEvents() and serializes it to the handler's output
func getListBucketEventsResponse(sessionID string, params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, error) {
mClient, err := newMinioClient(sessionID)
func getListBucketEventsResponse(session *models.Principal, params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, error) {
mClient, err := newMinioClient(session)
if err != nil {
log.Println("error creating MinIO Client:", err)
return nil, err
@@ -181,12 +177,8 @@ func createBucketEvent(client MCS3Client, arn string, notificationEvents []model
}
// getCreateBucketEventsResponse calls createBucketEvent to add a bucket event notification
func getCreateBucketEventsResponse(sessionID, bucketName string, eventReq *models.BucketEventRequest) error {
claims, err := auth.JWTAuthenticate(sessionID)
if err != nil {
return err
}
s3Client, err := newS3BucketClient(claims, bucketName)
func getCreateBucketEventsResponse(session *models.Principal, bucketName string, eventReq *models.BucketEventRequest) error {
s3Client, err := newS3BucketClient(session, bucketName)
if err != nil {
log.Println("error creating S3Client:", err)
return err
@@ -221,12 +213,8 @@ func joinNotificationEvents(events []models.NotificationEventType) string {
}
// getDeleteBucketEventsResponse calls deleteBucketEventNotification() to delete a bucket event notification
func getDeleteBucketEventsResponse(sessionID, bucketName string, arn string, events []models.NotificationEventType, prefix, suffix *string) error {
claims, err := auth.JWTAuthenticate(sessionID)
if err != nil {
return err
}
s3Client, err := newS3BucketClient(claims, bucketName)
func getDeleteBucketEventsResponse(session *models.Principal, bucketName string, arn string, events []models.NotificationEventType, prefix, suffix *string) error {
s3Client, err := newS3BucketClient(session, bucketName)
if err != nil {
log.Println("error creating S3Client:", err)
return err

View File

@@ -17,10 +17,7 @@
package restapi
import (
"log"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
"github.com/minio/mcs/models"
"github.com/minio/mcs/restapi/operations"
"github.com/minio/mcs/restapi/operations/user_api"
@@ -28,11 +25,8 @@ import (
func registerLogoutHandlers(api *operations.McsAPI) {
// logout from mcs
api.UserAPILogoutHandler = user_api.LogoutHandlerFunc(func(params user_api.LogoutParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getLogoutResponse(sessionID); err != nil {
return user_api.NewLogoutDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
api.UserAPILogoutHandler = user_api.LogoutHandlerFunc(func(params user_api.LogoutParams, session *models.Principal) middleware.Responder {
getLogoutResponse(session)
return user_api.NewLogoutOK()
})
}
@@ -43,17 +37,8 @@ func logout(credentials MCSCredentials) {
}
// getLogoutResponse performs logout() and returns nil or error
func getLogoutResponse(jwt string) error {
creds, err := getMcsCredentialsFromJWT(jwt)
if err != nil {
log.Println(err)
return err
}
func getLogoutResponse(session *models.Principal) {
creds := getMcsCredentialsFromSession(session)
credentials := mcsCredentials{mcsCredentials: creds}
if err != nil {
log.Println("error creating MinIO Client:", err)
return err
}
logout(credentials)
return nil
}

View File

@@ -33,18 +33,16 @@ import (
func registerServiceAccountsHandlers(api *operations.McsAPI) {
// Create Service Account
api.UserAPICreateServiceAccountHandler = user_api.CreateServiceAccountHandlerFunc(func(params user_api.CreateServiceAccountParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
creds, err := getCreateServiceAccountResponse(sessionID, params.Body)
api.UserAPICreateServiceAccountHandler = user_api.CreateServiceAccountHandlerFunc(func(params user_api.CreateServiceAccountParams, session *models.Principal) middleware.Responder {
creds, err := getCreateServiceAccountResponse(session, params.Body)
if err != nil {
return user_api.NewCreateServiceAccountDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewCreateServiceAccountCreated().WithPayload(creds)
})
// List Service Accounts for User
api.UserAPIListUserServiceAccountsHandler = user_api.ListUserServiceAccountsHandlerFunc(func(params user_api.ListUserServiceAccountsParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
serviceAccounts, err := getUserServiceAccountsResponse(sessionID)
api.UserAPIListUserServiceAccountsHandler = user_api.ListUserServiceAccountsHandlerFunc(func(params user_api.ListUserServiceAccountsParams, session *models.Principal) middleware.Responder {
serviceAccounts, err := getUserServiceAccountsResponse(session)
if err != nil {
return user_api.NewListUserServiceAccountsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
@@ -52,9 +50,8 @@ func registerServiceAccountsHandlers(api *operations.McsAPI) {
})
// Delete a User's service account
api.UserAPIDeleteServiceAccountHandler = user_api.DeleteServiceAccountHandlerFunc(func(params user_api.DeleteServiceAccountParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
if err := getDeleteServiceAccountResponse(sessionID, params.AccessKey); err != nil {
api.UserAPIDeleteServiceAccountHandler = user_api.DeleteServiceAccountHandlerFunc(func(params user_api.DeleteServiceAccountParams, session *models.Principal) middleware.Responder {
if err := getDeleteServiceAccountResponse(session, params.AccessKey); err != nil {
return user_api.NewDeleteServiceAccountDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return user_api.NewDeleteServiceAccountNoContent()
@@ -82,11 +79,11 @@ func createServiceAccount(ctx context.Context, userClient MinioAdmin, policy str
// getCreateServiceAccountResponse creates a service account with the defined policy for the user that
// is requestingit ,it first gets the credentials of the user and creates a client which is going to
// make the call to create the Service Account
func getCreateServiceAccountResponse(userSessionID string, serviceAccount *models.ServiceAccountRequest) (*models.ServiceAccountCreds, error) {
func getCreateServiceAccountResponse(session *models.Principal, serviceAccount *models.ServiceAccountRequest) (*models.ServiceAccountCreds, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
userAdmin, err := newMAdminClient(userSessionID)
userAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating user Client:", err)
return nil, err
@@ -118,11 +115,11 @@ func getUserServiceAccounts(ctx context.Context, userClient MinioAdmin) (models.
// getUserServiceAccountsResponse authenticates the user and calls
// getUserServiceAccounts to list the user's service accounts
func getUserServiceAccountsResponse(userSessionID string) (models.ServiceAccounts, error) {
func getUserServiceAccountsResponse(session *models.Principal) (models.ServiceAccounts, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
userAdmin, err := newMAdminClient(userSessionID)
userAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating user Client:", err)
return nil, err
@@ -146,11 +143,11 @@ func deleteServiceAccount(ctx context.Context, userClient MinioAdmin, accessKey
}
// getDeleteServiceAccountResponse authenticates the user and calls deleteServiceAccount
func getDeleteServiceAccountResponse(userSessionID, accessKey string) error {
func getDeleteServiceAccountResponse(session *models.Principal, accessKey string) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
userAdmin, err := newMAdminClient(userSessionID)
userAdmin, err := newMAdminClient(session)
if err != nil {
log.Println("error creating user Client:", err)
return err

View File

@@ -18,7 +18,6 @@ package restapi
import (
"errors"
"log"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
@@ -34,28 +33,23 @@ var (
func registerSessionHandlers(api *operations.McsAPI) {
// session check
api.UserAPISessionCheckHandler = user_api.SessionCheckHandlerFunc(func(params user_api.SessionCheckParams, principal *models.Principal) middleware.Responder {
sessionID := string(*principal)
sessionResp, err := getSessionResponse(sessionID)
api.UserAPISessionCheckHandler = user_api.SessionCheckHandlerFunc(func(params user_api.SessionCheckParams, session *models.Principal) middleware.Responder {
sessionResp, err := getSessionResponse(session)
if err != nil {
return user_api.NewSessionCheckDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())})
}
return user_api.NewSessionCheckOK().WithPayload(sessionResp)
})
}
// getSessionResponse parse the jwt of the current session and returns a list of allowed actions to render in the UI
func getSessionResponse(sessionID string) (*models.SessionResponse, error) {
func getSessionResponse(session *models.Principal) (*models.SessionResponse, error) {
// serialize output
claims, err := GetClaimsFromJWT(sessionID)
if err != nil {
log.Println("error getting claims from JWT", err)
if session == nil {
return nil, errorGenericInvalidSession
}
sessionResp := &models.SessionResponse{
Pages: acl.GetAuthorizedEndpoints(claims.Actions),
Pages: acl.GetAuthorizedEndpoints(session.Actions),
Status: models.SessionResponseStatusOk,
}
return sessionResp, nil

View File

@@ -25,6 +25,7 @@ import (
"github.com/go-openapi/errors"
"github.com/gorilla/websocket"
"github.com/minio/mcs/models"
"github.com/minio/mcs/pkg/auth"
)
@@ -100,13 +101,12 @@ func (c wsConn) readMessage() (messageType int, p []byte, err error) {
func serveWS(w http.ResponseWriter, req *http.Request) {
// Perform authentication before upgrading to a Websocket Connection
// authenticate WS connection with MCS
claims, err := auth.GetClaimsFromTokenInRequest(req)
session, err := auth.GetClaimsFromTokenInRequest(req)
if err != nil {
log.Print("error on ws authentication: ", err)
errors.ServeError(w, req, errors.New(http.StatusUnauthorized, err.Error()))
return
}
// upgrades the HTTP server connection to the WebSocket protocol.
conn, err := upgrader.Upgrade(w, req, nil)
if err != nil {
@@ -118,14 +118,14 @@ func serveWS(w http.ResponseWriter, req *http.Request) {
wsPath := strings.TrimPrefix(req.URL.Path, wsBasePath)
switch {
case wsPath == "/trace":
wsAdminClient, err := newWebSocketAdminClient(conn, claims)
wsAdminClient, err := newWebSocketAdminClient(conn, session)
if err != nil {
closeWsConn(conn)
return
}
go wsAdminClient.trace()
case wsPath == "/console":
wsAdminClient, err := newWebSocketAdminClient(conn, claims)
wsAdminClient, err := newWebSocketAdminClient(conn, session)
if err != nil {
closeWsConn(conn)
return
@@ -138,7 +138,7 @@ func serveWS(w http.ResponseWriter, req *http.Request) {
closeWsConn(conn)
return
}
wsAdminClient, err := newWebSocketAdminClient(conn, claims)
wsAdminClient, err := newWebSocketAdminClient(conn, session)
if err != nil {
closeWsConn(conn)
return
@@ -146,7 +146,7 @@ func serveWS(w http.ResponseWriter, req *http.Request) {
go wsAdminClient.heal(hOptions)
case strings.HasPrefix(wsPath, `/watch`):
wOptions := getWatchOptionsFromReq(req)
wsS3Client, err := newWebSocketS3Client(conn, claims, wOptions.BucketName)
wsS3Client, err := newWebSocketS3Client(conn, session, wOptions.BucketName)
if err != nil {
closeWsConn(conn)
return
@@ -159,7 +159,7 @@ func serveWS(w http.ResponseWriter, req *http.Request) {
}
// newWebSocketAdminClient returns a wsAdminClient authenticated as an admin user
func newWebSocketAdminClient(conn *websocket.Conn, autClaims *auth.DecryptedClaims) (*wsAdminClient, error) {
func newWebSocketAdminClient(conn *websocket.Conn, autClaims *models.Principal) (*wsAdminClient, error) {
// Only start Websocket Interaction after user has been
// authenticated with MinIO
mAdmin, err := newAdminFromClaims(autClaims)
@@ -182,7 +182,7 @@ func newWebSocketAdminClient(conn *websocket.Conn, autClaims *auth.DecryptedClai
}
// newWebSocketS3Client returns a wsAdminClient authenticated as MCS admin
func newWebSocketS3Client(conn *websocket.Conn, claims *auth.DecryptedClaims, bucketName string) (*wsS3Client, error) {
func newWebSocketS3Client(conn *websocket.Conn, claims *models.Principal, bucketName string) (*wsS3Client, error) {
// Only start Websocket Interaction after user has been
// authenticated with MinIO
s3Client, err := newS3BucketClient(claims, bucketName)

View File

@@ -1484,7 +1484,18 @@ definitions:
type: string
# Structure that holds the `Bearer {TOKEN}` present on authenticated requests
principal:
type: string
type: object
properties:
accessKeyID:
type: string
secretAccessKey:
type: string
sessionToken:
type: string
actions:
type: array
items:
type: string
startProfilingItem:
type: object
properties: