mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
fix(region): cloud lake of permissions
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
|
||||
+38
-20
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user