STS integration, JWT auth and Stateless MCS (#70)
This commit changes the authentication mechanism between mcs and minio to an sts
(security token service) schema using the user provided credentials, previously
mcs was using master credentials. With that said in order for you to
login to MCS as an admin your user must exists first on minio and have enough
privileges to do administrative operations.
```
./mc admin user add myminio alevsk alevsk12345
```
```
cat admin.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"admin:*",
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
./mc admin policy add myminio admin admin.json
```
```
./mc admin policy set myminio admin user=alevsk
```
This commit is contained in:
@@ -31,7 +31,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 {
|
||||
arnsResp, err := getArnsResponse()
|
||||
sessionID := string(*principal)
|
||||
arnsResp, err := getArnsResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewArnListDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -53,8 +54,8 @@ func getArns(ctx context.Context, client MinioAdmin) (*models.ArnsResponse, erro
|
||||
}
|
||||
|
||||
// getArnsResponse returns a list of active arns in the instance
|
||||
func getArnsResponse() (*models.ArnsResponse, error) {
|
||||
mAdmin, err := newMAdminClient()
|
||||
func getArnsResponse(sessionID string) (*models.ArnsResponse, error) {
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -33,7 +33,8 @@ import (
|
||||
func registerConfigHandlers(api *operations.McsAPI) {
|
||||
// List Configurations
|
||||
api.AdminAPIListConfigHandler = admin_api.ListConfigHandlerFunc(func(params admin_api.ListConfigParams, principal *models.Principal) middleware.Responder {
|
||||
configListResp, err := getListConfigResponse()
|
||||
sessionID := string(*principal)
|
||||
configListResp, err := getListConfigResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewListConfigDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -41,7 +42,8 @@ func registerConfigHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Configuration Info
|
||||
api.AdminAPIConfigInfoHandler = admin_api.ConfigInfoHandlerFunc(func(params admin_api.ConfigInfoParams, principal *models.Principal) middleware.Responder {
|
||||
config, err := getConfigResponse(params)
|
||||
sessionID := string(*principal)
|
||||
config, err := getConfigResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewConfigInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -49,7 +51,8 @@ func registerConfigHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Set Configuration
|
||||
api.AdminAPISetConfigHandler = admin_api.SetConfigHandlerFunc(func(params admin_api.SetConfigParams, principal *models.Principal) middleware.Responder {
|
||||
if err := setConfigResponse(params.Name, params.Body); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := setConfigResponse(sessionID, 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()
|
||||
@@ -75,8 +78,8 @@ func listConfig(client MinioAdmin) ([]*models.ConfigDescription, error) {
|
||||
}
|
||||
|
||||
// getListConfigResponse performs listConfig() and serializes it to the handler's output
|
||||
func getListConfigResponse() (*models.ListConfigResponse, error) {
|
||||
mAdmin, err := newMAdminClient()
|
||||
func getListConfigResponse(sessionID string) (*models.ListConfigResponse, error) {
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -122,8 +125,8 @@ func getConfig(client MinioAdmin, name string) ([]*models.ConfigurationKV, error
|
||||
}
|
||||
|
||||
// getConfigResponse performs getConfig() and serializes it to the handler's output
|
||||
func getConfigResponse(params admin_api.ConfigInfoParams) (*models.Configuration, error) {
|
||||
mAdmin, err := newMAdminClient()
|
||||
func getConfigResponse(sessionID string, params admin_api.ConfigInfoParams) (*models.Configuration, error) {
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -175,8 +178,8 @@ func buildConfig(configName *string, kvs []*models.ConfigurationKV) *string {
|
||||
}
|
||||
|
||||
// setConfigResponse implements setConfig() to be used by handler
|
||||
func setConfigResponse(name string, configRequest *models.SetConfigRequest) error {
|
||||
mAdmin, err := newMAdminClient()
|
||||
func setConfigResponse(sessionID string, name string, configRequest *models.SetConfigRequest) error {
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
|
||||
@@ -34,7 +34,8 @@ import (
|
||||
func registerGroupsHandlers(api *operations.McsAPI) {
|
||||
// List Groups
|
||||
api.AdminAPIListGroupsHandler = admin_api.ListGroupsHandlerFunc(func(params admin_api.ListGroupsParams, principal *models.Principal) middleware.Responder {
|
||||
listGroupsResponse, err := getListGroupsResponse()
|
||||
sessionID := string(*principal)
|
||||
listGroupsResponse, err := getListGroupsResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewListGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -42,7 +43,8 @@ func registerGroupsHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Group Info
|
||||
api.AdminAPIGroupInfoHandler = admin_api.GroupInfoHandlerFunc(func(params admin_api.GroupInfoParams, principal *models.Principal) middleware.Responder {
|
||||
groupInfo, err := getGroupInfoResponse(params)
|
||||
sessionID := string(*principal)
|
||||
groupInfo, err := getGroupInfoResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewGroupInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -50,21 +52,24 @@ func registerGroupsHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Add Group
|
||||
api.AdminAPIAddGroupHandler = admin_api.AddGroupHandlerFunc(func(params admin_api.AddGroupParams, principal *models.Principal) middleware.Responder {
|
||||
if err := getAddGroupResponse(params.Body); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := getAddGroupResponse(sessionID, 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 {
|
||||
if err := getRemoveGroupResponse(params); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := getRemoveGroupResponse(sessionID, 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 {
|
||||
groupUpdateResp, err := getUpdateGroupResponse(params)
|
||||
sessionID := string(*principal)
|
||||
groupUpdateResp, err := getUpdateGroupResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewUpdateGroupDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -82,9 +87,9 @@ func listGroups(ctx context.Context, client MinioAdmin) (*[]string, error) {
|
||||
}
|
||||
|
||||
// getListGroupsResponse performs listGroups() and serializes it to the handler's output
|
||||
func getListGroupsResponse() (*models.ListGroupsResponse, error) {
|
||||
func getListGroupsResponse(sessionID string) (*models.ListGroupsResponse, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -116,9 +121,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(params admin_api.GroupInfoParams) (*models.Group, error) {
|
||||
func getGroupInfoResponse(sessionID string, params admin_api.GroupInfoParams) (*models.Group, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -157,7 +162,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(params *models.AddGroupRequest) error {
|
||||
func getAddGroupResponse(sessionID string, params *models.AddGroupRequest) error {
|
||||
ctx := context.Background()
|
||||
// AddGroup request needed to proceed
|
||||
if params == nil {
|
||||
@@ -165,7 +170,7 @@ func getAddGroupResponse(params *models.AddGroupRequest) error {
|
||||
return errors.New(500, "error AddGroup body not in request")
|
||||
}
|
||||
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
@@ -196,14 +201,14 @@ func removeGroup(ctx context.Context, client MinioAdmin, group string) error {
|
||||
}
|
||||
|
||||
// getRemoveGroupResponse performs removeGroup() and serializes it to the handler's output
|
||||
func getRemoveGroupResponse(params admin_api.RemoveGroupParams) error {
|
||||
func getRemoveGroupResponse(sessionID string, 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()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
@@ -276,7 +281,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(params admin_api.UpdateGroupParams) (*models.Group, error) {
|
||||
func getUpdateGroupResponse(sessionID string, params admin_api.UpdateGroupParams) (*models.Group, error) {
|
||||
ctx := context.Background()
|
||||
if params.Name == "" {
|
||||
log.Println("error group name not in request")
|
||||
@@ -289,7 +294,7 @@ func getUpdateGroupResponse(params admin_api.UpdateGroupParams) (*models.Group,
|
||||
expectedGroupUpdate := params.Body
|
||||
groupName := params.Name
|
||||
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -31,7 +31,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 {
|
||||
infoResp, err := getAdminInfoResponse()
|
||||
sessionID := string(*principal)
|
||||
infoResp, err := getAdminInfoResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewAdminInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -62,8 +63,8 @@ func getAdminInfo(ctx context.Context, client MinioAdmin) (*UsageInfo, error) {
|
||||
}
|
||||
|
||||
// getAdminInfoResponse returns the response containing total buckets, objects and usage.
|
||||
func getAdminInfoResponse() (*models.AdminInfoResponse, error) {
|
||||
mAdmin, err := newMAdminClient()
|
||||
func getAdminInfoResponse(sessionID string) (*models.AdminInfoResponse, error) {
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -32,7 +32,8 @@ 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 {
|
||||
notifEndpoints, err := getNotificationEndpointsResponse()
|
||||
sessionID := string(*principal)
|
||||
notifEndpoints, err := getNotificationEndpointsResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewNotificationEndpointListDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -40,7 +41,8 @@ func registerAdminNotificationEndpointsHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// add a new notification endpoints
|
||||
api.AdminAPIAddNotificationEndpointHandler = admin_api.AddNotificationEndpointHandlerFunc(func(params admin_api.AddNotificationEndpointParams, principal *models.Principal) middleware.Responder {
|
||||
notifEndpoints, err := getAddNotificationEndpointResponse(¶ms)
|
||||
sessionID := string(*principal)
|
||||
notifEndpoints, err := getAddNotificationEndpointResponse(sessionID, ¶ms)
|
||||
if err != nil {
|
||||
return admin_api.NewAddNotificationEndpointDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -78,8 +80,8 @@ func getNotificationEndpoints(ctx context.Context, client MinioAdmin) (*models.N
|
||||
}
|
||||
|
||||
// getNotificationEndpointsResponse returns a list of notification endpoints in the instance
|
||||
func getNotificationEndpointsResponse() (*models.NotifEndpointResponse, error) {
|
||||
mAdmin, err := newMAdminClient()
|
||||
func getNotificationEndpointsResponse(sessionID string) (*models.NotifEndpointResponse, error) {
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -151,8 +153,8 @@ func addNotificationEndpoint(ctx context.Context, client MinioAdmin, params *adm
|
||||
}
|
||||
|
||||
// getNotificationEndpointsResponse returns a list of notification endpoints in the instance
|
||||
func getAddNotificationEndpointResponse(params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, error) {
|
||||
mAdmin, err := newMAdminClient()
|
||||
func getAddNotificationEndpointResponse(sessionID string, params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, error) {
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -35,7 +35,8 @@ import (
|
||||
func registersPoliciesHandler(api *operations.McsAPI) {
|
||||
// List Policies
|
||||
api.AdminAPIListPoliciesHandler = admin_api.ListPoliciesHandlerFunc(func(params admin_api.ListPoliciesParams, principal *models.Principal) middleware.Responder {
|
||||
listPoliciesResponse, err := getListPoliciesResponse()
|
||||
sessionID := string(*principal)
|
||||
listPoliciesResponse, err := getListPoliciesResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewListPoliciesDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -43,7 +44,8 @@ func registersPoliciesHandler(api *operations.McsAPI) {
|
||||
})
|
||||
// Policy Info
|
||||
api.AdminAPIPolicyInfoHandler = admin_api.PolicyInfoHandlerFunc(func(params admin_api.PolicyInfoParams, principal *models.Principal) middleware.Responder {
|
||||
policyInfo, err := getPolicyInfoResponse(params)
|
||||
sessionID := string(*principal)
|
||||
policyInfo, err := getPolicyInfoResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewPolicyInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -51,7 +53,8 @@ func registersPoliciesHandler(api *operations.McsAPI) {
|
||||
})
|
||||
// Add Policy
|
||||
api.AdminAPIAddPolicyHandler = admin_api.AddPolicyHandlerFunc(func(params admin_api.AddPolicyParams, principal *models.Principal) middleware.Responder {
|
||||
policyResponse, err := getAddPolicyResponse(params.Body)
|
||||
sessionID := string(*principal)
|
||||
policyResponse, err := getAddPolicyResponse(sessionID, params.Body)
|
||||
if err != nil {
|
||||
return admin_api.NewAddPolicyDefault(500).WithPayload(&models.Error{
|
||||
Code: 500,
|
||||
@@ -62,14 +65,16 @@ func registersPoliciesHandler(api *operations.McsAPI) {
|
||||
})
|
||||
// Remove Policy
|
||||
api.AdminAPIRemovePolicyHandler = admin_api.RemovePolicyHandlerFunc(func(params admin_api.RemovePolicyParams, principal *models.Principal) middleware.Responder {
|
||||
if err := getRemovePolicyResponse(params); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := getRemovePolicyResponse(sessionID, 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 {
|
||||
if err := getSetPolicyResponse(params.Name, params.Body); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := getSetPolicyResponse(sessionID, 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()
|
||||
@@ -97,9 +102,9 @@ func listPolicies(ctx context.Context, client MinioAdmin) ([]*models.Policy, err
|
||||
}
|
||||
|
||||
// getListPoliciesResponse performs listPolicies() and serializes it to the handler's output
|
||||
func getListPoliciesResponse() (*models.ListPoliciesResponse, error) {
|
||||
func getListPoliciesResponse(sessionID string) (*models.ListPoliciesResponse, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -131,13 +136,13 @@ func removePolicy(ctx context.Context, client MinioAdmin, name string) error {
|
||||
}
|
||||
|
||||
// getRemovePolicyResponse() performs removePolicy() and serializes it to the handler's output
|
||||
func getRemovePolicyResponse(params admin_api.RemovePolicyParams) error {
|
||||
func getRemovePolicyResponse(sessionID string, 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()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
@@ -173,14 +178,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(params *models.AddPolicyRequest) (*models.Policy, error) {
|
||||
func getAddPolicyResponse(sessionID string, 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()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -213,9 +218,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(params admin_api.PolicyInfoParams) (*models.Policy, error) {
|
||||
func getPolicyInfoResponse(sessionID string, params admin_api.PolicyInfoParams) (*models.Policy, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -244,13 +249,13 @@ func setPolicy(ctx context.Context, client MinioAdmin, name, entityName string,
|
||||
}
|
||||
|
||||
// getSetPolicyResponse() performs setPolicy() and serializes it to the handler's output
|
||||
func getSetPolicyResponse(name string, params *models.SetPolicyRequest) error {
|
||||
func getSetPolicyResponse(sessionID string, 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()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
|
||||
@@ -35,7 +35,8 @@ import (
|
||||
func registerProfilingHandler(api *operations.McsAPI) {
|
||||
// Start Profiling
|
||||
api.AdminAPIProfilingStartHandler = admin_api.ProfilingStartHandlerFunc(func(params admin_api.ProfilingStartParams, principal *models.Principal) middleware.Responder {
|
||||
profilingStartResponse, err := getProfilingStartResponse(params.Body)
|
||||
sessionID := string(*principal)
|
||||
profilingStartResponse, err := getProfilingStartResponse(sessionID, params.Body)
|
||||
if err != nil {
|
||||
return admin_api.NewProfilingStartDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -43,7 +44,8 @@ func registerProfilingHandler(api *operations.McsAPI) {
|
||||
})
|
||||
// Stop and download profiling data
|
||||
api.AdminAPIProfilingStopHandler = admin_api.ProfilingStopHandlerFunc(func(params admin_api.ProfilingStopParams, principal *models.Principal) middleware.Responder {
|
||||
profilingStopResponse, err := getProfilingStopResponse()
|
||||
sessionID := string(*principal)
|
||||
profilingStopResponse, err := getProfilingStopResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewProfilingStopDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -90,13 +92,13 @@ func startProfiling(ctx context.Context, client MinioAdmin, profilerType models.
|
||||
}
|
||||
|
||||
// getProfilingStartResponse performs startProfiling() and serializes it to the handler's output
|
||||
func getProfilingStartResponse(params *models.ProfilingStartRequest) (*models.StartProfilingList, error) {
|
||||
func getProfilingStartResponse(sessionID string, 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()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -127,9 +129,9 @@ func stopProfiling(ctx context.Context, client MinioAdmin) (io.ReadCloser, error
|
||||
}
|
||||
|
||||
// getProfilingStopResponse() performs setPolicy() and serializes it to the handler's output
|
||||
func getProfilingStopResponse() (io.ReadCloser, error) {
|
||||
func getProfilingStopResponse(sessionID string) (io.ReadCloser, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -32,7 +32,8 @@ import (
|
||||
func registerServiceHandlers(api *operations.McsAPI) {
|
||||
// Restart Service
|
||||
api.AdminAPIRestartServiceHandler = admin_api.RestartServiceHandlerFunc(func(params admin_api.RestartServiceParams, principal *models.Principal) middleware.Responder {
|
||||
if err := getRestartServiceResponse(); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := getRestartServiceResponse(sessionID); err != nil {
|
||||
return admin_api.NewRestartServiceDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
return admin_api.NewRestartServiceNoContent()
|
||||
@@ -61,9 +62,9 @@ func serviceRestart(ctx context.Context, client MinioAdmin) error {
|
||||
}
|
||||
|
||||
// getRestartServiceResponse performs serviceRestart()
|
||||
func getRestartServiceResponse() error {
|
||||
func getRestartServiceResponse(sessionID string) error {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
|
||||
@@ -34,7 +34,8 @@ import (
|
||||
func registerUsersHandlers(api *operations.McsAPI) {
|
||||
// List Users
|
||||
api.AdminAPIListUsersHandler = admin_api.ListUsersHandlerFunc(func(params admin_api.ListUsersParams, principal *models.Principal) middleware.Responder {
|
||||
listUsersResponse, err := getListUsersResponse()
|
||||
sessionID := string(*principal)
|
||||
listUsersResponse, err := getListUsersResponse(sessionID)
|
||||
if err != nil {
|
||||
return admin_api.NewListUsersDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -42,7 +43,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Add User
|
||||
api.AdminAPIAddUserHandler = admin_api.AddUserHandlerFunc(func(params admin_api.AddUserParams, principal *models.Principal) middleware.Responder {
|
||||
userResponse, err := getUserAddResponse(params)
|
||||
sessionID := string(*principal)
|
||||
userResponse, err := getUserAddResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewAddUserDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -50,7 +52,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Remove User
|
||||
api.AdminAPIRemoveUserHandler = admin_api.RemoveUserHandlerFunc(func(params admin_api.RemoveUserParams, principal *models.Principal) middleware.Responder {
|
||||
err := getRemoveUserResponse(params)
|
||||
sessionID := string(*principal)
|
||||
err := getRemoveUserResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewRemoveUserDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -58,7 +61,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Update User-Groups
|
||||
api.AdminAPIUpdateUserGroupsHandler = admin_api.UpdateUserGroupsHandlerFunc(func(params admin_api.UpdateUserGroupsParams, principal *models.Principal) middleware.Responder {
|
||||
userUpdateResponse, err := getUpdateUserGroupsResponse(params)
|
||||
sessionID := string(*principal)
|
||||
userUpdateResponse, err := getUpdateUserGroupsResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewUpdateUserGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -67,7 +71,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Get User
|
||||
api.AdminAPIGetUserInfoHandler = admin_api.GetUserInfoHandlerFunc(func(params admin_api.GetUserInfoParams, principal *models.Principal) middleware.Responder {
|
||||
userInfoResponse, err := getUserInfoResponse(params)
|
||||
sessionID := string(*principal)
|
||||
userInfoResponse, err := getUserInfoResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewGetUserDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -76,7 +81,8 @@ func registerUsersHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Update User
|
||||
api.AdminAPIUpdateUserInfoHandler = admin_api.UpdateUserInfoHandlerFunc(func(params admin_api.UpdateUserInfoParams, principal *models.Principal) middleware.Responder {
|
||||
userUpdateResponse, err := getUpdateUserResponse(params)
|
||||
sessionID := string(*principal)
|
||||
userUpdateResponse, err := getUpdateUserResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewUpdateUserInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -85,9 +91,10 @@ func registerUsersHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// Update User-Groups Bulk
|
||||
api.AdminAPIBulkUpdateUsersGroupsHandler = admin_api.BulkUpdateUsersGroupsHandlerFunc(func(params admin_api.BulkUpdateUsersGroupsParams, principal *models.Principal) middleware.Responder {
|
||||
error := getAddUsersListToGroupsResponse(params)
|
||||
if error != nil {
|
||||
return admin_api.NewBulkUpdateUsersGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(error.Error())})
|
||||
sessionID := string(*principal)
|
||||
err := getAddUsersListToGroupsResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return admin_api.NewBulkUpdateUsersGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
|
||||
return admin_api.NewBulkUpdateUsersGroupsOK()
|
||||
@@ -119,9 +126,9 @@ func listUsers(ctx context.Context, client MinioAdmin) ([]*models.User, error) {
|
||||
}
|
||||
|
||||
// getListUsersResponse performs listUsers() and serializes it to the handler's output
|
||||
func getListUsersResponse() (*models.ListUsersResponse, error) {
|
||||
func getListUsersResponse(sessionID string) (*models.ListUsersResponse, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -167,9 +174,9 @@ func addUser(ctx context.Context, client MinioAdmin, accessKey, secretKey *strin
|
||||
return userRet, nil
|
||||
}
|
||||
|
||||
func getUserAddResponse(params admin_api.AddUserParams) (*models.User, error) {
|
||||
func getUserAddResponse(sessionID string, params admin_api.AddUserParams) (*models.User, error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -194,10 +201,10 @@ func removeUser(ctx context.Context, client MinioAdmin, accessKey string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRemoveUserResponse(params admin_api.RemoveUserParams) error {
|
||||
func getRemoveUserResponse(sessionID string, params admin_api.RemoveUserParams) error {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
@@ -226,10 +233,10 @@ func getUserInfo(ctx context.Context, client MinioAdmin, accessKey string) (*mad
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
||||
func getUserInfoResponse(params admin_api.GetUserInfoParams) (*models.User, error) {
|
||||
func getUserInfoResponse(sessionID string, params admin_api.GetUserInfoParams) (*models.User, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -341,10 +348,10 @@ func updateUserGroups(ctx context.Context, client MinioAdmin, user string, group
|
||||
return userReturn, nil
|
||||
}
|
||||
|
||||
func getUpdateUserGroupsResponse(params admin_api.UpdateUserGroupsParams) (*models.User, error) {
|
||||
func getUpdateUserGroupsResponse(sessionID string, params admin_api.UpdateUserGroupsParams) (*models.User, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -382,10 +389,10 @@ func setUserStatus(ctx context.Context, client MinioAdmin, user string, status s
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUpdateUserResponse(params admin_api.UpdateUserInfoParams) (*models.User, error) {
|
||||
func getUpdateUserResponse(sessionID string, params admin_api.UpdateUserInfoParams) (*models.User, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
@@ -455,10 +462,10 @@ func addUsersListToGroups(ctx context.Context, client MinioAdmin, usersToUpdate
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAddUsersListToGroupsResponse(params admin_api.BulkUpdateUsersGroupsParams) error {
|
||||
func getAddUsersListToGroupsResponse(sessionID string, params admin_api.BulkUpdateUsersGroupsParams) error {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient()
|
||||
mAdmin, err := newMAdminClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
|
||||
@@ -24,6 +24,8 @@ import (
|
||||
|
||||
mcCmd "github.com/minio/mc/cmd"
|
||||
"github.com/minio/mc/pkg/probe"
|
||||
"github.com/minio/mcs/pkg/auth"
|
||||
"github.com/minio/minio-go/v6/pkg/credentials"
|
||||
iampolicy "github.com/minio/minio/pkg/iam/policy"
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
)
|
||||
@@ -192,14 +194,17 @@ func (ac adminClient) stopProfiling(ctx context.Context) (io.ReadCloser, error)
|
||||
return ac.client.DownloadProfilingData(ctx)
|
||||
}
|
||||
|
||||
func newMAdminClient() (*madmin.AdminClient, error) {
|
||||
endpoint := getMinIOServer()
|
||||
accessKeyID := getAccessKey()
|
||||
secretAccessKey := getSecretKey()
|
||||
|
||||
adminClient, pErr := NewAdminClient(endpoint, accessKeyID, secretAccessKey)
|
||||
if pErr != nil {
|
||||
return nil, pErr.Cause
|
||||
func newMAdminClient(jwt string) (*madmin.AdminClient, error) {
|
||||
claims, err := auth.JWTAuthenticate(jwt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
adminClient, err := madmin.NewWithOptions(getMinIOEndpoint(), &madmin.Options{
|
||||
Creds: credentials.NewStaticV4(claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken),
|
||||
Secure: getMinIOEndpointIsSecure(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return adminClient, nil
|
||||
}
|
||||
|
||||
@@ -22,7 +22,10 @@ import (
|
||||
|
||||
mc "github.com/minio/mc/cmd"
|
||||
"github.com/minio/mc/pkg/probe"
|
||||
"github.com/minio/mcs/pkg/auth"
|
||||
xjwt "github.com/minio/mcs/pkg/auth/jwt"
|
||||
"github.com/minio/minio-go/v6"
|
||||
"github.com/minio/minio-go/v6/pkg/credentials"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -107,20 +110,67 @@ func (c mcS3Client) removeNotificationConfig(arn string, event string, prefix st
|
||||
return c.client.RemoveNotificationConfig(arn, event, prefix, suffix)
|
||||
}
|
||||
|
||||
// newMinioClient creates a new MinIO client to talk to the server
|
||||
func newMinioClient() (*minio.Client, error) {
|
||||
endpoint := getMinIOEndpoint()
|
||||
accessKeyID := getAccessKey()
|
||||
secretAccessKey := getSecretKey()
|
||||
useSSL := getMinIOEndpointIsSecure()
|
||||
// Define MCSCredentials interface with all functions to be implemented
|
||||
// by mock when testing, it should include all needed minioCredentials.Credentials api calls
|
||||
// that are used within this project.
|
||||
type MCSCredentials interface {
|
||||
Get() (credentials.Value, error)
|
||||
Expire()
|
||||
}
|
||||
|
||||
// Initialize minio client object.
|
||||
minioClient, err := minio.NewV4(endpoint, accessKeyID, secretAccessKey, useSSL)
|
||||
// Interface implementation
|
||||
//
|
||||
// Define the structure of a mc S3Client and define the functions that are actually used
|
||||
// from mcsCredentials api.
|
||||
type mcsCredentials struct {
|
||||
minioCredentials *credentials.Credentials
|
||||
}
|
||||
|
||||
// implements *Credentials.Get()
|
||||
func (c mcsCredentials) Get() (credentials.Value, error) {
|
||||
return c.minioCredentials.Get()
|
||||
}
|
||||
|
||||
// implements *Credentials.Expire()
|
||||
func (c mcsCredentials) Expire() {
|
||||
c.minioCredentials.Expire()
|
||||
}
|
||||
|
||||
func newMcsCredentials(accessKey, secretKey, location string) (*credentials.Credentials, error) {
|
||||
return credentials.NewSTSAssumeRole(getMinIOServer(), credentials.STSAssumeRoleOptions{
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
Location: location,
|
||||
DurationSeconds: xjwt.GetMcsSTSAndJWTDurationInSeconds(),
|
||||
})
|
||||
}
|
||||
|
||||
// getMcsCredentialsFromJWT returns the *minioCredentials.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 := auth.JWTAuthenticate(jwt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
creds := credentials.NewStaticV4(claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken)
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
return minioClient, nil
|
||||
// newMinioClient creates a new MinIO client based on the minioCredentials extracted
|
||||
// from the provided jwt
|
||||
func newMinioClient(jwt string) (*minio.Client, error) {
|
||||
creds, err := getMcsCredentialsFromJWT(jwt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
adminClient, err := minio.NewWithOptions(getMinIOEndpoint(), &minio.Options{
|
||||
Creds: creds,
|
||||
Secure: getMinIOEndpointIsSecure(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return adminClient, nil
|
||||
}
|
||||
|
||||
// newS3BucketClient creates a new mc S3Client to talk to the server based on a bucket
|
||||
@@ -150,7 +200,7 @@ func newS3BucketClient(bucketName *string) (*mc.S3Client, error) {
|
||||
// parameters.
|
||||
func newS3Config(endpoint, accessKey, secretKey string, isSecure bool) *mc.Config {
|
||||
// We have a valid alias and hostConfig. We populate the
|
||||
// credentials from the match found in the config file.
|
||||
// minioCredentials from the match found in the config file.
|
||||
s3Config := new(mc.Config)
|
||||
|
||||
s3Config.AppName = "mcs" // TODO: make this a constant
|
||||
|
||||
@@ -198,7 +198,6 @@ func getSecureFeaturePolicy() string {
|
||||
return env.Get(McsSecureFeaturePolicy, "")
|
||||
}
|
||||
|
||||
// FeaturePolicy allows the Feature-Policy header with the value to be set with a custom value. Default is "".
|
||||
func getSecureExpectCTHeader() string {
|
||||
return env.Get(McsSecureExpectCTHeader, "")
|
||||
}
|
||||
|
||||
@@ -24,9 +24,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/mcs/restapi/sessions"
|
||||
|
||||
"github.com/minio/mcs/models"
|
||||
"github.com/minio/mcs/pkg/auth"
|
||||
|
||||
assetfs "github.com/elazarl/go-bindata-assetfs"
|
||||
|
||||
@@ -60,7 +59,7 @@ 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 sessions.GetInstance().ValidSession(token) {
|
||||
if auth.IsJWTValid(token) {
|
||||
prin := models.Principal(token)
|
||||
return &prin, nil
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package sessions
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
mcCmd "github.com/minio/mc/cmd"
|
||||
)
|
||||
|
||||
type Singleton struct {
|
||||
sessions map[string]*mcCmd.Config
|
||||
}
|
||||
|
||||
var instance *Singleton
|
||||
var once sync.Once
|
||||
|
||||
// Returns a Singleton instance that keeps the sessions
|
||||
func GetInstance() *Singleton {
|
||||
once.Do(func() {
|
||||
//build sessions hash
|
||||
sessions := make(map[string]*mcCmd.Config)
|
||||
|
||||
instance = &Singleton{
|
||||
sessions: sessions,
|
||||
}
|
||||
})
|
||||
return instance
|
||||
}
|
||||
|
||||
// The delete built-in function deletes the element with the specified key (m[key]) from the map.
|
||||
// If m is nil or there is no such element, delete is a no-op. https://golang.org/pkg/builtin/#delete
|
||||
func (s *Singleton) DeleteSession(sessionID string) {
|
||||
delete(s.sessions, sessionID)
|
||||
}
|
||||
|
||||
func (s *Singleton) NewSession(cfg *mcCmd.Config) string {
|
||||
// genereate random session id
|
||||
sessionID := RandomCharString(64)
|
||||
// store the cfg under that session id
|
||||
s.sessions[sessionID] = cfg
|
||||
return sessionID
|
||||
}
|
||||
|
||||
func (s *Singleton) ValidSession(sessionID string) bool {
|
||||
if _, ok := s.sessions[sessionID]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Do not use:
|
||||
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
|
||||
// It relies on math/rand and therefore not on a cryptographically secure RNG => It must not be used
|
||||
// for access/secret keys.
|
||||
|
||||
// The alphabet of random character string. Each character must be unique.
|
||||
//
|
||||
// The RandomCharString implementation requires that: 256 / len(letters) is a natural numbers.
|
||||
// For example: 256 / 64 = 4. However, 5 > 256/62 > 4 and therefore we must not use a alphabet
|
||||
// of 62 characters.
|
||||
// The reason is that if 256 / len(letters) is not a natural number then certain characters become
|
||||
// more likely then others.
|
||||
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
|
||||
|
||||
func RandomCharString(n int) string {
|
||||
random := make([]byte, n)
|
||||
if _, err := io.ReadFull(rand.Reader, random); err != nil {
|
||||
panic(err) // Can only happen if we would run out of entropy.
|
||||
}
|
||||
|
||||
var s strings.Builder
|
||||
for _, v := range random {
|
||||
j := v % byte(len(letters))
|
||||
s.WriteByte(letters[j])
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package sessions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
mcCmd "github.com/minio/mc/cmd"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestNewSession tests the creation of a new sesison for a valid cfg object
|
||||
func TestNewSession(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
cfg := mcCmd.Config{}
|
||||
// Test Case 1: No collision
|
||||
sessionID := GetInstance().NewSession(&cfg)
|
||||
assert.NotEmpty(sessionID, "Session ID was returned empty")
|
||||
}
|
||||
|
||||
// TestValidateSession tests a valid sessionId on the sessions object
|
||||
func TestValidateSession(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
cfg := mcCmd.Config{}
|
||||
// Test Case 1: Valid session
|
||||
sessionID := GetInstance().NewSession(&cfg)
|
||||
isValid := GetInstance().ValidSession(sessionID)
|
||||
assert.Equal(isValid, true, "Session was not found valid")
|
||||
// Test Case 2: Invalid session
|
||||
isInvalid := GetInstance().ValidSession("random")
|
||||
assert.Equal(isInvalid, false, "Session was found valid")
|
||||
}
|
||||
@@ -37,7 +37,8 @@ import (
|
||||
func registerBucketsHandlers(api *operations.McsAPI) {
|
||||
// list buckets
|
||||
api.UserAPIListBucketsHandler = user_api.ListBucketsHandlerFunc(func(params user_api.ListBucketsParams, principal *models.Principal) middleware.Responder {
|
||||
listBucketsResponse, err := getListBucketsResponse()
|
||||
sessionID := string(*principal)
|
||||
listBucketsResponse, err := getListBucketsResponse(sessionID)
|
||||
if err != nil {
|
||||
return user_api.NewListBucketsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -45,14 +46,16 @@ func registerBucketsHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// make bucket
|
||||
api.UserAPIMakeBucketHandler = user_api.MakeBucketHandlerFunc(func(params user_api.MakeBucketParams, principal *models.Principal) middleware.Responder {
|
||||
if err := getMakeBucketResponse(params.Body); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := getMakeBucketResponse(sessionID, 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 {
|
||||
if err := getDeleteBucketResponse(params); err != nil {
|
||||
sessionID := string(*principal)
|
||||
if err := getDeleteBucketResponse(sessionID, params); err != nil {
|
||||
return user_api.NewMakeBucketDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
|
||||
}
|
||||
@@ -60,7 +63,8 @@ func registerBucketsHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// get bucket info
|
||||
api.UserAPIBucketInfoHandler = user_api.BucketInfoHandlerFunc(func(params user_api.BucketInfoParams, principal *models.Principal) middleware.Responder {
|
||||
bucketInfoResp, err := getBucketInfoResponse(params)
|
||||
sessionID := string(*principal)
|
||||
bucketInfoResp, err := getBucketInfoResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return user_api.NewBucketInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -69,7 +73,8 @@ func registerBucketsHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
// set bucket policy
|
||||
api.UserAPIBucketSetPolicyHandler = user_api.BucketSetPolicyHandlerFunc(func(params user_api.BucketSetPolicyParams, principal *models.Principal) middleware.Responder {
|
||||
bucketSetPolicyResp, err := getBucketSetPolicyResponse(params.Name, params.Body)
|
||||
sessionID := string(*principal)
|
||||
bucketSetPolicyResp, err := getBucketSetPolicyResponse(sessionID, params.Name, params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewBucketSetPolicyDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -97,11 +102,10 @@ func listBuckets(ctx context.Context, client MinioClient) ([]*models.Bucket, err
|
||||
}
|
||||
|
||||
// getListBucketsResponse performs listBuckets() and serializes it to the handler's output
|
||||
func getListBucketsResponse() (*models.ListBucketsResponse, error) {
|
||||
func getListBucketsResponse(sessionID string) (*models.ListBucketsResponse, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
mClient, err := newMinioClient()
|
||||
mClient, err := newMinioClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return nil, err
|
||||
@@ -133,7 +137,7 @@ func makeBucket(ctx context.Context, client MinioClient, bucketName string) erro
|
||||
}
|
||||
|
||||
// getMakeBucketResponse performs makeBucket() to create a bucket with its access policy
|
||||
func getMakeBucketResponse(br *models.MakeBucketRequest) error {
|
||||
func getMakeBucketResponse(sessionID string, br *models.MakeBucketRequest) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
// bucket request needed to proceed
|
||||
@@ -141,7 +145,7 @@ func getMakeBucketResponse(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()
|
||||
mClient, err := newMinioClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return err
|
||||
@@ -187,11 +191,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(bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, error) {
|
||||
func getBucketSetPolicyResponse(sessionID string, bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
mClient, err := newMinioClient()
|
||||
mClient, err := newMinioClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return nil, err
|
||||
@@ -223,14 +227,14 @@ func removeBucket(client MinioClient, bucketName string) error {
|
||||
}
|
||||
|
||||
// getDeleteBucketResponse performs removeBucket() to delete a bucket
|
||||
func getDeleteBucketResponse(params user_api.DeleteBucketParams) error {
|
||||
func getDeleteBucketResponse(sessionID string, 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()
|
||||
mClient, err := newMinioClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return err
|
||||
@@ -272,8 +276,8 @@ func getBucketInfo(client MinioClient, bucketName string) (*models.Bucket, error
|
||||
}
|
||||
|
||||
// getBucketInfoResponse calls getBucketInfo() to get the bucket's info
|
||||
func getBucketInfoResponse(params user_api.BucketInfoParams) (*models.Bucket, error) {
|
||||
mClient, err := newMinioClient()
|
||||
func getBucketInfoResponse(sessionID string, params user_api.BucketInfoParams) (*models.Bucket, error) {
|
||||
mClient, err := newMinioClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -31,7 +31,8 @@ import (
|
||||
func registerBucketEventsHandlers(api *operations.McsAPI) {
|
||||
// list bucket events
|
||||
api.UserAPIListBucketEventsHandler = user_api.ListBucketEventsHandlerFunc(func(params user_api.ListBucketEventsParams, principal *models.Principal) middleware.Responder {
|
||||
listBucketEventsResponse, err := getListBucketEventsResponse(params)
|
||||
sessionID := string(*principal)
|
||||
listBucketEventsResponse, err := getListBucketEventsResponse(sessionID, params)
|
||||
if err != nil {
|
||||
return user_api.NewListBucketEventsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
}
|
||||
@@ -124,8 +125,8 @@ func listBucketEvents(client MinioClient, bucketName string) ([]*models.Notifica
|
||||
}
|
||||
|
||||
// getListBucketsResponse performs listBucketEvents() and serializes it to the handler's output
|
||||
func getListBucketEventsResponse(params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, error) {
|
||||
mClient, err := newMinioClient()
|
||||
func getListBucketEventsResponse(sessionID string, params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, error) {
|
||||
mClient, err := newMinioClient(sessionID)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -20,31 +20,14 @@ import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/minio/mc/pkg/probe"
|
||||
|
||||
"github.com/minio/mcs/restapi/sessions"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
mcCmd "github.com/minio/mc/cmd"
|
||||
"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"
|
||||
)
|
||||
|
||||
// Wraps the code at mc/cmd
|
||||
type McCmd interface {
|
||||
BuildS3Config(url, accessKey, secretKey, api, lookup string) (*mcCmd.Config, *probe.Error)
|
||||
}
|
||||
|
||||
// Implementation of McCmd
|
||||
type mcCmdWrapper struct {
|
||||
}
|
||||
|
||||
func (mc mcCmdWrapper) BuildS3Config(url, accessKey, secretKey, api, lookup string) (*mcCmd.Config, *probe.Error) {
|
||||
return mcCmd.BuildS3Config(url, accessKey, secretKey, api, lookup)
|
||||
}
|
||||
|
||||
func registerLoginHandlers(api *operations.McsAPI) {
|
||||
// get login strategy
|
||||
api.UserAPILoginDetailHandler = user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder {
|
||||
@@ -59,28 +42,34 @@ func registerLoginHandlers(api *operations.McsAPI) {
|
||||
}
|
||||
return user_api.NewLoginCreated().WithPayload(loginResponse)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
var ErrInvalidCredentials = errors.New("invalid credentials")
|
||||
var ErrInvalidCredentials = errors.New("invalid minioCredentials")
|
||||
|
||||
// login performs a check of credentials against MinIO
|
||||
func login(mc McCmd, accessKey, secretKey *string) (*string, error) {
|
||||
// Probe the credentials
|
||||
cfg, pErr := mc.BuildS3Config(getMinIOServer(), *accessKey, *secretKey, "", "auto")
|
||||
if pErr != nil {
|
||||
// login performs a check of minioCredentials against MinIO
|
||||
func login(credentials MCSCredentials) (*string, error) {
|
||||
// try to obtain minioCredentials,
|
||||
tokens, err := credentials.Get()
|
||||
if err != nil {
|
||||
return nil, ErrInvalidCredentials
|
||||
}
|
||||
// if we made it here, the credentials work, generate a session
|
||||
sessionID := sessions.GetInstance().NewSession(cfg)
|
||||
|
||||
return &sessionID, nil
|
||||
// if we made it here, the minioCredentials work, generate a jwt with claims
|
||||
jwt, err := auth.NewJWTWithClaimsForClient(&tokens, getMinIOServer())
|
||||
if err != nil {
|
||||
return nil, ErrInvalidCredentials
|
||||
}
|
||||
return &jwt, nil
|
||||
}
|
||||
|
||||
// getLoginResponse performs login() and serializes it to the handler's output
|
||||
func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, error) {
|
||||
mc := mcCmdWrapper{}
|
||||
sessionID, err := login(&mc, lr.AccessKey, lr.SecretKey)
|
||||
creds, err := newMcsCredentials(*lr.AccessKey, *lr.SecretKey, "")
|
||||
if err != nil {
|
||||
log.Println("error login:", err)
|
||||
return nil, err
|
||||
}
|
||||
credentials := mcsCredentials{minioCredentials: creds}
|
||||
sessionID, err := login(credentials)
|
||||
if err != nil {
|
||||
log.Println("error login:", err)
|
||||
return nil, err
|
||||
|
||||
@@ -20,43 +20,41 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
mcCmd "github.com/minio/mc/cmd"
|
||||
"github.com/minio/mc/pkg/probe"
|
||||
"github.com/minio/minio-go/v6/pkg/credentials"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var mcBuildS3ConfigMock func(url, accessKey, secretKey, api, lookup string) (*mcCmd.Config, *probe.Error)
|
||||
// Define a mock struct of MCSCredentials interface implementation
|
||||
type mcsCredentialsMock struct{}
|
||||
|
||||
type mcCmdMock struct{}
|
||||
// Common mocks
|
||||
var mcsCredentialsGetMock func() (credentials.Value, error)
|
||||
|
||||
func (mc mcCmdMock) BuildS3Config(url, accessKey, secretKey, api, lookup string) (*mcCmd.Config, *probe.Error) {
|
||||
return mcBuildS3ConfigMock(url, accessKey, secretKey, api, lookup)
|
||||
// mock function of Get()
|
||||
func (ac mcsCredentialsMock) Get() (credentials.Value, error) {
|
||||
return mcsCredentialsGetMock()
|
||||
}
|
||||
|
||||
// TestLogin tests the case of passing a valid and an invalid access/secret pair
|
||||
func TestLogin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
// We will write a test against play
|
||||
// Probe the credentials
|
||||
mcx := mcCmdMock{}
|
||||
access := "ABCDEFHIJK"
|
||||
secret := "ABCDEFHIJKABCDEFHIJK"
|
||||
|
||||
// Test Case 1: Valid credentials
|
||||
mcBuildS3ConfigMock = func(url, accessKey, secretKey, api, lookup string) (config *mcCmd.Config, p *probe.Error) {
|
||||
return &mcCmd.Config{}, nil
|
||||
funcAssert := assert.New(t)
|
||||
mcsCredentials := mcsCredentialsMock{}
|
||||
// Test Case 1: Valid mcsCredentials
|
||||
mcsCredentialsGetMock = func() (credentials.Value, error) {
|
||||
return credentials.Value{
|
||||
AccessKeyID: "fakeAccessKeyID",
|
||||
SecretAccessKey: "fakeSecretAccessKey",
|
||||
SessionToken: "fakeSessionToken",
|
||||
SignerType: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
sessionID, err := login(mcx, &access, &secret)
|
||||
assert.NotEmpty(sessionID, "Session ID was returned empty")
|
||||
assert.Nil(err, "error creating a session")
|
||||
jwt, err := login(mcsCredentials)
|
||||
funcAssert.NotEmpty(jwt, "JWT was returned empty")
|
||||
funcAssert.Nil(err, "error creating a session")
|
||||
|
||||
// Test Case 2: Invalid credentials
|
||||
mcBuildS3ConfigMock = func(url, accessKey, secretKey, api, lookup string) (config *mcCmd.Config, p *probe.Error) {
|
||||
return nil, probe.NewError(errors.New("Bad credentials"))
|
||||
mcsCredentialsGetMock = func() (credentials.Value, error) {
|
||||
return credentials.Value{}, errors.New("")
|
||||
}
|
||||
|
||||
sessionID, err = login(mcx, &access, &secret)
|
||||
assert.Empty(sessionID, "Session ID was not returned empty")
|
||||
assert.NotNil(err, "not error returned creating a session")
|
||||
_, err = login(mcsCredentials)
|
||||
funcAssert.NotNil(err, "not error returned creating a session")
|
||||
}
|
||||
|
||||
@@ -17,14 +17,13 @@
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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"
|
||||
"github.com/minio/mcs/restapi/sessions"
|
||||
)
|
||||
|
||||
func registerLogoutHandlers(api *operations.McsAPI) {
|
||||
@@ -38,21 +37,23 @@ func registerLogoutHandlers(api *operations.McsAPI) {
|
||||
})
|
||||
}
|
||||
|
||||
// logout() deletes provided bearer token from in memory sessions map
|
||||
// then checks that the session actually got removed
|
||||
func logout(sessionID string) error {
|
||||
sessionsMap := sessions.GetInstance()
|
||||
sessionsMap.DeleteSession(sessionID)
|
||||
if sessionsMap.ValidSession(sessionID) {
|
||||
return errors.New("something went wrong deleting your session, please try again")
|
||||
}
|
||||
return nil
|
||||
// logout() call Expire() on the provided minioCredentials
|
||||
func logout(credentials MCSCredentials) {
|
||||
credentials.Expire()
|
||||
}
|
||||
|
||||
// getLogoutResponse performs logout() and returns nil or error
|
||||
func getLogoutResponse(sessionID string) error {
|
||||
if err := logout(sessionID); err != nil {
|
||||
func getLogoutResponse(jwt string) error {
|
||||
creds, err := getMcsCredentialsFromJWT(jwt)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
credentials := mcsCredentials{minioCredentials: creds}
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return err
|
||||
}
|
||||
logout(credentials)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
import "testing"
|
||||
|
||||
mcCmd "github.com/minio/mc/cmd"
|
||||
"github.com/minio/mcs/restapi/sessions"
|
||||
)
|
||||
|
||||
// TestLogout tests the case of deleting a valid session id
|
||||
func TestLogout(t *testing.T) {
|
||||
cfg := mcCmd.Config{}
|
||||
// Creating a new session
|
||||
sessionID := sessions.GetInstance().NewSession(&cfg)
|
||||
// Test Case 1: Delete a session Valid sessionID
|
||||
function := "logout()"
|
||||
err := logout(sessionID)
|
||||
if err != nil {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
|
||||
}
|
||||
// mock function of Get()
|
||||
func (ac mcsCredentialsMock) Expire() {
|
||||
// Do nothing
|
||||
// Implementing this method for the mcsCredentials interface
|
||||
}
|
||||
|
||||
func TestLogout(t *testing.T) {
|
||||
// There's nothing to test right now
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user