diff --git a/go.mod b/go.mod index 41785a2ffd..fe230198c7 100644 --- a/go.mod +++ b/go.mod @@ -150,7 +150,7 @@ require ( yunion.io/x/jsonutils v0.0.0-20201110084044-3e4e1cb49769 yunion.io/x/log v0.0.0-20201210064738-43181789dc74 yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7 - yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c + yunion.io/x/pkg v0.0.0-20210721081124-55078288ca4c yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e yunion.io/x/sqlchemy v0.0.0-20210401131841-cdb9ab689824 yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce diff --git a/go.sum b/go.sum index e8a0de5170..525660fbea 100644 --- a/go.sum +++ b/go.sum @@ -924,8 +924,8 @@ yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7/go.mod h1:0vLkNEhlmA64HViPB yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= -yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c h1:J/joqbA1N2mAlOl0Uqd4LpAq3+DK5aoFMdz+p9Ld7pQ= -yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= +yunion.io/x/pkg v0.0.0-20210721081124-55078288ca4c h1:/ejlt78/0xod4bdkEThUuYsQ7vLajd48wpL2GMMSaXs= +yunion.io/x/pkg v0.0.0-20210721081124-55078288ca4c/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo= yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo= yunion.io/x/sqlchemy v0.0.0-20210401131841-cdb9ab689824 h1:3/VcCiO+vr3+zZFLNvre41ARF2xE6NVq6Ue7JPFuJvU= diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index cfc02c7841..c49a784311 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -362,7 +362,7 @@ func (manager *SCloudaccountManager) ValidateCreateData( ) (api.CloudaccountCreateInput, error) { input, err := manager.validateCreateData(ctx, userCred, ownerId, query, input) if err != nil { - return input, errors.Wrap(err, "validateCreateData") + return input, err } input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput) @@ -505,8 +505,7 @@ func (manager *SCloudaccountManager) validateCreateData( if err == cloudprovider.ErrNoSuchProvder { return input, httperrors.NewResourceNotFoundError("no such provider %s", input.Provider) } - //log.Debugf("ValidateCreateData %s", err.Error()) - return input, httperrors.NewInputParameterError("invalid cloud account info error: %s", err.Error()) + return input, httperrors.NewGeneralError(err) } // check accountId uniqueness diff --git a/pkg/httperrors/consts.go b/pkg/httperrors/consts.go index e2845c79ba..afe2cce967 100644 --- a/pkg/httperrors/consts.go +++ b/pkg/httperrors/consts.go @@ -92,6 +92,8 @@ const ( ErrUserDisabled = errors.Error("UserDisabled") ErrWrongPassword = errors.Error("WrongPassword") ErrIncorrectUsernameOrPassword = errors.Error("IncorrectUsernameOrPassword") + + ErrInvalidAccessKey = errors.Error("InvalidAccessKey") ) var ( @@ -172,6 +174,8 @@ var ( ErrIncorrectUsernameOrPassword: 401, ErrPolicyDefinition: 409, + + ErrInvalidAccessKey: 400, } ) diff --git a/pkg/multicloud/aliyun/aliyun.go b/pkg/multicloud/aliyun/aliyun.go index 991c9d2e87..a8520e6bf9 100644 --- a/pkg/multicloud/aliyun/aliyun.go +++ b/pkg/multicloud/aliyun/aliyun.go @@ -33,6 +33,7 @@ import ( api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/util/httputils" ) @@ -138,7 +139,7 @@ func NewAliyunClient(cfg *AliyunClientConfig) (*SAliyunClient, error) { } err := client.fetchRegions() if err != nil { - return nil, errors.Wrap(err, "fetchRegions") + return nil, err } err = client.fetchBuckets() if err != nil { @@ -163,9 +164,14 @@ func jsonRequest(client *sdk.Client, domain, apiVersion, apiName string, params if e, ok := errors.Cause(err).(*alierr.ServerError); ok { code := e.ErrorCode() switch code { - case "InvalidAccessKeyId.NotFound": - return nil, err - case "404 Not Found": + case "InvalidAccessKeyId.NotFound", + "InvalidAccessKeyId", + "NoEnabledAccessKey", + "InvalidAccessKeyId.Inactive", + "Forbidden.AccessKeyDisabled", + "Forbidden.AccessKey": + return nil, errors.Wrapf(httperrors.ErrInvalidAccessKey, err.Error()) + case "404 Not Found", "InstanceNotFound": return nil, errors.Wrap(cloudprovider.ErrNotFound, err.Error()) case "InvalidInstance.NotSupported", "SignatureNonceUsed", // SignatureNonce 重复。每次请求的 SignatureNonce 在 15 分钟内不能重复。 diff --git a/pkg/multicloud/aws/aws.go b/pkg/multicloud/aws/aws.go index e7f1b68fd1..9fb870cbcb 100644 --- a/pkg/multicloud/aws/aws.go +++ b/pkg/multicloud/aws/aws.go @@ -41,6 +41,7 @@ import ( api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" ) const ( @@ -115,7 +116,7 @@ func NewAwsClient(cfg *AwsClientConfig) (*SAwsClient, error) { } _, err := client.fetchRegions() if err != nil { - return nil, errors.Wrap(err, "fetchRegions") + return nil, err } err = client.fetchOwnerId() if err != nil { @@ -204,6 +205,9 @@ func (self *SAwsClient) fetchRegions() ([]SRegion, error) { // https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.DescribeRegions result, err := svc.DescribeRegions(&ec2.DescribeRegionsInput{}) if err != nil { + if e, ok := err.(awserr.Error); ok && e.Code() == "AuthFailure" { + return nil, errors.Wrap(httperrors.ErrInvalidAccessKey, err.Error()) + } return nil, errors.Wrap(err, "DescribeRegions") } describeRegionResult[self.accessUrl] = result diff --git a/pkg/multicloud/azure/azure.go b/pkg/multicloud/azure/azure.go index 2b6f735620..f895b089c4 100644 --- a/pkg/multicloud/azure/azure.go +++ b/pkg/multicloud/azure/azure.go @@ -1,5 +1,4 @@ // Copyright 2019 Yunion -// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -35,6 +34,7 @@ import ( api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/util/httputils" ) @@ -685,6 +685,9 @@ func _jsonRequest(client *autorest.Client, method, domain, path string, body jso cli := httputils.NewJsonClient(client) header, body, err := cli.Send(context.TODO(), req, &ae, debug) if err != nil { + if strings.Contains(err.Error(), "azure.BearerAuthorizer#WithAuthorization") { + return nil, errors.Wrapf(httperrors.ErrInvalidAccessKey, err.Error()) + } return nil, err } locationFunc := func(head http.Header) string { diff --git a/pkg/multicloud/ecloud/request.go b/pkg/multicloud/ecloud/request.go index aa2131d4dc..3b71091177 100644 --- a/pkg/multicloud/ecloud/request.go +++ b/pkg/multicloud/ecloud/request.go @@ -22,7 +22,9 @@ import ( "time" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/util/httputils" ) @@ -250,6 +252,9 @@ func (br *SBaseRequest) ForMateResponseBody(jrbody jsonutils.JSONObject) (jsonut default: if jrbody.Contains("errorMessage") { msg, _ := jrbody.GetString("errorMessage") + if strings.Contains(msg, "Invalid parameter AccessKey") { + return nil, errors.Wrapf(httperrors.ErrInvalidAccessKey, msg) + } return nil, &httputils.JSONClientError{Code: 400, Details: msg} } return nil, &httputils.JSONClientError{Code: 400, Details: jrbody.String()} diff --git a/pkg/multicloud/huawei/client/modules/manager_base.go b/pkg/multicloud/huawei/client/modules/manager_base.go index b206045287..3ea6cb525e 100644 --- a/pkg/multicloud/huawei/client/modules/manager_base.go +++ b/pkg/multicloud/huawei/client/modules/manager_base.go @@ -27,6 +27,7 @@ import ( "yunion.io/x/pkg/errors" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/multicloud/huawei/client/auth" "yunion.io/x/onecloud/pkg/multicloud/huawei/client/requests" "yunion.io/x/onecloud/pkg/multicloud/huawei/client/responses" @@ -166,6 +167,7 @@ type HuaweiClientError struct { Errorcode []string err error Details string + ErrorCode string } func (ce *HuaweiClientError) Error() string { @@ -227,7 +229,9 @@ func (self *SBaseManager) jsonRequest(request requests.IRequest) (http.Header, j switch err := e.(type) { case *HuaweiClientError: - if err.Code == 499 && retry > 0 && request.GetMethod() == "GET" { + if err.ErrorCode == "APIGW.0301" { + return h, b, errors.Wrapf(httperrors.ErrInvalidAccessKey, e.Error()) + } else if err.Code == 499 && retry > 0 && request.GetMethod() == "GET" { retry -= 1 time.Sleep(3 * time.Second * time.Duration(MAX_RETRY-retry)) } else if (err.Code == 404 || strings.Contains(err.Details, "could not be found") || strings.Contains(err.Details, "does not exist")) && request.GetMethod() != "POST" { diff --git a/pkg/multicloud/huawei/huawei.go b/pkg/multicloud/huawei/huawei.go index ad7f2f950a..c037b7ba62 100644 --- a/pkg/multicloud/huawei/huawei.go +++ b/pkg/multicloud/huawei/huawei.go @@ -126,7 +126,7 @@ func NewHuaweiClient(cfg *HuaweiClientConfig) (*SHuaweiClient, error) { func (self *SHuaweiClient) init() error { err := self.fetchRegions() if err != nil { - return errors.Wrap(err, "fetchRegions") + return err } err = self.initSigner() if err != nil { diff --git a/pkg/multicloud/openstack/openstack.go b/pkg/multicloud/openstack/openstack.go index e14f6e9447..ce89939397 100644 --- a/pkg/multicloud/openstack/openstack.go +++ b/pkg/multicloud/openstack/openstack.go @@ -29,6 +29,7 @@ import ( api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/util/httputils" "yunion.io/x/onecloud/pkg/util/version" @@ -113,7 +114,7 @@ func NewOpenStackClient(cfg *OpenstackClientConfig) (*SOpenStackClient, error) { } err := cli.fetchToken() if err != nil { - return nil, errors.Wrap(err, "fetchToken") + return nil, err } return cli, cli.fetchRegions() } @@ -387,7 +388,7 @@ func (cli *SOpenStackClient) fetchToken() error { var err error cli.tokenCredential, err = cli.getDefaultToken() if err != nil { - return errors.Wrap(err, "getDefaultToken") + return err } return cli.checkEndpointType() } @@ -427,6 +428,11 @@ func (cli *SOpenStackClient) getDefaultToken() (mcclient.TokenCredential, error) client := cli.getDefaultClient() token, err := client.Authenticate(cli.username, cli.password, cli.domainName, cli.project, cli.projectDomain) if err != nil { + if e, ok := err.(*httputils.JSONClientError); ok { + if e.Class == "Unauthorized" { + return nil, errors.Wrapf(httperrors.ErrInvalidAccessKey, err.Error()) + } + } return nil, errors.Wrap(err, "Authenticate") } return token, nil diff --git a/pkg/multicloud/qcloud/qcloud.go b/pkg/multicloud/qcloud/qcloud.go index c4d85a6c27..53a9a9d4c8 100644 --- a/pkg/multicloud/qcloud/qcloud.go +++ b/pkg/multicloud/qcloud/qcloud.go @@ -40,6 +40,7 @@ import ( api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/util/httputils" ) @@ -462,6 +463,12 @@ func _baseJsonRequest(client *common.Client, req tchttp.Request, resp qcloudResp needRetry := false e, ok := err.(*sdkerrors.TencentCloudSDKError) if ok { + if utils.IsInStringArray(e.Code, []string{ + "AuthFailure.SecretIdNotFound", + "AuthFailure.SignatureFailure", + }) { + return nil, errors.Wrapf(httperrors.ErrInvalidAccessKey, err.Error()) + } if utils.IsInStringArray(e.Code, []string{ "InvalidParameter.RoleNotExist", "ResourceNotFound", diff --git a/pkg/multicloud/ucloud/client.go b/pkg/multicloud/ucloud/client.go index f4536067d1..6cc3d585a5 100644 --- a/pkg/multicloud/ucloud/client.go +++ b/pkg/multicloud/ucloud/client.go @@ -23,7 +23,9 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/errors" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/util/httputils" ) @@ -154,7 +156,9 @@ func parseUcloudResponse(params SParams, resp jsonutils.JSONObject) (jsonutils.J err.Action, _ = params.data.GetString("Action") if err.RetCode > 0 { - log.Debugf("Ucloud json request err %s", params.PrettyString()) + if err.RetCode == 171 { + return nil, errors.Wrapf(httperrors.ErrInvalidAccessKey, err.Error()) + } return nil, err } diff --git a/pkg/multicloud/zstack/zstack.go b/pkg/multicloud/zstack/zstack.go index 8ae97f1437..507d3389db 100644 --- a/pkg/multicloud/zstack/zstack.go +++ b/pkg/multicloud/zstack/zstack.go @@ -34,6 +34,7 @@ import ( api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/util/httputils" ) @@ -227,7 +228,12 @@ func (cli *SZStackClient) _list(resource string, start int, limit int, params ur } _, resp, err := httputils.JSONRequest(cli.httpClient, context.Background(), "GET", requestURL, header, nil, cli.debug) if err != nil { - return nil, errors.Wrapf(err, fmt.Sprintf("GET %s params: %s", resource, params)) + if e, ok := err.(*httputils.JSONClientError); ok { + if strings.Contains(e.Details, "wrong accessKey signature") || strings.Contains(e.Details, "access key id") { + return nil, errors.Wrapf(httperrors.ErrInvalidAccessKey, err.Error()) + } + } + return nil, err } return resp, nil } diff --git a/pkg/util/httputils/httputils.go b/pkg/util/httputils/httputils.go index 65ed4beeff..cfd89a52c9 100644 --- a/pkg/util/httputils/httputils.go +++ b/pkg/util/httputils/httputils.go @@ -30,6 +30,7 @@ import ( "os" "strconv" "strings" + "syscall" "time" "github.com/fatih/color" @@ -435,6 +436,28 @@ func GetDefaultClient() *http.Client { return GetClient(true, time.Second*15) } +func getClientErrorClass(err error) error { + cause := errors.Cause(err) + if urlErr, ok := cause.(*url.Error); ok { + if netErr, ok := urlErr.Err.(*net.OpError); ok { + switch t := netErr.Err.(type) { + case *net.DNSError: + return errors.ErrDNS + case *os.SyscallError: + if errno, ok := t.Err.(syscall.Errno); ok { + switch errno { + case syscall.ECONNREFUSED: + return errors.ErrConnectRefused + case syscall.ETIMEDOUT: + return errors.ErrTimeout + } + } + } + } + } + return errors.ErrClient +} + func Request(client sClient, ctx context.Context, method THttpMethod, urlStr string, header http.Header, body io.Reader, debug bool) (*http.Response, error) { req, resp, err := requestInternal(client, ctx, method, urlStr, header, body, debug) if err != nil { @@ -448,13 +471,13 @@ func Request(client sClient, ctx context.Context, method THttpMethod, urlStr str } if req == nil { ce := newJsonClientErrorFromRequest2(string(method), urlStr, header, reqBody) - ce.Class = string(errors.ErrClient) + ce.Class = getClientErrorClass(err).Error() ce.Details = err.Error() ce.Code = 499 return nil, ce } ce := newJsonClientErrorFromRequest(req, reqBody) - ce.Class = string(errors.ErrClient) + ce.Class = getClientErrorClass(err).Error() ce.Details = err.Error() ce.Code = 499 return nil, ce diff --git a/vendor/modules.txt b/vendor/modules.txt index 1964efde46..776e685bb1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1143,7 +1143,7 @@ yunion.io/x/log/hooks yunion.io/x/ovsdb/cli_util yunion.io/x/ovsdb/schema/ovn_nb yunion.io/x/ovsdb/types -# yunion.io/x/pkg v0.0.0-20210218105412-13a69f60034c +# yunion.io/x/pkg v0.0.0-20210721081124-55078288ca4c yunion.io/x/pkg/errors yunion.io/x/pkg/gotypes yunion.io/x/pkg/prettytable diff --git a/vendor/yunion.io/x/pkg/errors/consts.go b/vendor/yunion.io/x/pkg/errors/consts.go index 4ac451d15f..399142ec92 100644 --- a/vendor/yunion.io/x/pkg/errors/consts.go +++ b/vendor/yunion.io/x/pkg/errors/consts.go @@ -5,10 +5,16 @@ const ( ErrClient = Error("ClientError") ErrUnclassified = Error("UnclassifiedError") + // network error + ErrDNS = Error("DNSError") + ErrEOF = Error("EOFError") + ErrNetwork = Error("NetworkError") + ErrConnectRefused = Error("ConnectRefusedError") + ErrTimeout = Error("TimeoutError") + ErrNotFound = Error("NotFoundError") ErrDuplicateId = Error("DuplicateIdError") ErrInvalidStatus = Error("InvalidStatusError") - ErrTimeout = Error("TimeoutError") ErrNotImplemented = Error("NotImplementedError") ErrNotSupported = Error("NotSupportedError")