From 0ba1e76400d2f5cba6a0c087c414263e36ea6f1e Mon Sep 17 00:00:00 2001 From: Lenin Alevski Date: Fri, 4 Sep 2020 20:32:57 -0700 Subject: [PATCH] centralize errors on a single error function (#266) prepareError receives an array of errors and return *model.Error object with a message and error code, we can extend this function to add more error types/code --- models/error.go | 2 +- restapi/admin_arns.go | 12 +- restapi/admin_config.go | 31 ++--- restapi/admin_groups.go | 64 +++++------ restapi/admin_info.go | 12 +- restapi/admin_nodes.go | 13 +-- restapi/admin_notification_endpoints.go | 22 ++-- restapi/admin_policies.go | 64 ++++------- restapi/admin_profiling.go | 25 ++--- restapi/admin_service.go | 12 +- restapi/admin_tenants.go | 143 ++++++++++-------------- restapi/admin_tenants_helper.go | 16 +-- restapi/admin_tenants_helper_test.go | 16 +++ restapi/admin_users.go | 73 +++++------- restapi/embedded_spec.go | 4 +- restapi/error.go | 100 +++++++++++++++++ restapi/resource_quota.go | 12 +- restapi/user_buckets.go | 64 +++++------ restapi/user_buckets_events.go | 31 ++--- restapi/user_login.go | 75 +++++-------- restapi/user_login_test.go | 2 +- restapi/user_service_accounts.go | 33 ++---- restapi/user_session.go | 13 +-- swagger.yml | 2 +- 24 files changed, 397 insertions(+), 444 deletions(-) create mode 100644 restapi/error.go diff --git a/models/error.go b/models/error.go index f7a16a517..9ddc464c6 100644 --- a/models/error.go +++ b/models/error.go @@ -35,7 +35,7 @@ import ( type Error struct { // code - Code int64 `json:"code,omitempty"` + Code int32 `json:"code,omitempty"` // message // Required: true diff --git a/restapi/admin_arns.go b/restapi/admin_arns.go index ab1b9c4a4..d441fab7a 100644 --- a/restapi/admin_arns.go +++ b/restapi/admin_arns.go @@ -18,11 +18,9 @@ package restapi import ( "context" - "log" "time" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -33,7 +31,7 @@ func registerAdminArnsHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewArnListDefault(int(err.Code)).WithPayload(err) } return admin_api.NewArnListOK().WithPayload(arnsResp) }) @@ -53,11 +51,10 @@ func getArns(ctx context.Context, client MinioAdmin) (*models.ArnsResponse, erro } // getArnsResponse returns a list of active arns in the instance -func getArnsResponse(session *models.Principal) (*models.ArnsResponse, error) { +func getArnsResponse(session *models.Principal) (*models.ArnsResponse, *models.Error) { mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -68,8 +65,7 @@ func getArnsResponse(session *models.Principal) (*models.ArnsResponse, error) { // serialize output arnsList, err := getArns(ctx, adminClient) if err != nil { - log.Println("error getting arn list:", err) - return nil, err + return nil, prepareError(err) } return arnsList, nil } diff --git a/restapi/admin_config.go b/restapi/admin_config.go index 99112a75e..e53c21537 100644 --- a/restapi/admin_config.go +++ b/restapi/admin_config.go @@ -19,7 +19,6 @@ package restapi import ( "context" "fmt" - "log" "strings" "github.com/go-openapi/runtime/middleware" @@ -36,7 +35,7 @@ func registerConfigHandlers(api *operations.ConsoleAPI) { 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.NewListConfigDefault(int(err.Code)).WithPayload(err) } return admin_api.NewListConfigOK().WithPayload(configListResp) }) @@ -44,14 +43,14 @@ func registerConfigHandlers(api *operations.ConsoleAPI) { 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.NewConfigInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewConfigInfoOK().WithPayload(config) }) // Set Configuration 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.NewSetConfigDefault(int(err.Code)).WithPayload(err) } return admin_api.NewSetConfigNoContent() }) @@ -76,11 +75,10 @@ func listConfig(client MinioAdmin) ([]*models.ConfigDescription, error) { } // getListConfigResponse performs listConfig() and serializes it to the handler's output -func getListConfigResponse(session *models.Principal) (*models.ListConfigResponse, error) { +func getListConfigResponse(session *models.Principal) (*models.ListConfigResponse, *models.Error) { mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used @@ -88,8 +86,7 @@ func getListConfigResponse(session *models.Principal) (*models.ListConfigRespons configDescs, err := listConfig(adminClient) if err != nil { - log.Println("error listing configurations:", err) - return nil, err + return nil, prepareError(err) } listGroupsResponse := &models.ListConfigResponse{ Configurations: configDescs, @@ -127,11 +124,10 @@ func getConfig(client MinioAdmin, name string) ([]*models.ConfigurationKV, error } // getConfigResponse performs getConfig() and serializes it to the handler's output -func getConfigResponse(session *models.Principal, params admin_api.ConfigInfoParams) (*models.Configuration, error) { +func getConfigResponse(session *models.Principal, params admin_api.ConfigInfoParams) (*models.Configuration, *models.Error) { mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used @@ -139,8 +135,7 @@ func getConfigResponse(session *models.Principal, params admin_api.ConfigInfoPar configkv, err := getConfig(adminClient, params.Name) if err != nil { - log.Println("error getting configuration:", err) - return nil, err + return nil, prepareError(err) } configurationObj := &models.Configuration{ Name: params.Name, @@ -180,11 +175,10 @@ func buildConfig(configName *string, kvs []*models.ConfigurationKV) *string { } // setConfigResponse implements setConfig() to be used by handler -func setConfigResponse(session *models.Principal, name string, configRequest *models.SetConfigRequest) error { +func setConfigResponse(session *models.Principal, name string, configRequest *models.SetConfigRequest) *models.Error { mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used @@ -194,8 +188,7 @@ func setConfigResponse(session *models.Principal, name string, configRequest *mo ctx := context.Background() if err := setConfigWithARNAccountID(ctx, adminClient, &configName, configRequest.KeyValues, configRequest.ArnResourceID); err != nil { - log.Println("error listing configurations:", err) - return err + return prepareError(err) } return nil } diff --git a/restapi/admin_groups.go b/restapi/admin_groups.go index e3070a433..2f060a9a6 100644 --- a/restapi/admin_groups.go +++ b/restapi/admin_groups.go @@ -22,7 +22,6 @@ import ( "github.com/go-openapi/errors" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/restapi/operations" "github.com/minio/minio/pkg/madmin" @@ -36,7 +35,7 @@ func registerGroupsHandlers(api *operations.ConsoleAPI) { 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.NewListGroupsDefault(int(err.Code)).WithPayload(err) } return admin_api.NewListGroupsOK().WithPayload(listGroupsResponse) }) @@ -44,21 +43,21 @@ func registerGroupsHandlers(api *operations.ConsoleAPI) { 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.NewGroupInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewGroupInfoOK().WithPayload(groupInfo) }) // Add Group 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.NewAddGroupDefault(int(err.Code)).WithPayload(err) } return admin_api.NewAddGroupCreated() }) // Remove Group 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.NewRemoveGroupDefault(int(err.Code)).WithPayload(err) } return admin_api.NewRemoveGroupNoContent() }) @@ -66,7 +65,7 @@ func registerGroupsHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewUpdateGroupDefault(int(err.Code)).WithPayload(err) } return admin_api.NewUpdateGroupOK().WithPayload(groupUpdateResp) }) @@ -82,12 +81,11 @@ func listGroups(ctx context.Context, client MinioAdmin) (*[]string, error) { } // getListGroupsResponse performs listGroups() and serializes it to the handler's output -func getListGroupsResponse(session *models.Principal) (*models.ListGroupsResponse, error) { +func getListGroupsResponse(session *models.Principal) (*models.ListGroupsResponse, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used @@ -95,8 +93,7 @@ func getListGroupsResponse(session *models.Principal) (*models.ListGroupsRespons groups, err := listGroups(ctx, adminClient) if err != nil { - log.Println("error listing groups:", err) - return nil, err + return nil, prepareError(err) } // serialize output listGroupsResponse := &models.ListGroupsResponse{ @@ -116,12 +113,11 @@ func groupInfo(ctx context.Context, client MinioAdmin, group string) (*madmin.Gr } // getGroupInfoResponse performs groupInfo() and serializes it to the handler's output -func getGroupInfoResponse(session *models.Principal, params admin_api.GroupInfoParams) (*models.Group, error) { +func getGroupInfoResponse(session *models.Principal, params admin_api.GroupInfoParams) (*models.Group, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used @@ -129,8 +125,7 @@ func getGroupInfoResponse(session *models.Principal, params admin_api.GroupInfoP groupDesc, err := groupInfo(ctx, adminClient, params.Name) if err != nil { - log.Println("error getting group info:", err) - return nil, err + return nil, prepareError(err) } groupResponse := &models.Group{ @@ -157,26 +152,23 @@ func addGroup(ctx context.Context, client MinioAdmin, group string, members []st } // getAddGroupResponse performs addGroup() and serializes it to the handler's output -func getAddGroupResponse(session *models.Principal, params *models.AddGroupRequest) error { +func getAddGroupResponse(session *models.Principal, params *models.AddGroupRequest) *models.Error { ctx := context.Background() // AddGroup request needed to proceed if params == nil { - log.Println("error AddGroup body not in request") - return errors.New(500, "error AddGroup body not in request") + return prepareError(errGroupBodyNotInRequest) } mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} if err := addGroup(ctx, adminClient, *params.Group, params.Members); err != nil { - log.Println("error adding group:", err) - return err + return prepareError(err) } return nil } @@ -196,25 +188,22 @@ func removeGroup(ctx context.Context, client MinioAdmin, group string) error { } // getRemoveGroupResponse performs removeGroup() and serializes it to the handler's output -func getRemoveGroupResponse(session *models.Principal, params admin_api.RemoveGroupParams) error { +func getRemoveGroupResponse(session *models.Principal, params admin_api.RemoveGroupParams) *models.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") + return prepareError(errGroupNameNotInRequest) } mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} if err := removeGroup(ctx, adminClient, params.Name); err != nil { - log.Println("error removing group:", err) - return err + return prepareError(err) } return nil } @@ -276,23 +265,21 @@ 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(session *models.Principal, params admin_api.UpdateGroupParams) (*models.Group, error) { +func getUpdateGroupResponse(session *models.Principal, params admin_api.UpdateGroupParams) (*models.Group, *models.Error) { ctx := context.Background() if params.Name == "" { - log.Println("error group name not in request") - return nil, errors.New(500, "error group name not in request") + return nil, prepareError(errGroupNameNotInRequest) } if params.Body == nil { - log.Println("error body not in request") - return nil, errors.New(500, "error body not in request") + return nil, prepareError(errGroupBodyNotInRequest) + } expectedGroupUpdate := params.Body groupName := params.Name mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used @@ -300,8 +287,7 @@ func getUpdateGroupResponse(session *models.Principal, params admin_api.UpdateGr groupUpdated, err := groupUpdate(ctx, adminClient, groupName, expectedGroupUpdate) if err != nil { - log.Println("error updating group:", err) - return nil, err + return nil, prepareError(err) } groupResponse := &models.Group{ Name: groupUpdated.Name, diff --git a/restapi/admin_info.go b/restapi/admin_info.go index 02e14a0ce..aed4d4ffe 100644 --- a/restapi/admin_info.go +++ b/restapi/admin_info.go @@ -18,11 +18,9 @@ package restapi import ( "context" - "log" "time" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -33,7 +31,7 @@ func registerAdminInfoHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewAdminInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewAdminInfoOK().WithPayload(infoResp) }) @@ -72,11 +70,10 @@ func getAdminInfo(ctx context.Context, client MinioAdmin) (*usageInfo, error) { } // getAdminInfoResponse returns the response containing total buckets, objects and usage. -func getAdminInfoResponse(session *models.Principal) (*models.AdminInfoResponse, error) { +func getAdminInfoResponse(session *models.Principal) (*models.AdminInfoResponse, *models.Error) { mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -87,8 +84,7 @@ func getAdminInfoResponse(session *models.Principal) (*models.AdminInfoResponse, // serialize output usage, err := getAdminInfo(ctx, adminClient) if err != nil { - log.Println("error getting information:", err) - return nil, err + return nil, prepareError(err) } sessionResp := &models.AdminInfoResponse{ Buckets: usage.Buckets, diff --git a/restapi/admin_nodes.go b/restapi/admin_nodes.go index 18e8268ef..30f21ac19 100644 --- a/restapi/admin_nodes.go +++ b/restapi/admin_nodes.go @@ -18,7 +18,6 @@ package restapi import ( "context" - "log" "sort" "github.com/minio/console/cluster" @@ -26,7 +25,6 @@ import ( "errors" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -39,7 +37,7 @@ func registerNodesHandlers(api *operations.ConsoleAPI) { api.AdminAPIGetMaxAllocatableMemHandler = admin_api.GetMaxAllocatableMemHandlerFunc(func(params admin_api.GetMaxAllocatableMemParams, principal *models.Principal) middleware.Responder { resp, err := getMaxAllocatableMemoryResponse(principal, params.NumNodes) if err != nil { - return admin_api.NewGetMaxAllocatableMemDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return admin_api.NewGetMaxAllocatableMemDefault(int(err.Code)).WithPayload(err) } return admin_api.NewGetMaxAllocatableMemOK().WithPayload(resp) }) @@ -123,19 +121,16 @@ func min(x, y int64) int64 { return x } -func getMaxAllocatableMemoryResponse(session *models.Principal, numNodes int32) (*models.MaxAllocatableMemResponse, error) { +func getMaxAllocatableMemoryResponse(session *models.Principal, numNodes int32) (*models.MaxAllocatableMemResponse, *models.Error) { ctx := context.Background() client, err := cluster.K8sClient(session.SessionToken) if err != nil { - log.Println("error getting k8sClient:", err) - return nil, err + return nil, prepareError(err) } clusterResources, err := getMaxAllocatableMemory(ctx, client.CoreV1(), numNodes) if err != nil { - log.Println("error getting cluster's resources:", err) - return nil, err - + return nil, prepareError(err) } return clusterResources, nil } diff --git a/restapi/admin_notification_endpoints.go b/restapi/admin_notification_endpoints.go index 26303d994..eb248e669 100644 --- a/restapi/admin_notification_endpoints.go +++ b/restapi/admin_notification_endpoints.go @@ -19,11 +19,9 @@ package restapi import ( "context" "errors" - "log" "time" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -34,7 +32,7 @@ func registerAdminNotificationEndpointsHandlers(api *operations.ConsoleAPI) { 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.NewNotificationEndpointListDefault(int(err.Code)).WithPayload(err) } return admin_api.NewNotificationEndpointListOK().WithPayload(notifEndpoints) }) @@ -42,7 +40,7 @@ func registerAdminNotificationEndpointsHandlers(api *operations.ConsoleAPI) { api.AdminAPIAddNotificationEndpointHandler = admin_api.AddNotificationEndpointHandlerFunc(func(params admin_api.AddNotificationEndpointParams, session *models.Principal) middleware.Responder { notifEndpoints, err := getAddNotificationEndpointResponse(session, ¶ms) if err != nil { - return admin_api.NewAddNotificationEndpointDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return admin_api.NewAddNotificationEndpointDefault(int(err.Code)).WithPayload(err) } return admin_api.NewAddNotificationEndpointCreated().WithPayload(notifEndpoints) }) @@ -78,11 +76,10 @@ func getNotificationEndpoints(ctx context.Context, client MinioAdmin) (*models.N } // getNotificationEndpointsResponse returns a list of notification endpoints in the instance -func getNotificationEndpointsResponse(session *models.Principal) (*models.NotifEndpointResponse, error) { +func getNotificationEndpointsResponse(session *models.Principal) (*models.NotifEndpointResponse, *models.Error) { mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -93,8 +90,7 @@ func getNotificationEndpointsResponse(session *models.Principal) (*models.NotifE // serialize output notfEndpointResp, err := getNotificationEndpoints(ctx, adminClient) if err != nil { - log.Println("error getting notification endpoint list:", err) - return nil, err + return nil, prepareError(err) } return notfEndpointResp, nil } @@ -150,11 +146,10 @@ func addNotificationEndpoint(ctx context.Context, client MinioAdmin, params *adm } // getNotificationEndpointsResponse returns a list of notification endpoints in the instance -func getAddNotificationEndpointResponse(session *models.Principal, params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, error) { +func getAddNotificationEndpointResponse(session *models.Principal, params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, *models.Error) { mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -165,8 +160,7 @@ func getAddNotificationEndpointResponse(session *models.Principal, params *admin // serialize output notfEndpointResp, err := addNotificationEndpoint(ctx, adminClient, params) if err != nil { - log.Println("error getting notification endpoint list:", err) - return nil, err + return nil, prepareError(err) } return notfEndpointResp, nil } diff --git a/restapi/admin_policies.go b/restapi/admin_policies.go index 3a4299b35..0346f921c 100644 --- a/restapi/admin_policies.go +++ b/restapi/admin_policies.go @@ -22,10 +22,7 @@ import ( "encoding/json" "log" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -37,7 +34,7 @@ func registersPoliciesHandler(api *operations.ConsoleAPI) { 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.NewListPoliciesDefault(int(err.Code)).WithPayload(err) } return admin_api.NewListPoliciesOK().WithPayload(listPoliciesResponse) }) @@ -45,7 +42,7 @@ func registersPoliciesHandler(api *operations.ConsoleAPI) { 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.NewPolicyInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewPolicyInfoOK().WithPayload(policyInfo) }) @@ -53,24 +50,21 @@ func registersPoliciesHandler(api *operations.ConsoleAPI) { 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, - Message: swag.String(err.Error()), - }) + return admin_api.NewAddPolicyDefault(int(err.Code)).WithPayload(err) } return admin_api.NewAddPolicyCreated().WithPayload(policyResponse) }) // Remove Policy 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.NewRemovePolicyDefault(int(err.Code)).WithPayload(err) } return admin_api.NewRemovePolicyNoContent() }) // Set Policy 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.NewSetPolicyDefault(int(err.Code)).WithPayload(err) } return admin_api.NewSetPolicyNoContent() }) @@ -97,12 +91,11 @@ func listPolicies(ctx context.Context, client MinioAdmin) ([]*models.Policy, err } // getListPoliciesResponse performs listPolicies() and serializes it to the handler's output -func getListPoliciesResponse(session *models.Principal) (*models.ListPoliciesResponse, error) { +func getListPoliciesResponse(session *models.Principal) (*models.ListPoliciesResponse, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used @@ -110,8 +103,7 @@ func getListPoliciesResponse(session *models.Principal) (*models.ListPoliciesRes policies, err := listPolicies(ctx, adminClient) if err != nil { - log.Println("error listing policies:", err) - return nil, err + return nil, prepareError(err) } // serialize output listPoliciesResponse := &models.ListPoliciesResponse{ @@ -131,24 +123,21 @@ func removePolicy(ctx context.Context, client MinioAdmin, name string) error { } // getRemovePolicyResponse() performs removePolicy() and serializes it to the handler's output -func getRemovePolicyResponse(session *models.Principal, params admin_api.RemovePolicyParams) error { +func getRemovePolicyResponse(session *models.Principal, params admin_api.RemovePolicyParams) *models.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") + return prepareError(errPolicyNameNotInRequest) } mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} if err := removePolicy(ctx, adminClient, params.Name); err != nil { - log.Println("error removing policy:", err) - return err + return prepareError(err) } return nil } @@ -173,25 +162,23 @@ func addPolicy(ctx context.Context, client MinioAdmin, name, policy string) (*mo } // getAddPolicyResponse performs addPolicy() and serializes it to the handler's output -func getAddPolicyResponse(session *models.Principal, params *models.AddPolicyRequest) (*models.Policy, error) { +func getAddPolicyResponse(session *models.Principal, params *models.AddPolicyRequest) (*models.Policy, *models.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") + return nil, prepareError(errPolicyBodyNotInRequest) } mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} policy, err := addPolicy(ctx, adminClient, *params.Name, *params.Policy) if err != nil { - log.Println("error adding policy") - return nil, err + return nil, prepareError(err) } return policy, nil } @@ -213,20 +200,18 @@ func policyInfo(ctx context.Context, client MinioAdmin, name string) (*models.Po } // getPolicyInfoResponse performs policyInfo() and serializes it to the handler's output -func getPolicyInfoResponse(session *models.Principal, params admin_api.PolicyInfoParams) (*models.Policy, error) { +func getPolicyInfoResponse(session *models.Principal, params admin_api.PolicyInfoParams) (*models.Policy, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} policy, err := policyInfo(ctx, adminClient, params.Name) if err != nil { - log.Println("error getting group info:", err) - return nil, err + return nil, prepareError(err) } return policy, nil } @@ -244,24 +229,21 @@ func setPolicy(ctx context.Context, client MinioAdmin, name, entityName string, } // getSetPolicyResponse() performs setPolicy() and serializes it to the handler's output -func getSetPolicyResponse(session *models.Principal, name string, params *models.SetPolicyRequest) error { +func getSetPolicyResponse(session *models.Principal, name string, params *models.SetPolicyRequest) *models.Error { ctx := context.Background() if name == "" { - log.Println("error policy name not in request") - return errors.New(500, "error policy name not in request") + return prepareError(errPolicyNameNotInRequest) } mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} if err := setPolicy(ctx, adminClient, name, *params.EntityName, params.EntityType); err != nil { - log.Println("error setting policy:", err) - return err + return prepareError(err) } return nil } diff --git a/restapi/admin_profiling.go b/restapi/admin_profiling.go index 4b7ee1908..31e22f6e8 100644 --- a/restapi/admin_profiling.go +++ b/restapi/admin_profiling.go @@ -22,10 +22,8 @@ import ( "log" "net/http" - "github.com/go-openapi/errors" "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -37,7 +35,7 @@ func registerProfilingHandler(api *operations.ConsoleAPI) { 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.NewProfilingStartDefault(int(err.Code)).WithPayload(err) } return admin_api.NewProfilingStartCreated().WithPayload(profilingStartResponse) }) @@ -45,7 +43,7 @@ func registerProfilingHandler(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewProfilingStopDefault(int(err.Code)).WithPayload(err) } // Custom response writer to set the content-disposition header to tell the // HTTP client the name and extension of the file we are returning @@ -90,24 +88,21 @@ func startProfiling(ctx context.Context, client MinioAdmin, profilerType models. } // getProfilingStartResponse performs startProfiling() and serializes it to the handler's output -func getProfilingStartResponse(session *models.Principal, params *models.ProfilingStartRequest) (*models.StartProfilingList, error) { +func getProfilingStartResponse(session *models.Principal, params *models.ProfilingStartRequest) (*models.StartProfilingList, *models.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") + return nil, prepareError(errPolicyBodyNotInRequest) } mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} profilingItems, err := startProfiling(ctx, adminClient, params.Type) if err != nil { - log.Println("error starting profiling:", err) - return nil, err + return nil, prepareError(err) } profilingList := &models.StartProfilingList{ StartResults: profilingItems, @@ -127,20 +122,18 @@ func stopProfiling(ctx context.Context, client MinioAdmin) (io.ReadCloser, error } // getProfilingStopResponse() performs setPolicy() and serializes it to the handler's output -func getProfilingStopResponse(session *models.Principal) (io.ReadCloser, error) { +func getProfilingStopResponse(session *models.Principal) (io.ReadCloser, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} profilingData, err := stopProfiling(ctx, adminClient) if err != nil { - log.Println("error stopping profiling:", err) - return nil, err + return nil, prepareError(err) } return profilingData, nil } diff --git a/restapi/admin_service.go b/restapi/admin_service.go index 408e8f5b8..6ab7ff680 100644 --- a/restapi/admin_service.go +++ b/restapi/admin_service.go @@ -18,11 +18,9 @@ package restapi import ( "context" - "log" "time" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" @@ -33,7 +31,7 @@ func registerServiceHandlers(api *operations.ConsoleAPI) { // Restart Service 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.NewRestartServiceDefault(int(err.Code)).WithPayload(err) } return admin_api.NewRestartServiceNoContent() }) @@ -61,20 +59,18 @@ func serviceRestart(ctx context.Context, client MinioAdmin) error { } // getRestartServiceResponse performs serviceRestart() -func getRestartServiceResponse(session *models.Principal) error { +func getRestartServiceResponse(session *models.Principal) *models.Error { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a MinIO Admin Client interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} if err := serviceRestart(ctx, adminClient); err != nil { - log.Println("error restarting service:", err) - return err + return prepareError(err) } return nil } diff --git a/restapi/admin_tenants.go b/restapi/admin_tenants.go index dfb1f2f4b..14588da63 100644 --- a/restapi/admin_tenants.go +++ b/restapi/admin_tenants.go @@ -64,8 +64,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { api.AdminAPICreateTenantHandler = admin_api.CreateTenantHandlerFunc(func(params admin_api.CreateTenantParams, session *models.Principal) middleware.Responder { resp, err := getTenantCreatedResponse(session, params) if err != nil { - log.Println(err) - return admin_api.NewCreateTenantDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return admin_api.NewCreateTenantDefault(int(err.Code)).WithPayload(err) } return admin_api.NewCreateTenantOK().WithPayload(resp) }) @@ -73,8 +72,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { api.AdminAPIListAllTenantsHandler = admin_api.ListAllTenantsHandlerFunc(func(params admin_api.ListAllTenantsParams, session *models.Principal) middleware.Responder { resp, err := getListAllTenantsResponse(session, params) if err != nil { - log.Println(err) - return admin_api.NewListTenantsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return admin_api.NewListTenantsDefault(int(err.Code)).WithPayload(err) } return admin_api.NewListTenantsOK().WithPayload(resp) @@ -83,8 +81,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { api.AdminAPIListTenantsHandler = admin_api.ListTenantsHandlerFunc(func(params admin_api.ListTenantsParams, session *models.Principal) middleware.Responder { resp, err := getListTenantsResponse(session, params) if err != nil { - log.Println(err) - return admin_api.NewListTenantsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return admin_api.NewListTenantsDefault(int(err.Code)).WithPayload(err) } return admin_api.NewListTenantsOK().WithPayload(resp) @@ -93,8 +90,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { api.AdminAPITenantInfoHandler = admin_api.TenantInfoHandlerFunc(func(params admin_api.TenantInfoParams, session *models.Principal) middleware.Responder { resp, err := getTenantInfoResponse(session, params) if err != nil { - log.Println(err) - return admin_api.NewTenantInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return admin_api.NewTenantInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewTenantInfoOK().WithPayload(resp) @@ -104,8 +100,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { 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(err.Error())}) + return admin_api.NewTenantInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewTenantInfoOK() @@ -115,8 +110,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { 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")}) + return admin_api.NewUpdateTenantDefault(int(err.Code)).WithPayload(err) } return admin_api.NewUpdateTenantCreated() }) @@ -126,7 +120,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { err := getTenantAddZoneResponse(session, params) if err != nil { log.Println(err) - return admin_api.NewTenantAddZoneDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String("Unable to add zone")}) + return admin_api.NewTenantAddZoneDefault(int(err.Code)).WithPayload(err) } return admin_api.NewTenantAddZoneCreated() }) @@ -136,7 +130,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { payload, err := getTenantUsageResponse(session, params) if err != nil { log.Println(err) - return admin_api.NewGetTenantUsageDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String("Unable to get tenant usage")}) + return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err) } return admin_api.NewGetTenantUsageOK().WithPayload(payload) }) @@ -146,7 +140,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { resp, err := getTenantUpdateZoneResponse(session, params) if err != nil { log.Println(err) - return admin_api.NewTenantUpdateZonesDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return admin_api.NewTenantUpdateZonesDefault(int(err.Code)).WithPayload(err) } return admin_api.NewTenantUpdateZonesOK().WithPayload(resp) }) @@ -156,7 +150,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { err := getTenantUpdateCertificatesResponse(session, params) if err != nil { log.Println(err) - return admin_api.NewGetTenantUsageDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String("Unable to update tenant certificates")}) + return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err) } return admin_api.NewTenantUpdateCertificateCreated() }) @@ -166,22 +160,22 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { err := getTenantUpdateEncryptionResponse(session, params) if err != nil { log.Println(err) - return admin_api.NewGetTenantUsageDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String("Unable to update encryption configuration")}) + return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err) } return admin_api.NewTenantUpdateCertificateCreated() }) } // getDeleteTenantResponse gets the output of deleting a minio instance -func getDeleteTenantResponse(session *models.Principal, params admin_api.DeleteTenantParams) error { +func getDeleteTenantResponse(session *models.Principal, params admin_api.DeleteTenantParams) *models.Error { opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - return err + return prepareError(err) } // get Kubernetes Client clientset, err := cluster.K8sClient(session.SessionToken) if err != nil { - return err + return prepareError(err) } opClient := &operatorClient{ client: opClientClientSet, @@ -190,7 +184,10 @@ func getDeleteTenantResponse(session *models.Principal, params admin_api.DeleteT if params.Body != nil { deleteTenantPVCs = params.Body.DeletePvcs } - return deleteTenantAction(context.Background(), opClient, clientset.CoreV1(), params.Namespace, params.Tenant, deleteTenantPVCs) + if err = deleteTenantAction(context.Background(), opClient, clientset.CoreV1(), params.Namespace, params.Tenant, deleteTenantPVCs); err != nil { + return prepareError(err) + } + return nil } // deleteTenantAction performs the actions of deleting a tenant @@ -286,14 +283,14 @@ func getTenantInfo(tenant *operator.Tenant) *models.Tenant { } } -func getTenantInfoResponse(session *models.Principal, params admin_api.TenantInfoParams) (*models.Tenant, error) { +func getTenantInfoResponse(session *models.Principal, params admin_api.TenantInfoParams) (*models.Tenant, *models.Error) { // 5 seconds timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - return nil, err + return nil, prepareError(err) } opClient := &operatorClient{ @@ -302,8 +299,7 @@ func getTenantInfoResponse(session *models.Principal, params admin_api.TenantInf minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant) if err != nil { - log.Println("error getting minioTenant:", err) - return nil, err + return nil, prepareError(err) } info := getTenantInfo(minTenant) @@ -357,44 +353,40 @@ func listTenants(ctx context.Context, operatorClient OperatorClientI, namespace }, nil } -func getListAllTenantsResponse(session *models.Principal, params admin_api.ListAllTenantsParams) (*models.ListTenantsResponse, error) { +func getListAllTenantsResponse(session *models.Principal, params admin_api.ListAllTenantsParams) (*models.ListTenantsResponse, *models.Error) { ctx := context.Background() opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - log.Println("error getting operator client:", err) - return nil, err + return nil, prepareError(err) } opClient := &operatorClient{ client: opClientClientSet, } listT, err := listTenants(ctx, opClient, "", params.Limit) if err != nil { - log.Println("error listing tenants:", err) - return nil, err + return nil, prepareError(err) } return listT, nil } // getListTenantsResponse list tenants by namespace -func getListTenantsResponse(session *models.Principal, params admin_api.ListTenantsParams) (*models.ListTenantsResponse, error) { +func getListTenantsResponse(session *models.Principal, params admin_api.ListTenantsParams) (*models.ListTenantsResponse, *models.Error) { ctx := context.Background() opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - log.Println("error getting operator client:", err) - return nil, err + return nil, prepareError(err) } opClient := &operatorClient{ client: opClientClientSet, } listT, err := listTenants(ctx, opClient, params.Namespace, params.Limit) if err != nil { - log.Println("error listing tenants:", err) - return nil, err + return nil, prepareError(err) } return listT, nil } -func getTenantCreatedResponse(session *models.Principal, params admin_api.CreateTenantParams) (*models.CreateTenantResponse, error) { +func getTenantCreatedResponse(session *models.Principal, params admin_api.CreateTenantParams) (*models.CreateTenantResponse, *models.Error) { tenantReq := params.Body minioImage := tenantReq.Image ctx := context.Background() @@ -412,7 +404,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create client: clientSet, } if err != nil { - return nil, err + return nil, prepareError(err) } ns := *tenantReq.Namespace @@ -448,14 +440,14 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create _, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &instanceSecret, metav1.CreateOptions{}) if err != nil { - return nil, err + return nil, prepareError(err) } var envrionmentVariables []corev1.EnvVar // Check the Erasure Coding Parity for validity and pass it to Tenant if tenantReq.ErasureCodingParity > 0 { if tenantReq.ErasureCodingParity < 2 && tenantReq.ErasureCodingParity > 8 { - return nil, errors.New("invalid Erasure Coding Value") + return nil, prepareError(errorInvalidErasureCodingValue) } envrionmentVariables = append(envrionmentVariables, corev1.EnvVar{ Name: "MINIO_STORAGE_CLASS_STANDARD", @@ -545,7 +537,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create externalCertSecretName := fmt.Sprintf("%s-instance-external-certificates", secretName) externalCertSecret, err := createOrReplaceExternalCertSecret(ctx, &k8sClient, ns, tenantReq.TLS.Minio, externalCertSecretName, tenantName) if err != nil { - return nil, err + return nil, prepareError(err) } minInst.Spec.ExternalCertSecret = externalCertSecret } @@ -561,13 +553,13 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create tenantExternalClientCertSecretName := fmt.Sprintf("%s-tenant-external-client-cert", secretName) minInst.Spec.ExternalClientCertSecret, err = createOrReplaceExternalCertSecret(ctx, &k8sClient, ns, tenantReq.Encryption.Client, tenantExternalClientCertSecretName, tenantName) if err != nil { - return nil, err + return nil, prepareError(errorGeneric) } } // KES configuration for Tenant instance minInst.Spec.KES, err = getKESConfiguration(ctx, &k8sClient, ns, tenantReq.Encryption, secretName, tenantName, minInst.Spec.RequestAutoCert) if err != nil { - return nil, err + return nil, prepareError(errorGeneric) } } @@ -626,7 +618,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create _, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &instanceSecret, metav1.CreateOptions{}) if err != nil { - return nil, err + return nil, prepareError(errorGeneric) } const consoleVersion = "minio/console:v0.3.19" @@ -645,7 +637,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create externalCertSecretName := fmt.Sprintf("%s-console-external-certificates", secretName) externalCertSecret, err := createOrReplaceExternalCertSecret(ctx, &k8sClient, ns, tenantReq.TLS.Console, externalCertSecretName, tenantName) if err != nil { - return nil, err + return nil, prepareError(errorGeneric) } minInst.Spec.Console.ExternalCertSecret = externalCertSecret } @@ -670,7 +662,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create for _, zone := range tenantReq.Zones { zone, err := parseTenantZoneRequest(zone, annotations) if err != nil { - return nil, err + return nil, prepareError(err) } minInst.Spec.Zones = append(minInst.Spec.Zones, *zone) } @@ -686,8 +678,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create if tenantReq.ImagePullSecret != "" { imagePullSecret = tenantReq.ImagePullSecret } else if imagePullSecret, err = setImageRegistry(ctx, tenantName, tenantReq.ImageRegistry, clientSet.CoreV1(), ns); err != nil { - log.Println("error setting image registry secret:", err) - return nil, err + return nil, prepareError(err) } // pass the image pull secret to the Tenant if imagePullSecret != "" { @@ -710,19 +701,19 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create opClient, err := cluster.OperatorClient(session.SessionToken) if err != nil { - return nil, err + return nil, prepareError(err) } _, err = opClient.MinioV1().Tenants(ns).Create(context.Background(), &minInst, metav1.CreateOptions{}) if err != nil { - return nil, err + return nil, prepareError(err) } // Integratrions if os.Getenv("GKE_INTEGRATION") != "" { err := gkeIntegration(clientSet, tenantName, ns, session.SessionToken) if err != nil { - return nil, err + return nil, prepareError(err) } } response := &models.CreateTenantResponse{ @@ -845,19 +836,17 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClientI, cli return nil } -func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateTenantParams) error { +func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateTenantParams) *models.Error { ctx := context.Background() opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - log.Println("error getting operator client:", err) - return err + return prepareError(err) } // get Kubernetes Client - clientset, err := cluster.K8sClient(session.SessionToken) + clientSet, err := cluster.K8sClient(session.SessionToken) if err != nil { - return err + return prepareError(err) } - opClient := &operatorClient{ client: opClientClientSet, } @@ -866,10 +855,8 @@ func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateT Timeout: 4 * time.Second, }, } - - if err := updateTenantAction(ctx, opClient, clientset.CoreV1(), httpC, params.Namespace, params); err != nil { - log.Println("error patching Tenant:", err) - return err + if err := updateTenantAction(ctx, opClient, clientSet.CoreV1(), httpC, params.Namespace, params); err != nil { + return prepareError(err, errors.New("unable to update tenant")) } return nil } @@ -899,51 +886,46 @@ func addTenantZone(ctx context.Context, operatorClient OperatorClientI, params a return nil } -func getTenantAddZoneResponse(session *models.Principal, params admin_api.TenantAddZoneParams) error { +func getTenantAddZoneResponse(session *models.Principal, params admin_api.TenantAddZoneParams) *models.Error { ctx := context.Background() opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - log.Println("error getting operator client:", err) - return err + return prepareError(err) } opClient := &operatorClient{ client: opClientClientSet, } if err := addTenantZone(ctx, opClient, params); err != nil { - log.Println("error patching Tenant:", err) - return err + return prepareError(err, errors.New("unable to add zone")) } return nil } // getTenantUsageResponse returns the usage of a tenant -func getTenantUsageResponse(session *models.Principal, params admin_api.GetTenantUsageParams) (*models.TenantUsage, error) { +func getTenantUsageResponse(session *models.Principal, params admin_api.GetTenantUsageParams) (*models.TenantUsage, *models.Error) { // 5 seconds timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - log.Println("error operator client", err) - return nil, err + return nil, prepareError(err, errorUnableToGetTenantUsage) } - clientset, err := cluster.K8sClient(session.SessionToken) + clientSet, err := cluster.K8sClient(session.SessionToken) if err != nil { - log.Println("error getting k8sClient:", err) - return nil, err + return nil, prepareError(err, errorUnableToGetTenantUsage) } opClient := &operatorClient{ client: opClientClientSet, } k8sClient := &k8sClient{ - client: clientset, + client: clientSet, } minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant) if err != nil { - log.Println("error getting minioTenant:", err) - return nil, err + return nil, prepareError(err, errorUnableToGetTenantUsage) } minTenant.EnsureDefaults() tenantScheme := getTenantScheme(minTenant) @@ -959,8 +941,7 @@ func getTenantUsageResponse(session *models.Principal, params admin_api.GetTenan tenantScheme, true) if err != nil { - log.Println("error getting tenant's admin client:", err) - return nil, err + return nil, prepareError(err, errorUnableToGetTenantUsage) } // create a minioClient interface implementation // defining the client to be used @@ -968,8 +949,7 @@ func getTenantUsageResponse(session *models.Principal, params admin_api.GetTenan // serialize output adminInfo, err := getAdminInfo(ctx, adminClient) if err != nil { - log.Println("error getting admin info:", err) - return nil, err + return nil, prepareError(err, errorUnableToGetTenantUsage) } info := &models.TenantUsage{Used: adminInfo.Usage, DiskUsed: adminInfo.DisksUsage} return info, nil @@ -1390,12 +1370,11 @@ func parseNodeSelectorTerm(term *corev1.NodeSelectorTerm) *models.NodeSelectorTe return &t } -func getTenantUpdateZoneResponse(session *models.Principal, params admin_api.TenantUpdateZonesParams) (*models.Tenant, error) { +func getTenantUpdateZoneResponse(session *models.Principal, params admin_api.TenantUpdateZonesParams) (*models.Tenant, *models.Error) { ctx := context.Background() opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - log.Println("error getting operator client:", err) - return nil, err + return nil, prepareError(err) } opClient := &operatorClient{ @@ -1405,7 +1384,7 @@ func getTenantUpdateZoneResponse(session *models.Principal, params admin_api.Ten t, err := updateTenantZones(ctx, opClient, params.Namespace, params.Tenant, params.Body.Zones) if err != nil { log.Println("error updating Tenant's zones:", err) - return nil, err + return nil, prepareError(err) } // parse it to models.Tenant diff --git a/restapi/admin_tenants_helper.go b/restapi/admin_tenants_helper.go index 759c6e4f6..4b396fc47 100644 --- a/restapi/admin_tenants_helper.go +++ b/restapi/admin_tenants_helper.go @@ -81,25 +81,25 @@ func tenantUpdateCertificates(ctx context.Context, operatorClient OperatorClient } // getTenantUpdateCertificatesResponse wrapper of tenantUpdateCertificates -func getTenantUpdateCertificatesResponse(session *models.Principal, params admin_api.TenantUpdateCertificateParams) error { +func getTenantUpdateCertificatesResponse(session *models.Principal, params admin_api.TenantUpdateCertificateParams) *models.Error { ctx := context.Background() // get Kubernetes Client clientSet, err := cluster.K8sClient(session.SessionToken) if err != nil { - return err + return prepareError(err, errorUnableToUpdateTenantCertificates) } k8sClient := k8sClient{ client: clientSet, } opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - return err + return prepareError(err, errorUnableToUpdateTenantCertificates) } opClient := operatorClient{ client: opClientClientSet, } if err := tenantUpdateCertificates(ctx, &opClient, &k8sClient, params.Namespace, params); err != nil { - return err + return prepareError(err, errorUnableToUpdateTenantCertificates) } return nil } @@ -157,25 +157,25 @@ func tenantUpdateEncryption(ctx context.Context, operatorClient OperatorClientI, } // getTenantUpdateEncryptionResponse is a wrapper for tenantUpdateEncryption -func getTenantUpdateEncryptionResponse(session *models.Principal, params admin_api.TenantUpdateEncryptionParams) error { +func getTenantUpdateEncryptionResponse(session *models.Principal, params admin_api.TenantUpdateEncryptionParams) *models.Error { ctx := context.Background() // get Kubernetes Client clientSet, err := cluster.K8sClient(session.SessionToken) if err != nil { - return err + return prepareError(err, errorUpdatingEncryptionConfig) } k8sClient := k8sClient{ client: clientSet, } opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { - return err + return prepareError(err, errorUpdatingEncryptionConfig) } opClient := operatorClient{ client: opClientClientSet, } if err := tenantUpdateEncryption(ctx, &opClient, &k8sClient, params.Namespace, params); err != nil { - return err + return prepareError(err, errorUpdatingEncryptionConfig) } return nil } diff --git a/restapi/admin_tenants_helper_test.go b/restapi/admin_tenants_helper_test.go index b43243c4f..166a37d78 100644 --- a/restapi/admin_tenants_helper_test.go +++ b/restapi/admin_tenants_helper_test.go @@ -1,3 +1,19 @@ +// 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 . + package restapi import ( diff --git a/restapi/admin_users.go b/restapi/admin_users.go index 7c4e55f2b..f31786955 100644 --- a/restapi/admin_users.go +++ b/restapi/admin_users.go @@ -19,7 +19,6 @@ package restapi import ( "github.com/go-openapi/errors" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -36,7 +35,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) { 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.NewListUsersDefault(int(err.Code)).WithPayload(err) } return admin_api.NewListUsersOK().WithPayload(listUsersResponse) }) @@ -44,7 +43,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) { 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.NewAddUserDefault(int(err.Code)).WithPayload(err) } return admin_api.NewAddUserCreated().WithPayload(userResponse) }) @@ -52,7 +51,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) { 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.NewRemoveUserDefault(int(err.Code)).WithPayload(err) } return admin_api.NewRemoveUserNoContent() }) @@ -60,7 +59,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewUpdateUserGroupsDefault(int(err.Code)).WithPayload(err) } return admin_api.NewUpdateUserGroupsOK().WithPayload(userUpdateResponse) @@ -69,7 +68,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewGetUserInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewGetUserInfoOK().WithPayload(userInfoResponse) @@ -78,7 +77,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewUpdateUserInfoDefault(int(err.Code)).WithPayload(err) } return admin_api.NewUpdateUserInfoOK().WithPayload(userUpdateResponse) @@ -87,7 +86,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewBulkUpdateUsersGroupsDefault(int(err.Code)).WithPayload(err) } return admin_api.NewBulkUpdateUsersGroupsOK() @@ -119,12 +118,11 @@ func listUsers(ctx context.Context, client MinioAdmin) ([]*models.User, error) { } // getListUsersResponse performs listUsers() and serializes it to the handler's output -func getListUsersResponse(session *models.Principal) (*models.ListUsersResponse, error) { +func getListUsersResponse(session *models.Principal) (*models.ListUsersResponse, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -132,8 +130,7 @@ func getListUsersResponse(session *models.Principal) (*models.ListUsersResponse, users, err := listUsers(ctx, adminClient) if err != nil { - log.Println("error listing users:", err) - return nil, err + return nil, prepareError(err) } // serialize output listUsersResponse := &models.ListUsersResponse{ @@ -167,12 +164,11 @@ func addUser(ctx context.Context, client MinioAdmin, accessKey, secretKey *strin return userRet, nil } -func getUserAddResponse(session *models.Principal, params admin_api.AddUserParams) (*models.User, error) { +func getUserAddResponse(session *models.Principal, params admin_api.AddUserParams) (*models.User, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -180,8 +176,7 @@ func getUserAddResponse(session *models.Principal, params admin_api.AddUserParam user, err := addUser(ctx, adminClient, params.Body.AccessKey, params.Body.SecretKey, params.Body.Groups) if err != nil { - log.Println("error adding user:", err) - return nil, err + return nil, prepareError(err) } return user, nil } @@ -194,13 +189,12 @@ func removeUser(ctx context.Context, client MinioAdmin, accessKey string) error return nil } -func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUserParams) error { +func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUserParams) *models.Error { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a minioClient interface implementation @@ -208,8 +202,7 @@ func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUse adminClient := adminClient{client: mAdmin} if err := removeUser(ctx, adminClient, params.Name); err != nil { - log.Println("error removing user:", err) - return err + return prepareError(err) } log.Println("User removed successfully:", params.Name) @@ -226,13 +219,12 @@ func getUserInfo(ctx context.Context, client MinioAdmin, accessKey string) (*mad return &userInfo, nil } -func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfoParams) (*models.User, error) { +func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfoParams) (*models.User, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation @@ -241,8 +233,7 @@ func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfo user, err := getUserInfo(ctx, adminClient, params.Name) if err != nil { - log.Println("error getting user:", err) - return nil, err + return nil, prepareError(err) } userInformation := &models.User{ @@ -341,13 +332,12 @@ func updateUserGroups(ctx context.Context, client MinioAdmin, user string, group return userReturn, nil } -func getUpdateUserGroupsResponse(session *models.Principal, params admin_api.UpdateUserGroupsParams) (*models.User, error) { +func getUpdateUserGroupsResponse(session *models.Principal, params admin_api.UpdateUserGroupsParams) (*models.User, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation @@ -357,8 +347,7 @@ func getUpdateUserGroupsResponse(session *models.Principal, params admin_api.Upd user, err := updateUserGroups(ctx, adminClient, params.Name, params.Body.Groups) if err != nil { - log.Println("error updating users's groups:", params.Body.Groups) - return nil, err + return nil, prepareError(err) } return user, nil @@ -382,13 +371,12 @@ func setUserStatus(ctx context.Context, client MinioAdmin, user string, status s return nil } -func getUpdateUserResponse(session *models.Principal, params admin_api.UpdateUserInfoParams) (*models.User, error) { +func getUpdateUserResponse(session *models.Principal, params admin_api.UpdateUserInfoParams) (*models.User, *models.Error) { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation @@ -400,14 +388,13 @@ func getUpdateUserResponse(session *models.Principal, params admin_api.UpdateUse groups := params.Body.Groups if err := setUserStatus(ctx, adminClient, name, status); err != nil { - log.Println("error updating user status:", status) - return nil, err + return nil, prepareError(err) } userElem, errUG := updateUserGroups(ctx, adminClient, name, groups) if errUG != nil { - return nil, errUG + return nil, prepareError(errUG) } return userElem, nil } @@ -455,13 +442,12 @@ func addUsersListToGroups(ctx context.Context, client MinioAdmin, usersToUpdate return nil } -func getAddUsersListToGroupsResponse(session *models.Principal, params admin_api.BulkUpdateUsersGroupsParams) error { +func getAddUsersListToGroupsResponse(session *models.Principal, params admin_api.BulkUpdateUsersGroupsParams) *models.Error { ctx := context.Background() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return err + return prepareError(err) } // create a minioClient interface implementation @@ -472,8 +458,7 @@ func getAddUsersListToGroupsResponse(session *models.Principal, params admin_api groupsList := params.Body.Groups if err := addUsersListToGroups(ctx, adminClient, usersList, groupsList); err != nil { - log.Println("error updating groups bulk users:", err.Error()) - return err + return prepareError(err) } return nil diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 01457993c..ae287db90 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -2320,7 +2320,7 @@ func init() { "properties": { "code": { "type": "integer", - "format": "int64" + "format": "int32" }, "message": { "type": "string" @@ -6461,7 +6461,7 @@ func init() { "properties": { "code": { "type": "integer", - "format": "int64" + "format": "int32" }, "message": { "type": "string" diff --git a/restapi/error.go b/restapi/error.go new file mode 100644 index 000000000..582ebb06b --- /dev/null +++ b/restapi/error.go @@ -0,0 +1,100 @@ +package restapi + +import ( + "errors" + "log" + + "github.com/go-openapi/swag" + "github.com/minio/console/models" + k8sErrors "k8s.io/apimachinery/pkg/api/errors" +) + +var ( + // Generic error messages + errorGeneric = errors.New("an error occurred, please try again") + errInvalidCredentials = errors.New("invalid Login") + errorGenericInvalidSession = errors.New("invalid session") + errorGenericUnauthorized = errors.New("unauthorized") + errorGenericForbidden = errors.New("forbidden") + errorGenericNotFound = errors.New("not found") + // Explicit error messages + errorInvalidErasureCodingValue = errors.New("invalid Erasure Coding Value") + errorUnableToGetTenantUsage = errors.New("unable to get tenant usage") + errorUnableToUpdateTenantCertificates = errors.New("unable to update tenant certificates") + errorUpdatingEncryptionConfig = errors.New("unable to update encryption configuration") + errBucketBodyNotInRequest = errors.New("error bucket body not in request") + errBucketNameNotInRequest = errors.New("error bucket name not in request") + errGroupBodyNotInRequest = errors.New("error group body not in request") + errGroupNameNotInRequest = errors.New("error group name not in request") + errPolicyNameNotInRequest = errors.New("error policy name not in request") + errPolicyBodyNotInRequest = errors.New("error policy body not in request") +) + +// prepareError receives an error object and parse it against k8sErrors, returns the right error code paired with a generic error message +func prepareError(err ...error) *models.Error { + errorCode := int32(500) + errorMessage := errorGeneric.Error() + if len(err) > 0 { + log.Print("original error: ", err[0].Error()) + if k8sErrors.IsUnauthorized(err[0]) { + errorCode = 401 + errorMessage = errorGenericUnauthorized.Error() + } + if k8sErrors.IsForbidden(err[0]) { + errorCode = 403 + errorMessage = errorGenericForbidden.Error() + } + if k8sErrors.IsNotFound(err[0]) { + errorCode = 404 + errorMessage = errorGenericNotFound.Error() + } + if errors.Is(err[0], errInvalidCredentials) { + errorCode = 401 + errorMessage = errInvalidCredentials.Error() + } + // console invalid erasure coding value + if errors.Is(err[0], errorInvalidErasureCodingValue) { + errorCode = 400 + errorMessage = errorInvalidErasureCodingValue.Error() + } + if errors.Is(err[0], errBucketBodyNotInRequest) { + errorCode = 400 + errorMessage = errBucketBodyNotInRequest.Error() + } + if errors.Is(err[0], errBucketNameNotInRequest) { + errorCode = 400 + errorMessage = errBucketNameNotInRequest.Error() + } + if errors.Is(err[0], errGroupBodyNotInRequest) { + errorCode = 400 + errorMessage = errGroupBodyNotInRequest.Error() + } + if errors.Is(err[0], errGroupNameNotInRequest) { + errorCode = 400 + errorMessage = errGroupNameNotInRequest.Error() + } + if errors.Is(err[0], errPolicyNameNotInRequest) { + errorCode = 400 + errorMessage = errPolicyNameNotInRequest.Error() + } + if errors.Is(err[0], errPolicyBodyNotInRequest) { + errorCode = 400 + errorMessage = errPolicyBodyNotInRequest.Error() + } + // console invalid session error + if errors.Is(err[0], errorGenericInvalidSession) { + errorCode = 401 + errorMessage = errorGenericInvalidSession.Error() + } + // if we received a second error take that as friendly message but dont override the code + if len(err) > 1 { + log.Print("friendly error: ", err[1].Error()) + errorMessage = err[1].Error() + } + // if we receive third error we just print that as debugging + if len(err) > 2 { + log.Print("debugging error: ", err[2].Error()) + } + } + return &models.Error{Code: errorCode, Message: swag.String(errorMessage)} +} diff --git a/restapi/resource_quota.go b/restapi/resource_quota.go index e224727c6..cab703020 100644 --- a/restapi/resource_quota.go +++ b/restapi/resource_quota.go @@ -18,12 +18,10 @@ package restapi import ( "context" - "log" "github.com/minio/console/cluster" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/admin_api" @@ -35,7 +33,7 @@ func registerResourceQuotaHandlers(api *operations.ConsoleAPI) { 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())}) + return admin_api.NewGetResourceQuotaDefault(int(err.Code)).WithPayload(err) } return admin_api.NewGetResourceQuotaOK().WithPayload(resp) @@ -68,20 +66,18 @@ func getResourceQuota(ctx context.Context, client K8sClientI, namespace, resourc return &rq, nil } -func getResourceQuotaResponse(session *models.Principal, params admin_api.GetResourceQuotaParams) (*models.ResourceQuota, error) { +func getResourceQuotaResponse(session *models.Principal, params admin_api.GetResourceQuotaParams) (*models.ResourceQuota, *models.Error) { ctx := context.Background() client, err := cluster.K8sClient(session.SessionToken) if err != nil { - log.Println("error getting k8sClient:", err) - return nil, err + return nil, prepareError(err) } k8sClient := &k8sClient{ client: client, } resourceQuota, err := getResourceQuota(ctx, k8sClient, params.Namespace, params.ResourceQuotaName) if err != nil { - log.Println("error getting resource quota:", err) - return nil, err + return nil, prepareError(err) } return resourceQuota, nil diff --git a/restapi/user_buckets.go b/restapi/user_buckets.go index a63933e0d..b8e170710 100644 --- a/restapi/user_buckets.go +++ b/restapi/user_buckets.go @@ -20,11 +20,9 @@ import ( "context" "encoding/json" "fmt" - "log" "strings" "time" - "github.com/go-openapi/errors" "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/swag" "github.com/minio/console/models" @@ -39,21 +37,21 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) { 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.NewListBucketsDefault(int(err.Code)).WithPayload(err) } return user_api.NewListBucketsOK().WithPayload(listBucketsResponse) }) // make bucket 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.NewMakeBucketDefault(int(err.Code)).WithPayload(err) } return user_api.NewMakeBucketCreated() }) // delete bucket 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.NewMakeBucketDefault(int(err.Code)).WithPayload(err) } return user_api.NewDeleteBucketNoContent() @@ -62,7 +60,7 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) { 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())}) + return user_api.NewBucketInfoDefault(int(err.Code)).WithPayload(err) } return user_api.NewBucketInfoOK().WithPayload(bucketInfoResp) @@ -71,7 +69,7 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) { 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())}) + return user_api.NewBucketSetPolicyDefault(int(err.Code)).WithPayload(err) } return user_api.NewBucketSetPolicyOK().WithPayload(bucketSetPolicyResp) }) @@ -92,22 +90,20 @@ func getaAcountUsageInfo(ctx context.Context, client MinioAdmin) ([]*models.Buck } // getListBucketsResponse performs listBuckets() and serializes it to the handler's output -func getListBucketsResponse(session *models.Principal) (*models.ListBucketsResponse, error) { +func getListBucketsResponse(session *models.Principal) (*models.ListBucketsResponse, *models.Error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) defer cancel() mAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used adminClient := adminClient{client: mAdmin} buckets, err := getaAcountUsageInfo(ctx, adminClient) if err != nil { - log.Println("error accountingUsageInfo:", err) - return nil, err + return nil, prepareError(err) } // serialize output @@ -128,26 +124,23 @@ func makeBucket(ctx context.Context, client MinioClient, bucketName string) erro } // getMakeBucketResponse performs makeBucket() to create a bucket with its access policy -func getMakeBucketResponse(session *models.Principal, br *models.MakeBucketRequest) error { +func getMakeBucketResponse(session *models.Principal, br *models.MakeBucketRequest) *models.Error { ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) defer cancel() // bucket request needed to proceed if br == nil { - log.Println("error bucket body not in request") - return errors.New(500, "error bucket body not in request") + return prepareError(errBucketBodyNotInRequest) } mClient, err := newMinioClient(session) if err != nil { - log.Println("error creating MinIO Client:", err) - return err + return prepareError(err) } // create a minioClient interface implementation // defining the client to be used minioClient := minioClient{client: mClient} if err := makeBucket(ctx, minioClient, *br.Name); err != nil { - log.Println("error making bucket:", err) - return err + return prepareError(err) } return nil } @@ -182,14 +175,13 @@ 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(session *models.Principal, bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, error) { +func getBucketSetPolicyResponse(session *models.Principal, bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, *models.Error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) defer cancel() mClient, err := newMinioClient(session) if err != nil { - log.Println("error creating MinIO Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -197,14 +189,12 @@ func getBucketSetPolicyResponse(session *models.Principal, bucketName string, re // set bucket access policy if err := setBucketAccessPolicy(ctx, minioClient, bucketName, req.Access); err != nil { - log.Println("error setting bucket access policy:", err) - return nil, err + return nil, prepareError(err) } // get updated bucket details and return it bucket, err := getBucketInfo(minioClient, bucketName) if err != nil { - log.Println("error getting bucket's info:", err) - return nil, err + return nil, prepareError(err) } return bucket, nil } @@ -215,23 +205,23 @@ func removeBucket(client MinioClient, bucketName string) error { } // getDeleteBucketResponse performs removeBucket() to delete a bucket -func getDeleteBucketResponse(session *models.Principal, params user_api.DeleteBucketParams) error { +func getDeleteBucketResponse(session *models.Principal, params user_api.DeleteBucketParams) *models.Error { if params.Name == "" { - log.Println("error bucket name not in request") - return errors.New(500, "error bucket name not in request") + return prepareError(errBucketNameNotInRequest) } bucketName := params.Name mClient, err := newMinioClient(session) if err != nil { - log.Println("error creating MinIO Client:", err) - return err + return prepareError(err) } // create a minioClient interface implementation // defining the client to be used minioClient := minioClient{client: mClient} - - return removeBucket(minioClient, bucketName) + if err := removeBucket(minioClient, bucketName); err != nil { + return prepareError(err) + } + return nil } // getBucketInfo return bucket information including name, policy access, size and creation date @@ -264,11 +254,10 @@ func getBucketInfo(client MinioClient, bucketName string) (*models.Bucket, error } // getBucketInfoResponse calls getBucketInfo() to get the bucket's info -func getBucketInfoResponse(session *models.Principal, params user_api.BucketInfoParams) (*models.Bucket, error) { +func getBucketInfoResponse(session *models.Principal, params user_api.BucketInfoParams) (*models.Bucket, *models.Error) { mClient, err := newMinioClient(session) if err != nil { - log.Println("error creating MinIO Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -276,8 +265,7 @@ func getBucketInfoResponse(session *models.Principal, params user_api.BucketInfo bucket, err := getBucketInfo(minioClient, params.Name) if err != nil { - log.Println("error getting bucket's info:", err) - return nil, err + return nil, prepareError(err) } return bucket, nil diff --git a/restapi/user_buckets_events.go b/restapi/user_buckets_events.go index 4d9403d89..cac6e6240 100644 --- a/restapi/user_buckets_events.go +++ b/restapi/user_buckets_events.go @@ -18,7 +18,6 @@ package restapi import ( "context" - "log" "strings" "github.com/go-openapi/runtime/middleware" @@ -34,21 +33,21 @@ func registerBucketEventsHandlers(api *operations.ConsoleAPI) { 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.NewListBucketEventsDefault(int(err.Code)).WithPayload(err) } return user_api.NewListBucketEventsOK().WithPayload(listBucketEventsResponse) }) // create bucket event 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.NewCreateBucketEventDefault(int(err.Code)).WithPayload(err) } return user_api.NewCreateBucketEventCreated() }) // delete bucket event 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.NewDeleteBucketEventDefault(int(err.Code)).WithPayload(err) } return user_api.NewDeleteBucketEventNoContent() }) @@ -125,11 +124,10 @@ func listBucketEvents(client MinioClient, bucketName string) ([]*models.Notifica } // getListBucketsResponse performs listBucketEvents() and serializes it to the handler's output -func getListBucketEventsResponse(session *models.Principal, params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, error) { +func getListBucketEventsResponse(session *models.Principal, params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, *models.Error) { mClient, err := newMinioClient(session) if err != nil { - log.Println("error creating MinIO Client:", err) - return nil, err + return nil, prepareError(err) } // create a minioClient interface implementation // defining the client to be used @@ -137,8 +135,7 @@ func getListBucketEventsResponse(session *models.Principal, params user_api.List bucketEvents, err := listBucketEvents(minioClient, params.BucketName) if err != nil { - log.Println("error listing bucket events:", err) - return nil, err + return nil, prepareError(err) } // serialize output listBucketsResponse := &models.ListBucketEventsResponse{ @@ -178,20 +175,18 @@ func createBucketEvent(ctx context.Context, client MCClient, arn string, notific } // getCreateBucketEventsResponse calls createBucketEvent to add a bucket event notification -func getCreateBucketEventsResponse(session *models.Principal, bucketName string, eventReq *models.BucketEventRequest) error { +func getCreateBucketEventsResponse(session *models.Principal, bucketName string, eventReq *models.BucketEventRequest) *models.Error { ctx := context.Background() s3Client, err := newS3BucketClient(session, bucketName) if err != nil { - log.Println("error creating S3Client:", err) - return err + return prepareError(err) } // create a mc S3Client interface implementation // defining the client to be used mcClient := mcClient{client: s3Client} err = createBucketEvent(ctx, mcClient, *eventReq.Configuration.Arn, eventReq.Configuration.Events, eventReq.Configuration.Prefix, eventReq.Configuration.Suffix, eventReq.IgnoreExisting) if err != nil { - log.Println("error creating bucket event:", err) - return err + return prepareError(err) } return nil } @@ -215,20 +210,18 @@ func joinNotificationEvents(events []models.NotificationEventType) string { } // getDeleteBucketEventsResponse calls deleteBucketEventNotification() to delete a bucket event notification -func getDeleteBucketEventsResponse(session *models.Principal, bucketName string, arn string, events []models.NotificationEventType, prefix, suffix *string) error { +func getDeleteBucketEventsResponse(session *models.Principal, bucketName string, arn string, events []models.NotificationEventType, prefix, suffix *string) *models.Error { ctx := context.Background() s3Client, err := newS3BucketClient(session, bucketName) if err != nil { - log.Println("error creating S3Client:", err) - return err + return prepareError(err) } // create a mc S3Client interface implementation // defining the client to be used mcClient := mcClient{client: s3Client} err = deleteBucketEventNotification(ctx, mcClient, arn, events, prefix, suffix) if err != nil { - log.Println("error deleting bucket event:", err) - return err + return prepareError(err) } return nil } diff --git a/restapi/user_login.go b/restapi/user_login.go index 180151073..047799e5a 100644 --- a/restapi/user_login.go +++ b/restapi/user_login.go @@ -18,11 +18,9 @@ package restapi import ( "context" - "errors" "log" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/pkg/acl" "github.com/minio/console/pkg/auth" @@ -32,17 +30,12 @@ import ( "github.com/minio/console/restapi/operations/user_api" ) -var ( - errorGeneric = errors.New("an error occurred, please try again") - errInvalidCredentials = errors.New("invalid Login") -) - func registerLoginHandlers(api *operations.ConsoleAPI) { // get login strategy api.UserAPILoginDetailHandler = user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder { loginDetails, err := getLoginDetailsResponse() if err != nil { - return user_api.NewLoginDetailDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) + return user_api.NewLoginDetailDefault(int(err.Code)).WithPayload(err) } return user_api.NewLoginDetailOK().WithPayload(loginDetails) }) @@ -50,21 +43,21 @@ func registerLoginHandlers(api *operations.ConsoleAPI) { api.UserAPILoginHandler = user_api.LoginHandlerFunc(func(params user_api.LoginParams) middleware.Responder { loginResponse, err := getLoginResponse(params.Body) if err != nil { - return user_api.NewLoginDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())}) + return user_api.NewLoginDefault(int(err.Code)).WithPayload(err) } return user_api.NewLoginCreated().WithPayload(loginResponse) }) api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder { loginResponse, err := getLoginOauth2AuthResponse(params.Body) if err != nil { - return user_api.NewLoginOauth2AuthDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())}) + return user_api.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err) } return user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse) }) api.UserAPILoginOperatorHandler = user_api.LoginOperatorHandlerFunc(func(params user_api.LoginOperatorParams) middleware.Responder { loginResponse, err := getLoginOperatorResponse(params.Body) if err != nil { - return user_api.NewLoginOperatorDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())}) + return user_api.NewLoginOperatorDefault(int(err.Code)).WithPayload(err) } return user_api.NewLoginOperatorCreated().WithPayload(loginResponse) }) @@ -76,8 +69,7 @@ func login(credentials ConsoleCredentials, actions []string) (*string, error) { // try to obtain consoleCredentials, tokens, err := credentials.Get() if err != nil { - log.Println("error authenticating user", err) - return nil, errInvalidCredentials + return nil, err } // if we made it here, the consoleCredentials work, generate a jwt with claims jwt, err := auth.NewEncryptedTokenForClient(&tokens, actions) @@ -103,32 +95,29 @@ func getConfiguredRegionForLogin(client MinioAdmin) (string, error) { } // getLoginResponse performs login() and serializes it to the handler's output -func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, error) { +func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, *models.Error) { ctx := context.Background() mAdmin, err := newSuperMAdminClient() if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, errorGeneric + return nil, prepareError(err) } adminClient := adminClient{client: mAdmin} // obtain the configured MinIO region // need it for user authentication location, err := getConfiguredRegionForLogin(adminClient) if err != nil { - return nil, err + return nil, prepareError(err) } creds, err := newConsoleCredentials(*lr.AccessKey, *lr.SecretKey, location) if err != nil { - log.Println("error login:", err) - return nil, errInvalidCredentials + return nil, prepareError(err) } credentials := consoleCredentials{consoleCredentials: creds} // obtain the current policy assigned to this user // necessary for generating the list of allowed endpoints userInfo, err := adminClient.getUserInfo(ctx, *lr.AccessKey) if err != nil { - log.Println("error login:", err) - return nil, errInvalidCredentials + return nil, prepareError(err) } policy, _ := adminClient.getPolicy(ctx, userInfo.PolicyName) // by default every user starts with an empty array of available actions @@ -141,7 +130,7 @@ func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, error) { } sessionID, err := login(credentials, actions) if err != nil { - return nil, err + return nil, prepareError(errInvalidCredentials, nil, err) } // serialize output loginResponse := &models.LoginResponse{ @@ -151,7 +140,7 @@ func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, error) { } // getLoginDetailsResponse returns information regarding the Console authentication mechanism. -func getLoginDetailsResponse() (*models.LoginDetails, error) { +func getLoginDetailsResponse() (*models.LoginDetails, *models.Error) { ctx := context.Background() loginStrategy := models.LoginDetailsLoginStrategyForm redirectURL := "" @@ -162,8 +151,7 @@ func getLoginDetailsResponse() (*models.LoginDetails, error) { // initialize new oauth2 client oauth2Client, err := oauth2.NewOauth2ProviderClient(ctx, nil) if err != nil { - log.Println("error getting new oauth2 provider client", err) - return nil, errorGeneric + return nil, prepareError(err) } // Validate user against IDP identityProvider := &auth.IdentityProvider{Client: oauth2Client} @@ -180,31 +168,29 @@ func loginOauth2Auth(ctx context.Context, provider *auth.IdentityProvider, code, userIdentity, err := provider.VerifyIdentity(ctx, code, state) if err != nil { log.Println("error validating user identity against idp:", err) - return nil, errorGeneric + return nil, errInvalidCredentials } return userIdentity, nil } -func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.LoginResponse, error) { +func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.LoginResponse, *models.Error) { ctx := context.Background() if oauth2.IsIdpEnabled() { // initialize new oauth2 client oauth2Client, err := oauth2.NewOauth2ProviderClient(ctx, nil) if err != nil { - log.Println("error getting new oauth2 client:", err) - return nil, errorGeneric + return nil, prepareError(err) } // initialize new identity provider identityProvider := &auth.IdentityProvider{Client: oauth2Client} // Validate user against IDP identity, err := loginOauth2Auth(ctx, identityProvider, *lr.Code, *lr.State) if err != nil { - return nil, err + return nil, prepareError(errInvalidCredentials, nil, err) } mAdmin, err := newSuperMAdminClient() if err != nil { - log.Println("error creating Madmin Client:", err) - return nil, errorGeneric + return nil, prepareError(err) } adminClient := adminClient{client: mAdmin} accessKey := identity.Email @@ -213,12 +199,11 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi // need it for user authentication location, err := getConfiguredRegionForLogin(adminClient) if err != nil { - return nil, err + return nil, prepareError(err) } // create user in MinIO if _, err := addUser(ctx, adminClient, &accessKey, &secretKey, []string{}); err != nil { - log.Println("error adding user:", err) - return nil, errorGeneric + return nil, prepareError(err) } // rollback user if there's an error after this point defer func() { @@ -231,26 +216,23 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi // assign the "consoleAdmin" policy to this user policyName := oauth2.GetIDPPolicyForUser() if err := setPolicy(ctx, adminClient, policyName, accessKey, models.PolicyEntityUser); err != nil { - log.Println("error setting policy:", err) - return nil, errorGeneric + return nil, prepareError(err) } // obtain the current policy details, necessary for generating the list of allowed endpoints policy, err := adminClient.getPolicy(ctx, policyName) if err != nil { - log.Println("error reading policy:", err) - return nil, errorGeneric + return nil, prepareError(err) } actions := acl.GetActionsStringFromPolicy(policy) // User was created correctly, create a new session/JWT creds, err := newConsoleCredentials(accessKey, secretKey, location) if err != nil { - log.Println("error login:", err) - return nil, errorGeneric + return nil, prepareError(err) } credentials := consoleCredentials{consoleCredentials: creds} jwt, err := login(credentials, actions) if err != nil { - return nil, err + return nil, prepareError(errInvalidCredentials, nil, err) } // serialize output loginResponse := &models.LoginResponse{ @@ -258,21 +240,20 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi } return loginResponse, nil } - return nil, errorGeneric + return nil, prepareError(errorGeneric) } // getLoginOperatorResponse validate the provided service account token against k8s api -func getLoginOperatorResponse(lmr *models.LoginOperatorRequest) (*models.LoginResponse, error) { +func getLoginOperatorResponse(lmr *models.LoginOperatorRequest) (*models.LoginResponse, *models.Error) { creds, err := newConsoleCredentials("", *lmr.Jwt, "") if err != nil { - log.Println("error login:", err) - return nil, errInvalidCredentials + return nil, prepareError(err) } credentials := consoleCredentials{consoleCredentials: creds} var actions []string jwt, err := login(credentials, actions) if err != nil { - return nil, err + return nil, prepareError(errInvalidCredentials, nil, err) } // serialize output loginResponse := &models.LoginResponse{ diff --git a/restapi/user_login_test.go b/restapi/user_login_test.go index f5a47abc1..7200ec3a2 100644 --- a/restapi/user_login_test.go +++ b/restapi/user_login_test.go @@ -100,7 +100,7 @@ func TestLoginOauth2Auth(t *testing.T) { return nil, errors.New("error") } if _, err := loginOauth2Auth(ctx, identityProvider, mockCode, mockState); funcAssert.Error(err) { - funcAssert.Equal("an error occurred, please try again", err.Error()) + funcAssert.Equal(errInvalidCredentials.Error(), err.Error()) } } diff --git a/restapi/user_service_accounts.go b/restapi/user_service_accounts.go index 4524cb7b3..509299a15 100644 --- a/restapi/user_service_accounts.go +++ b/restapi/user_service_accounts.go @@ -19,12 +19,10 @@ package restapi import ( "bytes" "context" - "log" "strings" "time" "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/user_api" @@ -36,7 +34,7 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) { 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.NewCreateServiceAccountDefault(int(err.Code)).WithPayload(err) } return user_api.NewCreateServiceAccountCreated().WithPayload(creds) }) @@ -44,7 +42,7 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) { 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())}) + return user_api.NewListUserServiceAccountsDefault(int(err.Code)).WithPayload(err) } return user_api.NewListUserServiceAccountsOK().WithPayload(serviceAccounts) }) @@ -52,7 +50,7 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) { // Delete a User's service account 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.NewDeleteServiceAccountDefault(int(err.Code)).WithPayload(err) } return user_api.NewDeleteServiceAccountNoContent() }) @@ -79,14 +77,13 @@ 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(session *models.Principal, serviceAccount *models.ServiceAccountRequest) (*models.ServiceAccountCreds, error) { +func getCreateServiceAccountResponse(session *models.Principal, serviceAccount *models.ServiceAccountRequest) (*models.ServiceAccountCreds, *models.Error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) defer cancel() userAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating user Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO user Admin Client interface implementation // defining the client to be used @@ -94,8 +91,7 @@ func getCreateServiceAccountResponse(session *models.Principal, serviceAccount * saCreds, err := createServiceAccount(ctx, userAdminClient, serviceAccount.Policy) if err != nil { - log.Println("error creating service account:", err) - return nil, err + return nil, prepareError(err) } return saCreds, nil } @@ -115,14 +111,13 @@ func getUserServiceAccounts(ctx context.Context, userClient MinioAdmin) (models. // getUserServiceAccountsResponse authenticates the user and calls // getUserServiceAccounts to list the user's service accounts -func getUserServiceAccountsResponse(session *models.Principal) (models.ServiceAccounts, error) { +func getUserServiceAccountsResponse(session *models.Principal) (models.ServiceAccounts, *models.Error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) defer cancel() userAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating user Client:", err) - return nil, err + return nil, prepareError(err) } // create a MinIO user Admin Client interface implementation // defining the client to be used @@ -130,11 +125,9 @@ func getUserServiceAccountsResponse(session *models.Principal) (models.ServiceAc serviceAccounts, err := getUserServiceAccounts(ctx, userAdminClient) if err != nil { - log.Println("error listing user's service account:", err) - return nil, err + return nil, prepareError(err) } return serviceAccounts, nil - } // deleteServiceAccount calls delete service account api @@ -143,22 +136,20 @@ func deleteServiceAccount(ctx context.Context, userClient MinioAdmin, accessKey } // getDeleteServiceAccountResponse authenticates the user and calls deleteServiceAccount -func getDeleteServiceAccountResponse(session *models.Principal, accessKey string) error { +func getDeleteServiceAccountResponse(session *models.Principal, accessKey string) *models.Error { ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) defer cancel() userAdmin, err := newMAdminClient(session) if err != nil { - log.Println("error creating user Client:", err) - return err + return prepareError(err) } // create a MinIO user Admin Client interface implementation // defining the client to be used userAdminClient := adminClient{client: userAdmin} if err := deleteServiceAccount(ctx, userAdminClient, accessKey); err != nil { - log.Println("error deleting user's service account:", err) - return err + return prepareError(err) } return nil } diff --git a/restapi/user_session.go b/restapi/user_session.go index 68d052580..40ddba40c 100644 --- a/restapi/user_session.go +++ b/restapi/user_session.go @@ -17,36 +17,29 @@ package restapi import ( - "errors" - "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/console/pkg/acl" "github.com/minio/console/restapi/operations" "github.com/minio/console/restapi/operations/user_api" ) -var ( - errorGenericInvalidSession = errors.New("invalid session") -) - func registerSessionHandlers(api *operations.ConsoleAPI) { // session check 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.NewSessionCheckDefault(int(err.Code)).WithPayload(err) } 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(session *models.Principal) (*models.SessionResponse, error) { +func getSessionResponse(session *models.Principal) (*models.SessionResponse, *models.Error) { // serialize output if session == nil { - return nil, errorGenericInvalidSession + return nil, prepareError(errorGenericInvalidSession) } sessionResp := &models.SessionResponse{ Pages: acl.GetAuthorizedEndpoints(session.Actions), diff --git a/swagger.yml b/swagger.yml index bd4d005bc..50ce3c44e 100644 --- a/swagger.yml +++ b/swagger.yml @@ -1355,7 +1355,7 @@ definitions: properties: code: type: integer - format: int64 + format: int32 message: type: string user: