2021-08-09 21:14:38 -04:00
|
|
|
// Copyright (c) 2015-2021 MinIO, Inc.
|
|
|
|
//
|
|
|
|
// This file is part of MinIO Object Storage stack
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"net/http"
|
|
|
|
|
2022-03-03 12:42:37 -05:00
|
|
|
"github.com/minio/kes"
|
2021-08-09 21:14:38 -04:00
|
|
|
"github.com/minio/madmin-go"
|
|
|
|
"github.com/minio/minio/internal/auth"
|
|
|
|
"github.com/minio/minio/internal/config"
|
|
|
|
iampolicy "github.com/minio/pkg/iam/policy"
|
|
|
|
)
|
|
|
|
|
2021-11-23 15:02:16 -05:00
|
|
|
func validateAdminReq(ctx context.Context, w http.ResponseWriter, r *http.Request, actions ...iampolicy.AdminAction) (ObjectLayer, auth.Credentials) {
|
2021-08-09 21:14:38 -04:00
|
|
|
// Get current object layer instance.
|
|
|
|
objectAPI := newObjectLayerFn()
|
|
|
|
if objectAPI == nil || globalNotificationSys == nil {
|
|
|
|
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL)
|
|
|
|
return nil, auth.Credentials{}
|
|
|
|
}
|
|
|
|
|
2021-11-23 15:02:16 -05:00
|
|
|
for _, action := range actions {
|
|
|
|
// Validate request signature.
|
|
|
|
cred, adminAPIErr := checkAdminRequestAuth(ctx, r, action, "")
|
|
|
|
if adminAPIErr != ErrNone {
|
|
|
|
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(adminAPIErr), r.URL)
|
|
|
|
return nil, cred
|
|
|
|
}
|
|
|
|
return objectAPI, cred
|
2021-08-09 21:14:38 -04:00
|
|
|
}
|
2021-11-23 15:02:16 -05:00
|
|
|
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL)
|
|
|
|
return nil, auth.Credentials{}
|
2021-08-09 21:14:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// AdminError - is a generic error for all admin APIs.
|
|
|
|
type AdminError struct {
|
|
|
|
Code string
|
|
|
|
Message string
|
|
|
|
StatusCode int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ae AdminError) Error() string {
|
|
|
|
return ae.Message
|
|
|
|
}
|
|
|
|
|
|
|
|
func toAdminAPIErr(ctx context.Context, err error) APIError {
|
|
|
|
if err == nil {
|
|
|
|
return noError
|
|
|
|
}
|
|
|
|
|
|
|
|
var apiErr APIError
|
|
|
|
switch e := err.(type) {
|
|
|
|
case iampolicy.Error:
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioMalformedIAMPolicy",
|
|
|
|
Description: e.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case config.Error:
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioConfigError",
|
|
|
|
Description: e.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case AdminError:
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: e.Code,
|
|
|
|
Description: e.Message,
|
|
|
|
HTTPStatusCode: e.StatusCode,
|
|
|
|
}
|
2021-12-14 17:09:57 -05:00
|
|
|
case SRError:
|
|
|
|
apiErr = errorCodes.ToAPIErrWithErr(e.Code, e.Cause)
|
2022-01-11 21:48:43 -05:00
|
|
|
case decomError:
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioDecommissionNotAllowed",
|
|
|
|
Description: e.Err,
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
2021-08-09 21:14:38 -04:00
|
|
|
default:
|
|
|
|
switch {
|
2022-01-10 20:26:00 -05:00
|
|
|
case errors.Is(err, errDecommissionAlreadyRunning):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioDecommissionNotAllowed",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case errors.Is(err, errDecommissionComplete):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioDecommissionNotAllowed",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
2021-08-09 21:14:38 -04:00
|
|
|
case errors.Is(err, errConfigNotFound):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioConfigError",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusNotFound,
|
|
|
|
}
|
|
|
|
case errors.Is(err, errIAMActionNotAllowed):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioIAMActionNotAllowed",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusForbidden,
|
|
|
|
}
|
2022-01-10 17:26:26 -05:00
|
|
|
case errors.Is(err, errIAMServiceAccount):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioIAMServiceAccount",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case errors.Is(err, errIAMServiceAccountUsed):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioIAMServiceAccountUsed",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
2021-08-09 21:14:38 -04:00
|
|
|
case errors.Is(err, errIAMNotInitialized):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioIAMNotInitialized",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusServiceUnavailable,
|
|
|
|
}
|
2021-11-03 22:47:49 -04:00
|
|
|
case errors.Is(err, errPolicyInUse):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminPolicyInUse",
|
|
|
|
Description: "The policy cannot be removed, as it is in use",
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
2022-03-03 12:42:37 -05:00
|
|
|
case errors.Is(err, kes.ErrKeyExists):
|
2021-08-09 21:14:38 -04:00
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioKMSKeyExists",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusConflict,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tier admin API errors
|
|
|
|
case errors.Is(err, madmin.ErrTierNameEmpty):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierNameEmpty",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case errors.Is(err, madmin.ErrTierInvalidConfig):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierInvalidConfig",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case errors.Is(err, madmin.ErrTierInvalidConfigVersion):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierInvalidConfigVersion",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case errors.Is(err, madmin.ErrTierTypeUnsupported):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierTypeUnsupported",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case errors.Is(err, errTierBackendInUse):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierBackendInUse",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusConflict,
|
|
|
|
}
|
2022-02-23 16:34:25 -05:00
|
|
|
case errors.Is(err, errTierBackendNotEmpty):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierBackendNotEmpty",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
2021-08-09 21:14:38 -04:00
|
|
|
case errors.Is(err, errTierInsufficientCreds):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierInsufficientCreds",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
case errIsTierPermError(err):
|
|
|
|
apiErr = APIError{
|
|
|
|
Code: "XMinioAdminTierInsufficientPermissions",
|
|
|
|
Description: err.Error(),
|
|
|
|
HTTPStatusCode: http.StatusBadRequest,
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
apiErr = errorCodes.ToAPIErrWithErr(toAdminAPIErrCode(ctx, err), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return apiErr
|
|
|
|
}
|
|
|
|
|
|
|
|
// toAdminAPIErrCode - converts errErasureWriteQuorum error to admin API
|
|
|
|
// specific error.
|
|
|
|
func toAdminAPIErrCode(ctx context.Context, err error) APIErrorCode {
|
|
|
|
switch err {
|
|
|
|
case errErasureWriteQuorum:
|
|
|
|
return ErrAdminConfigNoQuorum
|
|
|
|
default:
|
|
|
|
return toAPIErrorCode(ctx, err)
|
|
|
|
}
|
|
|
|
}
|