aws.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package aws
  15. import (
  16. "bytes"
  17. "fmt"
  18. "io/ioutil"
  19. "net/http"
  20. "net/url"
  21. "strings"
  22. "github.com/aws/aws-sdk-go/aws"
  23. sdk "github.com/aws/aws-sdk-go/aws"
  24. "github.com/aws/aws-sdk-go/aws/awserr"
  25. "github.com/aws/aws-sdk-go/aws/credentials"
  26. "github.com/aws/aws-sdk-go/aws/credentials/stscreds"
  27. "github.com/aws/aws-sdk-go/aws/session"
  28. "github.com/aws/aws-sdk-go/service/s3"
  29. "yunion.io/x/log"
  30. "yunion.io/x/pkg/errors"
  31. api "yunion.io/x/cloudmux/pkg/apis/compute"
  32. "yunion.io/x/cloudmux/pkg/cloudprovider"
  33. )
  34. const (
  35. CLOUD_PROVIDER_AWS = api.CLOUD_PROVIDER_AWS
  36. CLOUD_PROVIDER_AWS_CN = "AWS"
  37. CLOUD_PROVIDER_AWS_EN = "AWS"
  38. AWS_INTERNATIONAL_CLOUDENV = "InternationalCloud"
  39. AWS_CHINA_CLOUDENV = "ChinaCloud"
  40. AWS_INTERNATIONAL_DEFAULT_REGION = "us-west-1"
  41. AWS_CHINA_DEFAULT_REGION = "cn-north-1"
  42. AWS_API_VERSION = "2018-10-10"
  43. AWS_GLOBAL_ARN_PREFIX = "arn:aws:iam::aws:policy/"
  44. AWS_CHINA_ARN_PREFIX = "arn:aws-cn:iam::aws:policy/"
  45. DEFAULT_S3_REGION_ID = "us-east-1"
  46. DefaultAssumeRoleName = "OrganizationAccountAccessRole"
  47. )
  48. type AwsClientConfig struct {
  49. cpcfg cloudprovider.ProviderConfig
  50. accessUrl string // 服务区域 ChinaCloud | InternationalCloud
  51. accessKey string
  52. accessSecret string
  53. accountId string
  54. debug bool
  55. assumeRoleName string
  56. }
  57. func NewAwsClientConfig(accessUrl, accessKey, accessSecret, accountId string) *AwsClientConfig {
  58. cfg := &AwsClientConfig{
  59. accessUrl: accessUrl,
  60. accessKey: accessKey,
  61. accessSecret: accessSecret,
  62. accountId: accountId,
  63. }
  64. return cfg
  65. }
  66. func (cfg *AwsClientConfig) CloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *AwsClientConfig {
  67. cfg.cpcfg = cpcfg
  68. return cfg
  69. }
  70. func (cfg *AwsClientConfig) Debug(debug bool) *AwsClientConfig {
  71. cfg.debug = debug
  72. return cfg
  73. }
  74. func (cfg *AwsClientConfig) SetAssumeRole(roleName string) *AwsClientConfig {
  75. cfg.assumeRoleName = roleName
  76. return cfg
  77. }
  78. func (cfg *AwsClientConfig) getAssumeRoleName() string {
  79. if len(cfg.assumeRoleName) > 0 {
  80. return cfg.assumeRoleName
  81. }
  82. return DefaultAssumeRoleName
  83. }
  84. type SAwsClient struct {
  85. *AwsClientConfig
  86. ownerId string
  87. ownerName string
  88. regions []SRegion
  89. iBuckets []cloudprovider.ICloudBucket
  90. }
  91. func NewAwsClient(cfg *AwsClientConfig) (*SAwsClient, error) {
  92. client := SAwsClient{
  93. AwsClientConfig: cfg,
  94. }
  95. var err error
  96. client.regions, err = client.GetRegions()
  97. if err != nil {
  98. return nil, errors.Wrapf(err, "GetRegions")
  99. }
  100. return &client, nil
  101. }
  102. func (cli *SAwsClient) getIamArn(arn string) string {
  103. switch cli.GetAccessEnv() {
  104. case api.CLOUD_ACCESS_ENV_AWS_GLOBAL:
  105. return AWS_GLOBAL_ARN_PREFIX + arn
  106. default:
  107. return AWS_CHINA_ARN_PREFIX + arn
  108. }
  109. }
  110. func GetDefaultRegionId(accessUrl string) string {
  111. defaultRegion := AWS_INTERNATIONAL_DEFAULT_REGION
  112. switch accessUrl {
  113. case AWS_INTERNATIONAL_CLOUDENV:
  114. defaultRegion = AWS_INTERNATIONAL_DEFAULT_REGION
  115. case AWS_CHINA_CLOUDENV:
  116. defaultRegion = AWS_CHINA_DEFAULT_REGION
  117. }
  118. return defaultRegion
  119. }
  120. func (self *SAwsClient) getDefaultRegionId() string {
  121. return GetDefaultRegionId(self.accessUrl)
  122. }
  123. func (client *SAwsClient) getDefaultSession(assumeRole bool) (*session.Session, error) {
  124. return client.getAwsSession(client.getDefaultRegionId(), assumeRole)
  125. }
  126. func (client *SAwsClient) GetAccountId() string {
  127. err := client.fetchOwnerId()
  128. if err != nil {
  129. return ""
  130. }
  131. return client.ownerId
  132. }
  133. func (self *SAwsClient) ec2Request(regionId string, apiName string, params map[string]string, retval interface{}, assumeRole bool) error {
  134. return self.request(regionId, EC2_SERVICE_NAME, EC2_SERVICE_ID, "2016-11-15", apiName, params, retval, assumeRole)
  135. }
  136. // Amazon Elastic Container Service
  137. func (self *SAwsClient) ecsRequest(regionId string, apiName string, params map[string]interface{}, retval interface{}, assumeRole bool) error {
  138. return self.invoke(regionId, ECS_SERVICE_NAME, ECS_SERVICE_ID, "2014-11-13", apiName, "", params, retval, assumeRole)
  139. }
  140. func (self *SAwsClient) lambdaRequest(regionId string, apiName, path string, params map[string]interface{}, retval interface{}, assumeRole bool) error {
  141. return self.invoke(regionId, LAMBDA_SERVICE_NAME, LAMBDA_SERVICE_ID, "2015-03-31", apiName, path, params, retval, assumeRole)
  142. }
  143. func (self *SAwsClient) kinesisRequest(regionId string, apiName, path string, params map[string]interface{}, retval interface{}, assumeRole bool) error {
  144. return self.invoke(regionId, KINESIS_SERVICE_NAME, KINESIS_SERVICE_ID, "2013-12-02", apiName, path, params, retval, assumeRole)
  145. }
  146. func (self *SAwsClient) cfRequest(apiName string, params map[string]string, retval interface{}, assumeRole bool) error {
  147. return self.request("", CDN_SERVICE_NAME, CDN_SERVICE_ID, "2020-05-31", apiName, params, retval, assumeRole)
  148. }
  149. func (client *SAwsClient) getHttpClient() (*http.Client, error) {
  150. httpClient := client.cpcfg.AdaptiveTimeoutHttpClient()
  151. transport, _ := httpClient.Transport.(*http.Transport)
  152. httpClient.Transport = cloudprovider.GetCheckTransport(transport, func(req *http.Request) (func(resp *http.Response) error, error) {
  153. var action string
  154. if req.ContentLength > 0 && !strings.Contains(req.URL.Host, ".s3.") {
  155. body, err := ioutil.ReadAll(req.Body)
  156. if err != nil {
  157. return nil, errors.Wrapf(err, "ioutil.ReadAll")
  158. }
  159. req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
  160. params, err := url.ParseQuery(string(body))
  161. if err != nil {
  162. return nil, errors.Wrapf(err, "ParseQuery(%s)", string(body))
  163. }
  164. action = params.Get("Action")
  165. }
  166. service := strings.Split(req.URL.Host, ".")[0]
  167. method, path := req.Method, req.URL.Path
  168. respCheck := func(resp *http.Response) error {
  169. if resp.StatusCode == 403 {
  170. if client.cpcfg.UpdatePermission != nil {
  171. if len(action) > 0 {
  172. client.cpcfg.UpdatePermission(service, action)
  173. } else { // s3
  174. client.cpcfg.UpdatePermission(service, fmt.Sprintf("%s %s", method, path))
  175. }
  176. }
  177. }
  178. return nil
  179. }
  180. if client.cpcfg.ReadOnly {
  181. if len(action) > 0 {
  182. for _, prefix := range []string{"Get", "List", "Describe"} {
  183. if strings.HasPrefix(action, prefix) {
  184. return respCheck, nil
  185. }
  186. }
  187. return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s", action)
  188. }
  189. // organization
  190. if service == "organizations" {
  191. return respCheck, nil
  192. }
  193. // s3
  194. if req.Method == "GET" || req.Method == "HEAD" {
  195. return respCheck, nil
  196. }
  197. return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path)
  198. }
  199. return respCheck, nil
  200. })
  201. return httpClient, nil
  202. }
  203. func (client *SAwsClient) getAwsSession(regionId string, assumeRole bool) (*session.Session, error) {
  204. httpClient, err := client.getHttpClient()
  205. if err != nil {
  206. return nil, errors.Wrap(err, "getHttpClient")
  207. }
  208. s, err := session.NewSession(&sdk.Config{
  209. Region: sdk.String(regionId),
  210. Credentials: credentials.NewStaticCredentials(
  211. client.accessKey, client.accessSecret, "",
  212. ),
  213. HTTPClient: httpClient,
  214. DisableParamValidation: sdk.Bool(true),
  215. CredentialsChainVerboseErrors: sdk.Bool(true),
  216. })
  217. if err != nil {
  218. return nil, errors.Wrap(err, "getAwsSession.NewSession")
  219. }
  220. if assumeRole && len(client.accountId) > 0 {
  221. // need to assumeRole
  222. var env string
  223. switch client.GetAccessEnv() {
  224. case api.CLOUD_ACCESS_ENV_AWS_GLOBAL:
  225. env = "aws"
  226. default:
  227. env = "aws-cn"
  228. }
  229. roleARN := fmt.Sprintf("arn:%s:iam::%s:role/%s", env, client.accountId, client.getAssumeRoleName())
  230. creds := stscreds.NewCredentials(s, roleARN)
  231. s = s.Copy(&aws.Config{Credentials: creds})
  232. }
  233. if client.debug {
  234. logLevel := aws.LogLevelType(uint(aws.LogDebugWithRequestErrors) + uint(aws.LogDebugWithHTTPBody) + uint(aws.LogDebugWithSigning))
  235. s.Config.LogLevel = &logLevel
  236. }
  237. return s, nil
  238. }
  239. func (self *SAwsClient) invalidateIBuckets() {
  240. self.iBuckets = nil
  241. }
  242. func (self *SAwsClient) getIBuckets() ([]cloudprovider.ICloudBucket, error) {
  243. if self.iBuckets == nil {
  244. err := self.fetchBuckets()
  245. if err != nil {
  246. return nil, errors.Wrap(err, "fetchBuckets")
  247. }
  248. }
  249. return self.iBuckets, nil
  250. }
  251. func (client *SAwsClient) fetchOwnerId() error {
  252. ident, err := client.GetCallerIdentity()
  253. if err != nil {
  254. return errors.Wrap(err, "GetCallerIdentity")
  255. }
  256. client.ownerId = ident.Account
  257. return nil
  258. }
  259. func (client *SAwsClient) fetchBuckets() error {
  260. s, err := client.getDefaultSession(true)
  261. if err != nil {
  262. return errors.Wrap(err, "getDefaultSession")
  263. }
  264. s3cli := s3.New(s)
  265. output, err := s3cli.ListBuckets(&s3.ListBucketsInput{})
  266. if err != nil {
  267. if e, ok := err.(awserr.Error); ok && e.Code() == "AccessDenied" {
  268. return errors.Wrapf(cloudprovider.ErrForbidden, "%s", e.Message())
  269. }
  270. return errors.Wrap(err, "ListBuckets")
  271. }
  272. ret := make([]cloudprovider.ICloudBucket, 0)
  273. for _, bInfo := range output.Buckets {
  274. if err := FillZero(bInfo); err != nil {
  275. log.Errorf("s3cli.Binfo.FillZero error %s", err)
  276. continue
  277. }
  278. input := &s3.GetBucketLocationInput{}
  279. input.Bucket = bInfo.Name
  280. output, err := s3cli.GetBucketLocation(input)
  281. if err != nil {
  282. log.Errorf("s3cli.GetBucketLocation error %s", err)
  283. continue
  284. }
  285. if err := FillZero(output); err != nil {
  286. log.Errorf("s3cli.GetBucketLocation.FillZero error %s", err)
  287. continue
  288. }
  289. location := *output.LocationConstraint
  290. if len(location) == 0 {
  291. // https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html
  292. // Buckets in Region us-east-1 have a LocationConstraint of null.
  293. location = DEFAULT_S3_REGION_ID
  294. }
  295. region, err := client.GetIRegionById(location)
  296. if err != nil {
  297. log.Errorf("client.getIRegionByRegionId %s fail %s", location, err)
  298. continue
  299. }
  300. b := SBucket{
  301. region: region.(*SRegion),
  302. Name: *bInfo.Name,
  303. Location: location,
  304. CreationDate: *bInfo.CreationDate,
  305. }
  306. ret = append(ret, &b)
  307. }
  308. client.iBuckets = ret
  309. return nil
  310. }
  311. // 只是使用fetchRegions初始化好的self.iregions. 本身并不从云服务器厂商拉取region信息
  312. func (self *SAwsClient) GetRegions() ([]SRegion, error) {
  313. params := map[string]string{
  314. "AllRegions": "true",
  315. }
  316. ret := struct {
  317. RegionInfo []SRegion `xml:"regionInfo>item"`
  318. }{}
  319. err := self.ec2Request("", "DescribeRegions", params, &ret, false)
  320. if err != nil {
  321. if e, ok := err.(*sAwsError); ok && e.Errors.Code == "AuthFailure" {
  322. return nil, errors.Wrap(cloudprovider.ErrInvalidAccessKey, err.Error())
  323. }
  324. return nil, errors.Wrapf(err, "DescribeRegions")
  325. }
  326. return ret.RegionInfo, nil
  327. }
  328. func (self *SAwsClient) GetIRegions() ([]cloudprovider.ICloudRegion, error) {
  329. ret := []cloudprovider.ICloudRegion{}
  330. for i := range self.regions {
  331. self.regions[i].client = self
  332. ret = append(ret, &self.regions[i])
  333. }
  334. return ret, nil
  335. }
  336. func (self *SAwsClient) GetRegion(regionId string) (*SRegion, error) {
  337. regions, err := self.GetRegions()
  338. if err != nil {
  339. return nil, errors.Wrapf(err, "GetRegions")
  340. }
  341. if len(regionId) == 0 {
  342. regionId = AWS_INTERNATIONAL_DEFAULT_REGION
  343. switch self.accessUrl {
  344. case AWS_INTERNATIONAL_CLOUDENV:
  345. regionId = AWS_INTERNATIONAL_DEFAULT_REGION
  346. case AWS_CHINA_CLOUDENV:
  347. regionId = AWS_CHINA_DEFAULT_REGION
  348. }
  349. }
  350. for i := 0; i < len(regions); i += 1 {
  351. if regions[i].GetId() == regionId {
  352. regions[i].client = self
  353. return &regions[i], nil
  354. }
  355. }
  356. return nil, errors.Wrap(cloudprovider.ErrNotFound, regionId)
  357. }
  358. func (self *SAwsClient) getDefaultRegion() (*SRegion, error) {
  359. return self.GetRegion("")
  360. }
  361. func (self *SAwsClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
  362. for i := range self.regions {
  363. self.regions[i].client = self
  364. if self.regions[i].GetId() == id || self.regions[i].GetGlobalId() == id {
  365. return &self.regions[i], nil
  366. }
  367. }
  368. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "GetIRegionById(%s)", id)
  369. }
  370. func (self *SAwsClient) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
  371. for i := 0; i < len(self.regions); i += 1 {
  372. ihost, err := self.regions[i].GetIHostById(id)
  373. if err == nil {
  374. return ihost, nil
  375. } else if errors.Cause(err) != cloudprovider.ErrNotFound {
  376. log.Errorf("GetIHostById %s: %s", id, err)
  377. return nil, errors.Wrap(err, "GetIHostById")
  378. }
  379. }
  380. return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIHostById")
  381. }
  382. func (self *SAwsClient) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
  383. for i := 0; i < len(self.regions); i += 1 {
  384. ihost, err := self.regions[i].GetIVpcById(id)
  385. if err == nil {
  386. return ihost, nil
  387. } else if errors.Cause(err) != cloudprovider.ErrNotFound {
  388. log.Errorf("GetIVpcById %s: %s", id, err)
  389. return nil, errors.Wrap(err, "GetIVpcById")
  390. }
  391. }
  392. return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIVpcById")
  393. }
  394. func (self *SAwsClient) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
  395. for i := 0; i < len(self.regions); i += 1 {
  396. ihost, err := self.regions[i].GetIStorageById(id)
  397. if err == nil {
  398. return ihost, nil
  399. } else if errors.Cause(err) != cloudprovider.ErrNotFound {
  400. log.Errorf("GetIStorageById %s: %s", id, err)
  401. return nil, errors.Wrap(err, "GetIStorageById")
  402. }
  403. }
  404. return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIStorageById")
  405. }
  406. func (self *SAwsClient) cdnList(marker string, pageSize int64) ([]SCdnDomain, string, error) {
  407. input := map[string]string{
  408. "Marker": marker,
  409. "MaxItems": fmt.Sprintf("%d", pageSize),
  410. }
  411. ret := &struct {
  412. Items []SCdnDomain `xml:"Items>DistributionSummary"`
  413. NextMarker string `xml:"NextMarker,omitempty"`
  414. }{}
  415. err := self.cfRequest("ListDistributions2020_05_31", input, ret, true)
  416. if err != nil {
  417. return nil, "", errors.Wrap(err, "cdnList")
  418. }
  419. return ret.Items, ret.NextMarker, err
  420. }
  421. func (self *SAwsClient) cdnGet(id string) (*SCdnDomain, error) {
  422. input := map[string]string{
  423. "Id": id,
  424. }
  425. var ret SCdnDomain
  426. err := self.cfRequest("GetDistribution2020_05_31", input, &ret, true)
  427. if err != nil {
  428. return nil, errors.Wrap(err, "cdnGet")
  429. }
  430. return &ret, err
  431. }
  432. type SAccountBalance struct {
  433. AvailableAmount float64
  434. AvailableCashAmount float64
  435. CreditAmount float64
  436. MybankCreditAmount float64
  437. Currency string
  438. }
  439. func (self *SAwsClient) QueryAccountBalance() (*SAccountBalance, error) {
  440. return nil, cloudprovider.ErrNotSupported
  441. }
  442. func (self *SAwsClient) GetIProjects() ([]cloudprovider.ICloudProject, error) {
  443. return nil, cloudprovider.ErrNotImplemented
  444. }
  445. func (self *SAwsClient) GetAccessEnv() string {
  446. switch self.accessUrl {
  447. case AWS_INTERNATIONAL_CLOUDENV:
  448. return api.CLOUD_ACCESS_ENV_AWS_GLOBAL
  449. case AWS_CHINA_CLOUDENV:
  450. return api.CLOUD_ACCESS_ENV_AWS_CHINA
  451. default:
  452. return api.CLOUD_ACCESS_ENV_AWS_GLOBAL
  453. }
  454. }
  455. func (self *SAwsClient) iamRequest(apiName string, params map[string]string, retval interface{}) error {
  456. return self.request("", IAM_SERVICE_NAME, IAM_SERVICE_ID, "2010-05-08", apiName, params, retval, true)
  457. }
  458. func (self *SAwsClient) dnsRequest(apiName string, params map[string]string, retval interface{}) error {
  459. return self.request("", ROUTE53_SERVICE_NAME, ROUTE53_SERVICE_ID, "2013-04-01", apiName, params, retval, true)
  460. }
  461. func (self *SAwsClient) stsRequest(apiName string, params map[string]string, retval interface{}) error {
  462. return self.request("", STS_SERVICE_NAME, STS_SERVICE_ID, "2011-06-15", apiName, params, retval, false)
  463. }
  464. func (self *SAwsClient) GetCapabilities() []string {
  465. caps := []string{
  466. cloudprovider.CLOUD_CAPABILITY_COMPUTE,
  467. cloudprovider.CLOUD_CAPABILITY_NETWORK,
  468. cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP,
  469. cloudprovider.CLOUD_CAPABILITY_EIP,
  470. cloudprovider.CLOUD_CAPABILITY_LOADBALANCER,
  471. cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE,
  472. cloudprovider.CLOUD_CAPABILITY_RDS,
  473. cloudprovider.CLOUD_CAPABILITY_CACHE,
  474. cloudprovider.CLOUD_CAPABILITY_NAT + cloudprovider.READ_ONLY_SUFFIX,
  475. cloudprovider.CLOUD_CAPABILITY_EVENT,
  476. cloudprovider.CLOUD_CAPABILITY_CLOUDID,
  477. cloudprovider.CLOUD_CAPABILITY_DNSZONE,
  478. cloudprovider.CLOUD_CAPABILITY_SAML_AUTH,
  479. cloudprovider.CLOUD_CAPABILITY_WAF,
  480. cloudprovider.CLOUD_CAPABILITY_VPC_PEER,
  481. cloudprovider.CLOUD_CAPABILITY_CONTAINER,
  482. cloudprovider.CLOUD_CAPABILITY_CDN + cloudprovider.READ_ONLY_SUFFIX,
  483. }
  484. return caps
  485. }
  486. func (client *SAwsClient) GetIamLoginUrl() string {
  487. identity, err := client.GetCallerIdentity()
  488. if err != nil {
  489. log.Errorf("failed to get caller identity error: %v", err)
  490. return ""
  491. }
  492. switch client.GetAccessEnv() {
  493. case api.CLOUD_ACCESS_ENV_AWS_CHINA:
  494. return fmt.Sprintf("https://%s.signin.amazonaws.cn/console/", identity.Account)
  495. default:
  496. return fmt.Sprintf("https://%s.signin.aws.amazon.com/console/", identity.Account)
  497. }
  498. }
  499. func (client *SAwsClient) GetBucketCannedAcls() []string {
  500. switch client.GetAccessEnv() {
  501. case api.CLOUD_ACCESS_ENV_AWS_CHINA:
  502. return []string{
  503. string(cloudprovider.ACLPrivate),
  504. }
  505. default:
  506. return []string{
  507. string(cloudprovider.ACLPrivate),
  508. string(cloudprovider.ACLAuthRead),
  509. string(cloudprovider.ACLPublicRead),
  510. string(cloudprovider.ACLPublicReadWrite),
  511. }
  512. }
  513. }
  514. func (client *SAwsClient) GetObjectCannedAcls() []string {
  515. switch client.GetAccessEnv() {
  516. case api.CLOUD_ACCESS_ENV_AWS_CHINA:
  517. return []string{
  518. string(cloudprovider.ACLPrivate),
  519. }
  520. default:
  521. return []string{
  522. string(cloudprovider.ACLPrivate),
  523. string(cloudprovider.ACLAuthRead),
  524. string(cloudprovider.ACLPublicRead),
  525. string(cloudprovider.ACLPublicReadWrite),
  526. }
  527. }
  528. }
  529. func (client *SAwsClient) GetSamlEntityId() string {
  530. switch client.accessUrl {
  531. case AWS_CHINA_CLOUDENV:
  532. return cloudprovider.SAML_ENTITY_ID_AWS_CN
  533. default:
  534. return cloudprovider.SAML_ENTITY_ID_AWS
  535. }
  536. }