From 0feb31c29dceed39ef83705957c25750cec6d0f1 Mon Sep 17 00:00:00 2001 From: ioito Date: Fri, 8 Apr 2022 20:42:35 +0800 Subject: [PATCH] fix(region): cloud lake of permissions --- pkg/cloudprovider/transport.go | 23 +++++-- pkg/multicloud/aliyun/aliyun.go | 96 ++++++++++++++++----------- pkg/multicloud/aliyun/business.go | 2 +- pkg/multicloud/aliyun/monitor.go | 2 +- pkg/multicloud/aliyun/ram.go | 2 +- pkg/multicloud/aliyun/region.go | 24 +++---- pkg/multicloud/aliyun/sts.go | 2 +- pkg/multicloud/apsara/apsara.go | 56 +++++++++++----- pkg/multicloud/aws/aws.go | 58 ++++++++++------ pkg/multicloud/azure/azure.go | 8 +-- pkg/multicloud/cloudpods/cloudpods.go | 10 +-- pkg/multicloud/ctyun/ctyun.go | 8 +-- pkg/multicloud/google/google.go | 20 ++++-- pkg/multicloud/hcso/huawei.go | 16 ++--- pkg/multicloud/hcso/region.go | 8 +-- pkg/multicloud/huawei/huawei.go | 70 +++++++++++-------- pkg/multicloud/huawei/region.go | 13 ---- pkg/multicloud/nutanix/nutanix.go | 8 +-- pkg/multicloud/openstack/openstack.go | 10 +-- pkg/multicloud/qcloud/qcloud.go | 50 +++++++++----- pkg/multicloud/ucloud/ucloud.go | 14 ++-- pkg/multicloud/zstack/zstack.go | 10 +-- 22 files changed, 308 insertions(+), 202 deletions(-) diff --git a/pkg/cloudprovider/transport.go b/pkg/cloudprovider/transport.go index d7d584872b..3e8cb6982c 100644 --- a/pkg/cloudprovider/transport.go +++ b/pkg/cloudprovider/transport.go @@ -17,19 +17,30 @@ package cloudprovider import "net/http" type transport struct { - readOnlyCheck func(req *http.Request) error - ts *http.Transport + check func(*http.Request) (func(resp *http.Response), error) + ts *http.Transport } func (self *transport) RoundTrip(req *http.Request) (*http.Response, error) { - err := self.readOnlyCheck(req) + var respCheck func(resp *http.Response) = nil + var err error + if self.check != nil { + respCheck, err = self.check(req) + if err != nil { + return nil, err + } + } + resp, err := self.ts.RoundTrip(req) if err != nil { return nil, err } - return self.ts.RoundTrip(req) + if respCheck != nil { + respCheck(resp) + } + return resp, nil } -func GetReadOnlyCheckTransport(ts *http.Transport, check func(req *http.Request) error) http.RoundTripper { - ret := &transport{ts: ts, readOnlyCheck: check} +func GetCheckTransport(ts *http.Transport, check func(*http.Request) (func(resp *http.Response), error)) http.RoundTripper { + ret := &transport{ts: ts, check: check} return ret } diff --git a/pkg/multicloud/aliyun/aliyun.go b/pkg/multicloud/aliyun/aliyun.go index 8ba3742770..1b7ce4b70f 100644 --- a/pkg/multicloud/aliyun/aliyun.go +++ b/pkg/multicloud/aliyun/aliyun.go @@ -15,7 +15,9 @@ package aliyun import ( + "bytes" "fmt" + "io/ioutil" "net/http" "net/url" "strings" @@ -161,11 +163,10 @@ func NewAliyunClient(cfg *AliyunClientConfig) (*SAliyunClient, error) { return &client, nil } -func jsonRequest(client *sdk.Client, domain, apiVersion, apiName string, params map[string]string, updateFunc func(string, string), debug bool) (jsonutils.JSONObject, error) { +func jsonRequest(client *sdk.Client, domain, apiVersion, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) { if debug { log.Debugf("request %s %s %s %s", domain, apiVersion, apiName, params) } - service := strings.Split(domain, ".")[0] var resp jsonutils.JSONObject var err error for i := 1; i < 4; i++ { @@ -182,16 +183,8 @@ 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 "NoPermission", "Forbidden.RAM", "SubAccountNoPermission", "Forbidden": - if updateFunc != nil { - updateFunc(service, apiName) - } - return nil, errors.Wrapf(httperrors.ErrNoPermission, err.Error()) case "InternalError": if apiName == "QueryAccountBalance" { - if updateFunc != nil { - updateFunc(service, apiName) - } return nil, errors.Wrapf(httperrors.ErrNoPermission, err.Error()) } return nil, err @@ -346,7 +339,7 @@ func (self *SAliyunClient) fetchNasEndpoints() error { if err != nil { return errors.Wrapf(err, "getDefaultClient") } - resp, err := jsonRequest(client, "nas.aliyuncs.com", ALIYUN_NAS_API_VERSION, "DescribeRegions", nil, self.cpcfg.UpdatePermission, self.debug) + resp, err := jsonRequest(client, "nas.aliyuncs.com", ALIYUN_NAS_API_VERSION, "DescribeRegions", nil, self.debug) if err != nil { return errors.Wrapf(err, "DescribeRegions") } @@ -386,7 +379,7 @@ func (self *SAliyunClient) fetchVpcEndpoints() error { if err != nil { return errors.Wrapf(err, "getDefaultClient") } - resp, err := jsonRequest(client, "vpc.aliyuncs.com", ALIYUN_API_VERSION_VPC, "DescribeRegions", nil, self.cpcfg.UpdatePermission, self.debug) + resp, err := jsonRequest(client, "vpc.aliyuncs.com", ALIYUN_API_VERSION_VPC, "DescribeRegions", nil, self.debug) if err != nil { return errors.Wrapf(err, "DescribeRegions") } @@ -408,21 +401,44 @@ func (self *SAliyunClient) getSdkClient(regionId string) (*sdk.Client, error) { regionId, &sdk.Config{ HttpTransport: transport, - Transport: cloudprovider.GetReadOnlyCheckTransport(transport, func(req *http.Request) error { - if self.cpcfg.ReadOnly { - params, err := url.ParseQuery(req.URL.RawQuery) - if err != nil { - return errors.Wrapf(err, "ParseQuery(%s)", req.URL.RawQuery) - } - action := params.Get("Action") - for _, prefix := range []string{"Get", "List", "Describe"} { - if strings.HasPrefix(action, prefix) { - return nil + Transport: cloudprovider.GetCheckTransport(transport, func(req *http.Request) (func(resp *http.Response), error) { + params, err := url.ParseQuery(req.URL.RawQuery) + if err != nil { + return nil, errors.Wrapf(err, "ParseQuery(%s)", req.URL.RawQuery) + } + service := strings.Split(req.URL.Host, ".")[0] + action := params.Get("Action") + respCheck := func(resp *http.Response) { + if self.cpcfg.UpdatePermission != nil && resp.StatusCode >= 400 && resp.ContentLength > 0 { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + resp.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + obj, err := jsonutils.Parse(body) + if err != nil { + return + } + ret := struct{ Code string }{} + obj.Unmarshal(&ret) + if utils.IsInStringArray(ret.Code, []string{ + "NoPermission", + "SubAccountNoPermission", + }) || utils.HasPrefix(ret.Code, "Forbidden") || + action == "QueryAccountBalance" && ret.Code == "InternalError" { + self.cpcfg.UpdatePermission(service, action) } } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) } - return nil + for _, prefix := range []string{"Get", "List", "Describe"} { + if strings.HasPrefix(action, prefix) { + return respCheck, nil + } + } + if self.cpcfg.ReadOnly { + return respCheck, errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) + } + return respCheck, nil }), }, &credentials.BaseCredential{ @@ -438,7 +454,7 @@ func (self *SAliyunClient) imsRequest(apiName string, params map[string]string) if err != nil { return nil, err } - return jsonRequest(cli, "ims.aliyuncs.com", ALIYUN_IMS_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "ims.aliyuncs.com", ALIYUN_IMS_API_VERSION, apiName, params, self.debug) } func (self *SAliyunClient) rmRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -446,7 +462,7 @@ func (self *SAliyunClient) rmRequest(apiName string, params map[string]string) ( if err != nil { return nil, err } - return jsonRequest(cli, "resourcemanager.aliyuncs.com", ALIYUN_RM_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "resourcemanager.aliyuncs.com", ALIYUN_RM_API_VERSION, apiName, params, self.debug) } func (self *SAliyunClient) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -454,7 +470,7 @@ func (self *SAliyunClient) ecsRequest(apiName string, params map[string]string) if err != nil { return nil, err } - return jsonRequest(cli, "ecs.aliyuncs.com", ALIYUN_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "ecs.aliyuncs.com", ALIYUN_API_VERSION, apiName, params, self.debug) } func (self *SAliyunClient) pvtzRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -462,7 +478,7 @@ func (self *SAliyunClient) pvtzRequest(apiName string, params map[string]string) if err != nil { return nil, err } - return jsonRequest(cli, "pvtz.aliyuncs.com", ALIYUN_PVTZ_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "pvtz.aliyuncs.com", ALIYUN_PVTZ_API_VERSION, apiName, params, self.debug) } func (self *SAliyunClient) alidnsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -470,7 +486,7 @@ func (self *SAliyunClient) alidnsRequest(apiName string, params map[string]strin if err != nil { return nil, err } - return jsonRequest(cli, "alidns.aliyuncs.com", ALIYUN_ALIDNS_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "alidns.aliyuncs.com", ALIYUN_ALIDNS_API_VERSION, apiName, params, self.debug) } func (self *SAliyunClient) cbnRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -478,7 +494,7 @@ func (self *SAliyunClient) cbnRequest(apiName string, params map[string]string) if err != nil { return nil, err } - return jsonRequest(cli, "cbn.aliyuncs.com", ALIYUN_CBN_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "cbn.aliyuncs.com", ALIYUN_CBN_API_VERSION, apiName, params, self.debug) } func (self *SAliyunClient) cdnRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -486,7 +502,7 @@ func (self *SAliyunClient) cdnRequest(apiName string, params map[string]string) if err != nil { return nil, err } - return jsonRequest(cli, "cdn.aliyuncs.com", ALIYUN_CDN_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "cdn.aliyuncs.com", ALIYUN_CDN_API_VERSION, apiName, params, self.debug) } func (self *SAliyunClient) fetchRegions() error { @@ -531,14 +547,20 @@ func (client *SAliyunClient) getOssClientByEndpoint(endpoint string) (*oss.Clien // oss use no timeout client so as to send/download large files httpClient := client.cpcfg.AdaptiveTimeoutHttpClient() transport, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(transport, func(req *http.Request) error { - if client.cpcfg.ReadOnly { - if req.Method == "GET" { - return nil + httpClient.Transport = cloudprovider.GetCheckTransport(transport, func(req *http.Request) (func(resp *http.Response), error) { + path, method := req.URL.Path, req.Method + respCheck := func(resp *http.Response) { + if client.cpcfg.UpdatePermission != nil && resp.StatusCode == 403 { + client.cpcfg.UpdatePermission("oss", fmt.Sprintf("%s %s", method, path)) } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.RawPath) } - return nil + if client.cpcfg.ReadOnly { + if req.Method == "GET" || req.Method == "HEAD" { + return respCheck, nil + } + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.RawPath) + } + return respCheck, nil }) cliOpts := []oss.ClientOption{ oss.HTTPClient(httpClient), diff --git a/pkg/multicloud/aliyun/business.go b/pkg/multicloud/aliyun/business.go index 42caed4b67..daf68f4ede 100644 --- a/pkg/multicloud/aliyun/business.go +++ b/pkg/multicloud/aliyun/business.go @@ -29,7 +29,7 @@ func (self *SAliyunClient) businessRequest(apiName string, params map[string]str if err != nil { return nil, err } - return jsonRequest(cli, "business.aliyuncs.com", ALIYUN_BSS_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "business.aliyuncs.com", ALIYUN_BSS_API_VERSION, apiName, params, self.debug) } type SAccountBalance struct { diff --git a/pkg/multicloud/aliyun/monitor.go b/pkg/multicloud/aliyun/monitor.go index e140a20d5b..2f8780f463 100644 --- a/pkg/multicloud/aliyun/monitor.go +++ b/pkg/multicloud/aliyun/monitor.go @@ -31,7 +31,7 @@ func (r *SRegion) metricsRequest(action string, params map[string]string) (jsonu if err != nil { return nil, errors.Wrap(err, "r.getSdkClient") } - return jsonRequest(client, "metrics.aliyuncs.com", ALIYUN_API_VERSION_METRICS, action, params, r.client.cpcfg.UpdatePermission, r.client.debug) + return jsonRequest(client, "metrics.aliyuncs.com", ALIYUN_API_VERSION_METRICS, action, params, r.client.debug) } type SResourceLabel struct { diff --git a/pkg/multicloud/aliyun/ram.go b/pkg/multicloud/aliyun/ram.go index 081400311a..fc502a5239 100644 --- a/pkg/multicloud/aliyun/ram.go +++ b/pkg/multicloud/aliyun/ram.go @@ -23,5 +23,5 @@ func (self *SAliyunClient) ramRequest(apiName string, params map[string]string) if err != nil { return nil, err } - return jsonRequest(cli, "ram.aliyuncs.com", ALIYUN_RAM_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "ram.aliyuncs.com", ALIYUN_RAM_API_VERSION, apiName, params, self.debug) } diff --git a/pkg/multicloud/aliyun/region.go b/pkg/multicloud/aliyun/region.go index e5328b6cb1..4126ddae15 100644 --- a/pkg/multicloud/aliyun/region.go +++ b/pkg/multicloud/aliyun/region.go @@ -137,7 +137,7 @@ func (self *SRegion) ecsRequest(apiName string, params map[string]string) (jsonu if len(endpoint) == 0 { endpoint = "ecs.aliyuncs.com" } - return jsonRequest(client, endpoint, ALIYUN_API_VERSION, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, endpoint, ALIYUN_API_VERSION, apiName, params, self.client.debug) } func (self *SRegion) wafRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -149,7 +149,7 @@ func (self *SRegion) wafRequest(apiName string, params map[string]string) (jsonu return nil, cloudprovider.ErrNotSupported } endpoint := fmt.Sprintf("wafopenapi.%s.aliyuncs.com", self.RegionId) - return jsonRequest(client, endpoint, ALIYUN_WAF_API_VERSION, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, endpoint, ALIYUN_WAF_API_VERSION, apiName, params, self.client.debug) } func (self *SRegion) esRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -158,7 +158,7 @@ func (self *SRegion) esRequest(apiName string, params map[string]string) (jsonut return nil, err } domain := fmt.Sprintf("elasticsearch.%s.aliyuncs.com", self.RegionId) - return jsonRequest(client, domain, ALIYUN_ES_API_VERSION, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, domain, ALIYUN_ES_API_VERSION, apiName, params, self.client.debug) } func (self *SRegion) kafkaRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -167,7 +167,7 @@ func (self *SRegion) kafkaRequest(apiName string, params map[string]string) (jso return nil, err } domain := fmt.Sprintf("alikafka.%s.aliyuncs.com", self.RegionId) - return jsonRequest(client, domain, ALIYUN_KAFKA_API_VERSION, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, domain, ALIYUN_KAFKA_API_VERSION, apiName, params, self.client.debug) } func (self *SRegion) rdsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -175,7 +175,7 @@ func (self *SRegion) rdsRequest(apiName string, params map[string]string) (jsonu if err != nil { return nil, err } - return jsonRequest(client, "rds.aliyuncs.com", ALIYUN_RDS_API_VERSION, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, "rds.aliyuncs.com", ALIYUN_RDS_API_VERSION, apiName, params, self.client.debug) } func (self *SRegion) k8sRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -183,7 +183,7 @@ func (self *SRegion) k8sRequest(apiName string, params map[string]string) (jsonu if err != nil { return nil, err } - return jsonRequest(client, fmt.Sprintf("cs.%s.aliyuncs.com", self.RegionId), ALIYUN_K8S_API_VERSION, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, fmt.Sprintf("cs.%s.aliyuncs.com", self.RegionId), ALIYUN_K8S_API_VERSION, apiName, params, self.client.debug) } func (self *SRegion) mongodbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { @@ -191,7 +191,7 @@ func (self *SRegion) mongodbRequest(apiName string, params map[string]string) (j if err != nil { return nil, err } - return jsonRequest(client, "mongodb.aliyuncs.com", ALIYUN_MONGO_DB_API_VERSION, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, "mongodb.aliyuncs.com", ALIYUN_MONGO_DB_API_VERSION, apiName, params, self.client.debug) } func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { @@ -200,7 +200,7 @@ func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonut return nil, err } endpoint := self.GetClient().getVpcEndpoint(self.RegionId) - return jsonRequest(client, endpoint, ALIYUN_API_VERSION_VPC, action, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, endpoint, ALIYUN_API_VERSION_VPC, action, params, self.client.debug) } func (self *SRegion) nasRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { @@ -223,7 +223,7 @@ func (self *SRegion) nasRequest(action string, params map[string]string) (jsonut } endpint := self.GetClient().getNasEndpoint(self.RegionId) - return jsonRequest(client, endpint, ALIYUN_NAS_API_VERSION, action, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, endpint, ALIYUN_NAS_API_VERSION, action, params, self.client.debug) } func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { @@ -236,7 +236,7 @@ func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonut params["RegionId"] = transRegionIdFromEcsRegionId(self, "redis") } - return jsonRequest(client, "r-kvstore.aliyuncs.com", ALIYUN_API_VERSION_KVS, action, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, "r-kvstore.aliyuncs.com", ALIYUN_API_VERSION_KVS, action, params, self.client.debug) } type LBRegion struct { @@ -286,7 +286,7 @@ func (self *SRegion) lbRequest(apiName string, params map[string]string) (jsonut } func (self *SRegion) _lbRequest(client *sdk.Client, apiName string, domain string, params map[string]string) (jsonutils.JSONObject, error) { - return jsonRequest(client, domain, ALIYUN_API_VERSION_LB, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, domain, ALIYUN_API_VERSION_LB, apiName, params, self.client.debug) } ///////////////////////////////////////////////////////////////////////////// @@ -1240,5 +1240,5 @@ func (self *SRegion) trialRequest(apiName string, params map[string]string) (jso return nil, err } domain := fmt.Sprintf("actiontrail.%s.aliyuncs.com", self.RegionId) - return jsonRequest(client, domain, ALIYUN_API_VERSION_TRIAL, apiName, params, self.client.cpcfg.UpdatePermission, self.client.debug) + return jsonRequest(client, domain, ALIYUN_API_VERSION_TRIAL, apiName, params, self.client.debug) } diff --git a/pkg/multicloud/aliyun/sts.go b/pkg/multicloud/aliyun/sts.go index 441e5613fe..b5c3f5e956 100644 --- a/pkg/multicloud/aliyun/sts.go +++ b/pkg/multicloud/aliyun/sts.go @@ -23,7 +23,7 @@ func (self *SAliyunClient) stsRequest(apiName string, params map[string]string) if err != nil { return nil, err } - return jsonRequest(cli, "sts.aliyuncs.com", ALIYUN_STS_API_VERSION, apiName, params, self.cpcfg.UpdatePermission, self.debug) + return jsonRequest(cli, "sts.aliyuncs.com", ALIYUN_STS_API_VERSION, apiName, params, self.debug) } type SCallerIdentity struct { diff --git a/pkg/multicloud/apsara/apsara.go b/pkg/multicloud/apsara/apsara.go index 66acf7e070..2b1fcd58c1 100644 --- a/pkg/multicloud/apsara/apsara.go +++ b/pkg/multicloud/apsara/apsara.go @@ -15,8 +15,10 @@ package apsara import ( + "bytes" "crypto/tls" "fmt" + "io/ioutil" "net/http" "net/url" "strings" @@ -279,21 +281,43 @@ func (self *SApsaraClient) getDefaultClient(regionId string) (*sdk.Client, error regionId, &sdk.Config{ HttpTransport: transport, - Transport: cloudprovider.GetReadOnlyCheckTransport(transport, func(req *http.Request) error { - if self.cpcfg.ReadOnly { - params, err := url.ParseQuery(req.URL.RawQuery) - if err != nil { - return errors.Wrapf(err, "ParseQuery(%s)", req.URL.RawQuery) - } - action := params.Get("Action") - for _, prefix := range []string{"Get", "List", "Describe"} { - if strings.HasPrefix(action, prefix) { - return nil + Transport: cloudprovider.GetCheckTransport(transport, func(req *http.Request) (func(resp *http.Response), error) { + params, err := url.ParseQuery(req.URL.RawQuery) + if err != nil { + return nil, errors.Wrapf(err, "ParseQuery(%s)", req.URL.RawQuery) + } + action := params.Get("Action") + service := strings.ToLower(params.Get("Product")) + respCheck := func(resp *http.Response) { + if self.cpcfg.UpdatePermission != nil { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + resp.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + obj, err := jsonutils.Parse(body) + if err != nil { + return + } + ret := struct { + AsapiErrorCode string `json:"asapiErrorCode"` + Code int + }{} + obj.Unmarshal(&ret) + if ret.Code == 403 || strings.Contains(ret.AsapiErrorCode, "NoPermission") { + self.cpcfg.UpdatePermission(service, action) } } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) } - return nil + if self.cpcfg.ReadOnly { + for _, prefix := range []string{"Get", "List", "Describe"} { + if strings.HasPrefix(action, prefix) { + return respCheck, nil + } + } + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) + } + return respCheck, nil }), }, &credentials.BaseCredential{ @@ -366,14 +390,14 @@ func (client *SApsaraClient) getOssClient(regionId string) (*oss.Client, error) // oss use no timeout client so as to send/download large files httpClient := client.cpcfg.AdaptiveTimeoutHttpClient() transport, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(transport, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(transport, func(req *http.Request) (func(resp *http.Response), error) { if client.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) cliOpts := []oss.ClientOption{ oss.HTTPClient(httpClient), diff --git a/pkg/multicloud/aws/aws.go b/pkg/multicloud/aws/aws.go index b82367291c..27e9511140 100644 --- a/pkg/multicloud/aws/aws.go +++ b/pkg/multicloud/aws/aws.go @@ -244,33 +244,51 @@ func (client *SAwsClient) getAwsSession(regionId string, assumeRole bool) (*sess } httpClient := client.cpcfg.AdaptiveTimeoutHttpClient() transport, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(transport, func(req *http.Request) error { - if client.cpcfg.ReadOnly { - if req.ContentLength > 0 { - body, err := ioutil.ReadAll(req.Body) - if err != nil { - return errors.Wrapf(err, "ioutil.ReadAll") - } - req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) - params, err := url.ParseQuery(string(body)) - if err != nil { - return errors.Wrapf(err, "ParseQuery(%s)", string(body)) - } - action := params.Get("Action") - for _, prefix := range []string{"Get", "List", "Describe"} { - if strings.HasPrefix(action, prefix) { - return nil + httpClient.Transport = cloudprovider.GetCheckTransport(transport, func(req *http.Request) (func(resp *http.Response), error) { + var action string + if req.ContentLength > 0 { + body, err := ioutil.ReadAll(req.Body) + if err != nil { + return nil, errors.Wrapf(err, "ioutil.ReadAll") + } + req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + params, err := url.ParseQuery(string(body)) + if err != nil { + return nil, errors.Wrapf(err, "ParseQuery(%s)", string(body)) + } + action = params.Get("Action") + } + + service := strings.Split(req.URL.Host, ".")[0] + method, path := req.Method, req.URL.Path + respCheck := func(resp *http.Response) { + if resp.StatusCode == 403 { + if client.cpcfg.UpdatePermission != nil { + if len(action) > 0 { + client.cpcfg.UpdatePermission(service, action) + } else { // s3 + client.cpcfg.UpdatePermission(service, fmt.Sprintf("%s %s", method, path)) } } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) + } + } + + if client.cpcfg.ReadOnly { + if len(action) > 0 { + for _, prefix := range []string{"Get", "List", "Describe"} { + if strings.HasPrefix(action, prefix) { + return respCheck, nil + } + } + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) } // s3 if req.Method == "GET" || req.Method == "HEAD" { - return nil + return respCheck, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return respCheck, nil }) s, err := session.NewSession(&sdk.Config{ Region: sdk.String(regionId), diff --git a/pkg/multicloud/azure/azure.go b/pkg/multicloud/azure/azure.go index cd62cf61c6..1491ac3ff9 100644 --- a/pkg/multicloud/azure/azure.go +++ b/pkg/multicloud/azure/azure.go @@ -159,14 +159,14 @@ func (self *SAzureClient) getClient(resource TAzureResource) (*autorest.Client, httpClient := self.cpcfg.AdaptiveTimeoutHttpClient() transport, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(transport, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(transport, func(req *http.Request) (func(resp *http.Response), error) { if self.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) client.Sender = httpClient diff --git a/pkg/multicloud/cloudpods/cloudpods.go b/pkg/multicloud/cloudpods/cloudpods.go index 873914ffab..0953a8f13e 100644 --- a/pkg/multicloud/cloudpods/cloudpods.go +++ b/pkg/multicloud/cloudpods/cloudpods.go @@ -95,18 +95,18 @@ func (self *SCloudpodsClient) auth() error { client := mcclient.NewClient(self.authURL, 0, self.debug, true, "", "") client.SetHttpTransportProxyFunc(self.cpcfg.ProxyFunc) ts, _ := client.GetClient().Transport.(*http.Transport) - client.SetTransport(cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + client.SetTransport(cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if self.cpcfg.ReadOnly { if req.Method == "GET" || req.Method == "HEAD" { - return nil + return nil, nil } // 认证 if req.Method == "POST" && req.URL.Path == "/v3/auth/tokens" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil })) token, err := client.AuthenticateByAccessKey(self.accessKey, self.accessSecret, "cli") if err != nil { diff --git a/pkg/multicloud/ctyun/ctyun.go b/pkg/multicloud/ctyun/ctyun.go index efc157dc27..b3b39da960 100644 --- a/pkg/multicloud/ctyun/ctyun.go +++ b/pkg/multicloud/ctyun/ctyun.go @@ -91,14 +91,14 @@ type SCtyunClient struct { func NewSCtyunClient(cfg *CtyunClientConfig) (*SCtyunClient, error) { httpClient := cfg.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if cfg.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) client := &SCtyunClient{ CtyunClientConfig: cfg, diff --git a/pkg/multicloud/google/google.go b/pkg/multicloud/google/google.go index 5e865e08f7..1eed18f083 100644 --- a/pkg/multicloud/google/google.go +++ b/pkg/multicloud/google/google.go @@ -140,14 +140,26 @@ func NewGoogleClient(cfg *GoogleClientConfig) (*SGoogleClient, error) { httpClient := cfg.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { + service := strings.Split(req.URL.Host, ".")[0] + if service == "www" { + service = strings.Split(req.URL.Path, "/")[0] + } + method, path := req.Method, req.URL.Path + respCheck := func(resp *http.Response) { + if resp.StatusCode == 403 { + if cfg.cpcfg.UpdatePermission != nil { + cfg.cpcfg.UpdatePermission(service, fmt.Sprintf("%s %s", method, path)) + } + } + } if cfg.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return respCheck, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return respCheck, nil }) ctx := context.Background() diff --git a/pkg/multicloud/hcso/huawei.go b/pkg/multicloud/hcso/huawei.go index 57a0b0790b..439282d5e4 100644 --- a/pkg/multicloud/hcso/huawei.go +++ b/pkg/multicloud/hcso/huawei.go @@ -156,14 +156,14 @@ func (self *SHuaweiClient) newRegionAPIClient(regionId string) (*client.Client, httpClient := self.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if self.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) cli.SetHttpClient(httpClient) @@ -178,14 +178,14 @@ func (self *SHuaweiClient) newGeneralAPIClient() (*client.Client, error) { httpClient := self.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if self.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) cli.SetHttpClient(httpClient) diff --git a/pkg/multicloud/hcso/region.go b/pkg/multicloud/hcso/region.go index 77b032adbd..4266fc917e 100644 --- a/pkg/multicloud/hcso/region.go +++ b/pkg/multicloud/hcso/region.go @@ -105,14 +105,14 @@ func (self *SRegion) getOBSClient() (*obs.ObsClient, error) { client := obsClient.GetClient() ts, _ := client.Transport.(*http.Transport) - client.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + client.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if self.client.cpcfg.ReadOnly { if req.Method == "GET" || req.Method == "HEAD" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) self.obsClient = obsClient diff --git a/pkg/multicloud/huawei/huawei.go b/pkg/multicloud/huawei/huawei.go index 84d20fdd18..6f471180f6 100644 --- a/pkg/multicloud/huawei/huawei.go +++ b/pkg/multicloud/huawei/huawei.go @@ -154,21 +154,33 @@ func (self *SHuaweiClient) initSigner() error { } func (self *SHuaweiClient) newRegionAPIClient(regionId string) (*client.Client, error) { - cli, err := client.NewPublicCloudClientWithAccessKey(regionId, self.ownerId, self.projectId, self.accessKey, self.accessSecret, self.debug) + projectId := self.projectId + if len(regionId) == 0 { + projectId = "" + } + cli, err := client.NewPublicCloudClientWithAccessKey(regionId, self.ownerId, projectId, self.accessKey, self.accessSecret, self.debug) if err != nil { return nil, err } httpClient := self.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { + service, method, path := strings.Split(req.URL.Host, ".")[0], req.Method, req.URL.Path + respCheck := func(resp *http.Response) { + if resp.StatusCode == 403 { + if self.cpcfg.UpdatePermission != nil { + self.cpcfg.UpdatePermission(service, fmt.Sprintf("%s %s", method, path)) + } + } + } if self.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return respCheck, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return respCheck, nil }) cli.SetHttpClient(httpClient) @@ -176,25 +188,7 @@ func (self *SHuaweiClient) newRegionAPIClient(regionId string) (*client.Client, } func (self *SHuaweiClient) newGeneralAPIClient() (*client.Client, error) { - cli, err := client.NewPublicCloudClientWithAccessKey("", self.ownerId, "", self.accessKey, self.accessSecret, self.debug) - if err != nil { - return nil, err - } - - httpClient := self.cpcfg.AdaptiveTimeoutHttpClient() - ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { - if self.cpcfg.ReadOnly { - if req.Method == "GET" { - return nil - } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) - } - return nil - }) - cli.SetHttpClient(httpClient) - - return cli, nil + return self.newRegionAPIClient("") } func (self *SHuaweiClient) fetchRegions() error { @@ -271,9 +265,33 @@ func getOBSEndpoint(regionId string) string { return fmt.Sprintf("obs.%s.myhuaweicloud.com", regionId) } -func (client *SHuaweiClient) getOBSClient(regionId string) (*obs.ObsClient, error) { +func (self *SHuaweiClient) getOBSClient(regionId string) (*obs.ObsClient, error) { endpoint := getOBSEndpoint(regionId) - return obs.New(client.accessKey, client.accessSecret, endpoint) + cli, err := obs.New(self.accessKey, self.accessSecret, endpoint) + if err != nil { + return nil, err + } + client := cli.GetClient() + ts, _ := client.Transport.(*http.Transport) + client.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { + method, path := req.Method, req.URL.Path + respCheck := func(resp *http.Response) { + if resp.StatusCode == 403 { + if self.cpcfg.UpdatePermission != nil { + self.cpcfg.UpdatePermission("obs", fmt.Sprintf("%s %s", method, path)) + } + } + } + if self.cpcfg.ReadOnly { + if req.Method == "GET" || req.Method == "HEAD" { + return respCheck, nil + } + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + } + return respCheck, nil + }) + + return cli, nil } func (self *SHuaweiClient) fetchBuckets() error { diff --git a/pkg/multicloud/huawei/region.go b/pkg/multicloud/huawei/region.go index 8527302e9c..bee286cee0 100644 --- a/pkg/multicloud/huawei/region.go +++ b/pkg/multicloud/huawei/region.go @@ -16,7 +16,6 @@ package huawei import ( "fmt" - "net/http" "strings" "time" @@ -100,18 +99,6 @@ func (self *SRegion) getOBSClient() (*obs.ObsClient, error) { return nil, err } - client := obsClient.GetClient() - ts, _ := client.Transport.(*http.Transport) - client.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { - if self.client.cpcfg.ReadOnly { - if req.Method == "GET" || req.Method == "HEAD" { - return nil - } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) - } - return nil - }) - self.obsClient = obsClient } diff --git a/pkg/multicloud/nutanix/nutanix.go b/pkg/multicloud/nutanix/nutanix.go index 68c6b40053..2dc1b24b27 100644 --- a/pkg/multicloud/nutanix/nutanix.go +++ b/pkg/multicloud/nutanix/nutanix.go @@ -133,14 +133,14 @@ func (cli *SNutanixClient) getDefaultClient(timeout time.Duration) *http.Client httputils.SetClientProxyFunc(client, proxy) ts, _ := client.Transport.(*http.Transport) - client.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + client.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if cli.cpcfg.ReadOnly { if req.Method == "GET" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) return client diff --git a/pkg/multicloud/openstack/openstack.go b/pkg/multicloud/openstack/openstack.go index 6f5692f8a6..6e056fa07a 100644 --- a/pkg/multicloud/openstack/openstack.go +++ b/pkg/multicloud/openstack/openstack.go @@ -425,18 +425,18 @@ func (cli *SOpenStackClient) getDefaultClient() *mcclient.Client { client.SetHttpTransportProxyFunc(cli.cpcfg.ProxyFunc) _client := client.GetClient() ts, _ := _client.Transport.(*http.Transport) - _client.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + _client.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if cli.cpcfg.ReadOnly { if req.Method == "GET" || req.Method == "HEAD" { - return nil + return nil, nil } // 认证 if req.Method == "POST" && strings.HasSuffix(req.URL.Path, "auth/tokens") { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) return client diff --git a/pkg/multicloud/qcloud/qcloud.go b/pkg/multicloud/qcloud/qcloud.go index 5133ebc182..9b130f6b24 100644 --- a/pkg/multicloud/qcloud/qcloud.go +++ b/pkg/multicloud/qcloud/qcloud.go @@ -611,26 +611,32 @@ func (client *SQcloudClient) getSdkClient(regionId string) (*common.Client, erro } httpClient := client.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - cli.WithHttpTransport(cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + cli.WithHttpTransport(cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { + body, err := ioutil.ReadAll(req.Body) + if err != nil { + return nil, errors.Wrapf(err, "ioutil.ReadAll") + } + req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + params, err := url.ParseQuery(string(body)) + if err != nil { + return nil, errors.Wrapf(err, "ParseQuery(%s)", string(body)) + } + service := strings.Split(req.URL.Host, ".")[0] + action := params.Get("Action") + respCheck := func(resp *http.Response) { + if client.cpcfg.UpdatePermission != nil { + client.cpcfg.UpdatePermission(service, action) + } + } if client.cpcfg.ReadOnly { - body, err := ioutil.ReadAll(req.Body) - if err != nil { - return errors.Wrapf(err, "ioutil.ReadAll") - } - req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) - params, err := url.ParseQuery(string(body)) - if err != nil { - return errors.Wrapf(err, "ParseQuery(%s)", string(body)) - } - action := params.Get("Action") for _, prefix := range []string{"Get", "List", "Describe"} { if strings.HasPrefix(action, prefix) { - return nil + return respCheck, nil } } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, action) } - return nil + return respCheck, nil })) return cli, nil } @@ -907,14 +913,22 @@ func (client *SQcloudClient) getCosClient(bucket *SBucket) (*cos.Client, error) RequestBody: client.debug, ResponseHeader: client.debug, ResponseBody: client.debug, - Transport: cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + Transport: cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { + method, path := req.Method, req.URL.Path + respCheck := func(resp *http.Response) { + if resp.StatusCode == 403 { + if client.cpcfg.UpdatePermission != nil { + client.cpcfg.UpdatePermission("cos", fmt.Sprintf("%s %s", method, path)) + } + } + } if client.cpcfg.ReadOnly { if req.Method == "GET" || req.Method == "HEAD" { - return nil + return respCheck, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s", req.Method, req.URL.Path) } - return nil + return respCheck, nil }), }, }, diff --git a/pkg/multicloud/ucloud/ucloud.go b/pkg/multicloud/ucloud/ucloud.go index a4be8ec5d9..d5cf4d2f5b 100644 --- a/pkg/multicloud/ucloud/ucloud.go +++ b/pkg/multicloud/ucloud/ucloud.go @@ -106,31 +106,31 @@ type SUcloudClient struct { func NewUcloudClient(cfg *UcloudClientConfig) (*SUcloudClient, error) { httpClient := cfg.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if cfg.cpcfg.ReadOnly { if req.ContentLength > 0 { body, err := ioutil.ReadAll(req.Body) if err != nil { - return errors.Wrapf(err, "ioutil.ReadAll") + return nil, errors.Wrapf(err, "ioutil.ReadAll") } req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) obj, err := jsonutils.Parse(body) if err != nil { - return errors.Wrapf(err, "Parse request body") + return nil, errors.Wrapf(err, "Parse request body") } action, err := obj.GetString("Action") if err != nil { - return errors.Wrapf(err, "Get request action") + return nil, errors.Wrapf(err, "Get request action") } for _, prefix := range []string{"Get", "Describe", "List"} { if strings.HasPrefix(action, prefix) { - return nil + return nil, nil } } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } } - return nil + return nil, nil }) client := SUcloudClient{ UcloudClientConfig: cfg, diff --git a/pkg/multicloud/zstack/zstack.go b/pkg/multicloud/zstack/zstack.go index 78689816c8..531642f80f 100644 --- a/pkg/multicloud/zstack/zstack.go +++ b/pkg/multicloud/zstack/zstack.go @@ -107,18 +107,18 @@ func getSignUrl(uri string) (string, error) { func NewZStackClient(cfg *ZstackClientConfig) (*SZStackClient, error) { httpClient := cfg.cpcfg.AdaptiveTimeoutHttpClient() ts, _ := httpClient.Transport.(*http.Transport) - httpClient.Transport = cloudprovider.GetReadOnlyCheckTransport(ts, func(req *http.Request) error { + httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) { if cfg.cpcfg.ReadOnly { if req.Method == "GET" || req.Method == "HEAD" { - return nil + return nil, nil } // 认证 if req.Method == "PUT" && req.URL.Path == "/zstack/v1/accounts/login" { - return nil + return nil, nil } - return errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) + return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path) } - return nil + return nil, nil }) cli := &SZStackClient{