github.com/minio/console@v1.4.1/api/errors.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2022 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package api
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"strings"
    23  
    24  	"github.com/minio/minio-go/v7"
    25  
    26  	"github.com/minio/console/models"
    27  	"github.com/minio/madmin-go/v3"
    28  )
    29  
    30  var (
    31  	ErrDefault                          = errors.New("an error occurred, please try again")
    32  	ErrInvalidLogin                     = errors.New("invalid Login")
    33  	ErrForbidden                        = errors.New("403 Forbidden")
    34  	ErrBadRequest                       = errors.New("400 Bad Request")
    35  	ErrFileTooLarge                     = errors.New("413 File too Large")
    36  	ErrInvalidSession                   = errors.New("invalid session")
    37  	ErrNotFound                         = errors.New("not found")
    38  	ErrGroupAlreadyExists               = errors.New("error group name already in use")
    39  	ErrInvalidErasureCodingValue        = errors.New("invalid Erasure Coding Value")
    40  	ErrBucketBodyNotInRequest           = errors.New("error bucket body not in request")
    41  	ErrBucketNameNotInRequest           = errors.New("error bucket name not in request")
    42  	ErrGroupBodyNotInRequest            = errors.New("error group body not in request")
    43  	ErrGroupNameNotInRequest            = errors.New("error group name not in request")
    44  	ErrPolicyNameNotInRequest           = errors.New("error policy name not in request")
    45  	ErrPolicyBodyNotInRequest           = errors.New("error policy body not in request")
    46  	ErrPolicyNameContainsSpace          = errors.New("error policy name cannot contain spaces")
    47  	ErrInvalidEncryptionAlgorithm       = errors.New("error invalid encryption algorithm")
    48  	ErrSSENotConfigured                 = errors.New("error server side encryption configuration not found")
    49  	ErrBucketLifeCycleNotConfigured     = errors.New("error bucket life cycle configuration not found")
    50  	ErrChangePassword                   = errors.New("error please check your current password")
    51  	ErrInvalidLicense                   = errors.New("invalid license key")
    52  	ErrLicenseNotFound                  = errors.New("license not found")
    53  	ErrAvoidSelfAccountDelete           = errors.New("logged in user cannot be deleted by itself")
    54  	ErrAccessDenied                     = errors.New("access denied")
    55  	ErrOauth2Provider                   = errors.New("unable to contact configured identity provider")
    56  	ErrOauth2Login                      = errors.New("unable to login using configured identity provider")
    57  	ErrNonUniqueAccessKey               = errors.New("access key already in use")
    58  	ErrRemoteTierExists                 = errors.New("specified remote tier already exists")
    59  	ErrRemoteTierNotFound               = errors.New("specified remote tier was not found")
    60  	ErrRemoteTierUppercase              = errors.New("tier name must be in uppercase")
    61  	ErrRemoteTierBucketNotFound         = errors.New("remote tier bucket not found")
    62  	ErrRemoteInvalidCredentials         = errors.New("invalid remote tier credentials")
    63  	ErrUnableToGetTenantUsage           = errors.New("unable to get tenant usage")
    64  	ErrTooManyNodes                     = errors.New("cannot request more nodes than what is available in the cluster")
    65  	ErrTooFewNodes                      = errors.New("there are not enough nodes in the cluster to support this tenant")
    66  	ErrTooFewAvailableNodes             = errors.New("there is not enough available nodes to satisfy this requirement")
    67  	ErrFewerThanFourNodes               = errors.New("at least 4 nodes are required for a tenant")
    68  	ErrUnableToGetTenantLogs            = errors.New("unable to get tenant logs")
    69  	ErrUnableToUpdateTenantCertificates = errors.New("unable to update tenant certificates")
    70  	ErrUpdatingEncryptionConfig         = errors.New("unable to update encryption configuration")
    71  	ErrDeletingEncryptionConfig         = errors.New("error disabling tenant encryption")
    72  	ErrEncryptionConfigNotFound         = errors.New("encryption configuration not found")
    73  	ErrPolicyNotFound                   = errors.New("policy does not exist")
    74  	ErrLoginNotAllowed                  = errors.New("login not allowed")
    75  	ErrHealthReportFail                 = errors.New("failure to generate Health report")
    76  )
    77  
    78  type CodedAPIError struct {
    79  	Code     int
    80  	APIError *models.APIError
    81  }
    82  
    83  // ErrorWithContext :
    84  func ErrorWithContext(ctx context.Context, err ...interface{}) *CodedAPIError {
    85  	errorCode := 500
    86  	errorMessage := ErrDefault.Error()
    87  	var detailedMessage string
    88  	var err1 error
    89  	var exists bool
    90  	if len(err) > 0 {
    91  		if err1, exists = err[0].(error); exists {
    92  			detailedMessage = err1.Error()
    93  			var lastError error
    94  			if len(err) > 1 {
    95  				if err2, lastExists := err[1].(error); lastExists {
    96  					lastError = err2
    97  				}
    98  			}
    99  			if err1.Error() == ErrForbidden.Error() {
   100  				errorCode = 403
   101  			}
   102  			if err1.Error() == ErrBadRequest.Error() {
   103  				errorCode = 400
   104  			}
   105  			if err1 == ErrNotFound {
   106  				errorCode = 404
   107  				errorMessage = ErrNotFound.Error()
   108  			}
   109  			if errors.Is(err1, ErrInvalidLogin) {
   110  				detailedMessage = ""
   111  				errorCode = 401
   112  				errorMessage = ErrInvalidLogin.Error()
   113  			}
   114  			if strings.Contains(strings.ToLower(err1.Error()), ErrAccessDenied.Error()) {
   115  				errorCode = 403
   116  				errorMessage = err1.Error()
   117  			}
   118  			// If the last error is ErrInvalidLogin, this is a login failure
   119  			if errors.Is(lastError, ErrInvalidLogin) {
   120  				detailedMessage = ""
   121  				errorCode = 401
   122  				errorMessage = err1.Error()
   123  			}
   124  			if strings.Contains(err1.Error(), ErrLoginNotAllowed.Error()) {
   125  				detailedMessage = ""
   126  				errorCode = 400
   127  				errorMessage = ErrLoginNotAllowed.Error()
   128  			}
   129  			// console invalid erasure coding value
   130  			if errors.Is(err1, ErrInvalidErasureCodingValue) {
   131  				errorCode = 400
   132  				errorMessage = ErrInvalidErasureCodingValue.Error()
   133  			}
   134  			if errors.Is(err1, ErrBucketBodyNotInRequest) {
   135  				errorCode = 400
   136  				errorMessage = ErrBucketBodyNotInRequest.Error()
   137  			}
   138  			if errors.Is(err1, ErrBucketNameNotInRequest) {
   139  				errorCode = 400
   140  				errorMessage = ErrBucketNameNotInRequest.Error()
   141  			}
   142  			if errors.Is(err1, ErrGroupBodyNotInRequest) {
   143  				errorCode = 400
   144  				errorMessage = ErrGroupBodyNotInRequest.Error()
   145  			}
   146  			if errors.Is(err1, ErrGroupNameNotInRequest) {
   147  				errorCode = 400
   148  				errorMessage = ErrGroupNameNotInRequest.Error()
   149  			}
   150  			if errors.Is(err1, ErrPolicyNameNotInRequest) {
   151  				errorCode = 400
   152  				errorMessage = ErrPolicyNameNotInRequest.Error()
   153  			}
   154  			if errors.Is(err1, ErrPolicyBodyNotInRequest) {
   155  				errorCode = 400
   156  				errorMessage = ErrPolicyBodyNotInRequest.Error()
   157  			}
   158  			if errors.Is(err1, ErrPolicyNameContainsSpace) {
   159  				errorCode = 400
   160  				errorMessage = ErrPolicyNameContainsSpace.Error()
   161  			}
   162  			// console invalid session errors
   163  			if errors.Is(err1, ErrInvalidSession) {
   164  				errorCode = 401
   165  				errorMessage = ErrInvalidSession.Error()
   166  			}
   167  			if errors.Is(err1, ErrGroupAlreadyExists) {
   168  				errorCode = 400
   169  				errorMessage = ErrGroupAlreadyExists.Error()
   170  			}
   171  			// Bucket life cycle not configured
   172  			if errors.Is(err1, ErrBucketLifeCycleNotConfigured) {
   173  				errorCode = 404
   174  				errorMessage = ErrBucketLifeCycleNotConfigured.Error()
   175  			}
   176  			// Encryption not configured
   177  			if errors.Is(err1, ErrSSENotConfigured) {
   178  				errorCode = 404
   179  				errorMessage = ErrSSENotConfigured.Error()
   180  			}
   181  			if errors.Is(err1, ErrEncryptionConfigNotFound) {
   182  				errorCode = 404
   183  				errorMessage = err1.Error()
   184  			}
   185  			// account change password
   186  			if errors.Is(err1, ErrChangePassword) {
   187  				errorCode = 403
   188  				errorMessage = ErrChangePassword.Error()
   189  			}
   190  			if madmin.ToErrorResponse(err1).Code == "SignatureDoesNotMatch" {
   191  				errorCode = 403
   192  				errorMessage = ErrChangePassword.Error()
   193  			}
   194  			if errors.Is(err1, ErrLicenseNotFound) {
   195  				errorCode = 404
   196  				errorMessage = ErrLicenseNotFound.Error()
   197  			}
   198  			if errors.Is(err1, ErrInvalidLicense) {
   199  				errorCode = 404
   200  				errorMessage = ErrInvalidLicense.Error()
   201  			}
   202  			if errors.Is(err1, ErrAvoidSelfAccountDelete) {
   203  				errorCode = 403
   204  				errorMessage = ErrAvoidSelfAccountDelete.Error()
   205  			}
   206  			if errors.Is(err1, ErrAccessDenied) {
   207  				errorCode = 403
   208  				errorMessage = ErrAccessDenied.Error()
   209  			}
   210  			if errors.Is(err1, ErrPolicyNotFound) {
   211  				errorCode = 404
   212  				errorMessage = ErrPolicyNotFound.Error()
   213  			}
   214  			if madmin.ToErrorResponse(err1).Code == "AccessDenied" {
   215  				errorCode = 403
   216  				errorMessage = ErrAccessDenied.Error()
   217  			}
   218  			if madmin.ToErrorResponse(err1).Code == "InvalidAccessKeyId" {
   219  
   220  				errorCode = 401
   221  				errorMessage = ErrInvalidSession.Error()
   222  			}
   223  			// console invalid session errors
   224  			if madmin.ToErrorResponse(err1).Code == "XMinioAdminNoSuchUser" {
   225  				errorCode = 401
   226  				errorMessage = ErrInvalidSession.Error()
   227  			}
   228  			// tiering errors
   229  			if err1.Error() == ErrRemoteTierExists.Error() {
   230  				errorCode = 400
   231  				errorMessage = err1.Error()
   232  			}
   233  			if err1.Error() == ErrRemoteTierNotFound.Error() {
   234  				errorCode = 400
   235  				errorMessage = err1.Error()
   236  			}
   237  
   238  			if err1.Error() == ErrRemoteTierUppercase.Error() {
   239  				errorCode = 400
   240  				errorMessage = err1.Error()
   241  			}
   242  			if err1.Error() == ErrRemoteTierBucketNotFound.Error() {
   243  				errorCode = 400
   244  				errorMessage = err1.Error()
   245  			}
   246  			if err1.Error() == ErrRemoteInvalidCredentials.Error() {
   247  				errorCode = 403
   248  				errorMessage = err1.Error()
   249  			}
   250  			if err1.Error() == ErrFileTooLarge.Error() {
   251  				errorCode = 413
   252  				errorMessage = err1.Error()
   253  			}
   254  			// bucket already exists
   255  			if minio.ToErrorResponse(err1).Code == "BucketAlreadyOwnedByYou" {
   256  				errorCode = 400
   257  				errorMessage = "Bucket already exists"
   258  			}
   259  
   260  			LogError("ErrorWithContext:%v", err...)
   261  			LogIf(ctx, err1, err...)
   262  		}
   263  
   264  		if len(err) > 1 && err[1] != nil {
   265  			if err2, ok := err[1].(error); ok {
   266  				errorMessage = err2.Error()
   267  			}
   268  		}
   269  	}
   270  	return &CodedAPIError{Code: errorCode, APIError: &models.APIError{Message: errorMessage, DetailedMessage: detailedMessage}}
   271  }
   272  
   273  // Error receives an errors object and parse it against k8sErrors, returns the right errors code paired with a generic errors message
   274  func Error(err ...interface{}) *CodedAPIError {
   275  	ctx, cancel := context.WithCancel(context.Background())
   276  	defer cancel()
   277  	return ErrorWithContext(ctx, err...)
   278  }