alibabacloudstack/connectivity/config.go (214 lines of code) (raw):

package connectivity import ( "fmt" "log" "encoding/json" "net/http" "strings" roa "github.com/alibabacloud-go/tea-roa/client" rpc "github.com/alibabacloud-go/tea-rpc/client" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" credential "github.com/aliyun/credentials-go/credentials" "github.com/jmespath/go-jmespath" ) var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/" // Config of alibabacloudstack type Config struct { AccessKey string SecretKey string EcsRoleName string Region Region RegionId string Department string ResourceGroup string ResourceGroupId string SecurityToken string OtsInstanceName string AccountId string Protocol string ClientReadTimeout int ClientConnectTimeout int SourceIp string SecureTransport string ResourceSetName string RamRoleArn string RamRoleSessionName string RamRolePolicy string RamRoleSessionExpiration int Endpoints map[ServiceCode]string ConfigurationSource string Insecure bool Proxy string Domain string Eagleeye EagleEye } func (c *Config) getAuthCredential(stsSupported, ramSupported bool) auth.Credential { if c.AccessKey != "" && c.SecretKey != "" { if stsSupported && c.SecurityToken != "" { return credentials.NewStsTokenCredential(c.AccessKey, c.SecretKey, c.SecurityToken) } if ramSupported && c.RamRoleArn != "" { log.Printf("[INFO] Assume RAM Role specified in provider block assume_role { ... }") return credentials.NewRamRoleArnWithPolicyCredential( c.AccessKey, c.SecretKey, c.RamRoleArn, c.RamRoleSessionName, c.RamRolePolicy, c.RamRoleSessionExpiration) } return credentials.NewAccessKeyCredential(c.AccessKey, c.SecretKey) } if c.EcsRoleName != "" { return credentials.NewEcsRamRoleCredential(c.EcsRoleName) } return credentials.NewAccessKeyCredential(c.AccessKey, c.SecretKey) } // getAuthCredentialByEcsRoleName aims to access meta to get sts credential // Actually, the job should be done by sdk, but currently not all resources and products support alibaba-cloud-sdk-go, // and their go sdk does support ecs role name. // This method is a temporary solution and it should be removed after all go sdk support ecs role name func (c *Config) getAuthCredentialByEcsRoleName() (accessKey, secretKey, token string, err error) { if c.AccessKey != "" { return c.AccessKey, c.SecretKey, c.SecurityToken, nil } if c.EcsRoleName == "" { return } requestUrl := securityCredURL + c.EcsRoleName httpRequest, err := http.NewRequest(requests.GET, requestUrl, strings.NewReader("")) if err != nil { err = fmt.Errorf("build sts requests err: %s", err.Error()) return } httpClient := &http.Client{} httpResponse, err := httpClient.Do(httpRequest) if err != nil { err = fmt.Errorf("get Ecs sts token err : %s", err.Error()) return } response := responses.NewCommonResponse() err = responses.Unmarshal(response, httpResponse, "") if err != nil { err = fmt.Errorf("Unmarshal Ecs sts token response err : %s", err.Error()) return } if response.GetHttpStatus() != http.StatusOK { err = fmt.Errorf("get Ecs sts token err, httpStatus: %d, message = %s", response.GetHttpStatus(), response.GetHttpContentString()) return } var data interface{} err = json.Unmarshal(response.GetHttpContentBytes(), &data) if err != nil { err = fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error()) return } code, err := jmespath.Search("Code", data) if err != nil { err = fmt.Errorf("refresh Ecs sts token err, fail to get Code: %s", err.Error()) return } if code.(string) != "Success" { err = fmt.Errorf("refresh Ecs sts token err, Code is not Success") return } accessKeyId, err := jmespath.Search("AccessKeyId", data) if err != nil { err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeyId: %s", err.Error()) return } accessKeySecret, err := jmespath.Search("AccessKeySecret", data) if err != nil { err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeySecret: %s", err.Error()) return } securityToken, err := jmespath.Search("SecurityToken", data) if err != nil { err = fmt.Errorf("refresh Ecs sts token err, fail to get SecurityToken: %s", err.Error()) return } if accessKeyId == nil || accessKeySecret == nil || securityToken == nil { err = fmt.Errorf("there is no any available accesskey, secret and security token for Ecs role %s", c.EcsRoleName) return } return accessKeyId.(string), accessKeySecret.(string), securityToken.(string), nil } func (c *Config) MakeConfigByEcsRoleName() error { accessKey, secretKey, token, err := c.getAuthCredentialByEcsRoleName() if err != nil { return err } c.AccessKey, c.SecretKey, c.SecurityToken = accessKey, secretKey, token return nil } func (c *Config) getTeaRpcDslSdkConfig(stsSupported bool) (config rpc.Config, err error) { config.SetRegionId(c.RegionId) config.SetUserAgent(fmt.Sprintf("%s/%s %s/%s %s/%s", Terraform, TerraformVersion, Provider, ProviderVersion, Module, c.ConfigurationSource)) credential, err := credential.NewCredential(c.getCredentialConfig(stsSupported)) config.SetCredential(credential). SetRegionId(c.RegionId). SetProtocol(c.Protocol). SetReadTimeout(c.ClientReadTimeout). SetConnectTimeout(c.ClientConnectTimeout). SetMaxIdleConns(500) if c.SourceIp != "" { config.SetSourceIp(c.SourceIp) } if c.SecureTransport != "" { config.SetSecureTransport(c.SecureTransport) } proxyProtocol := strings.ToUpper(strings.Split(c.Proxy, ":")[0]) switch proxyProtocol { case "HTTP": config.SetHttpProxy(c.Proxy) case "HTTPS": config.SetHttpsProxy(c.Proxy) case "SOCKS": config.SetSocks5Proxy(c.Proxy) } return } func (c *Config) getTeaRoaDslSdkConfig(stsSupported bool) (config roa.Config, err error) { config.SetRegionId(c.RegionId) config.SetUserAgent(fmt.Sprintf("%s/%s %s/%s %s/%s", Terraform, TerraformVersion, Provider, ProviderVersion, Module, c.ConfigurationSource)) credential, err := credential.NewCredential(c.getCredentialConfig(stsSupported)) config.SetCredential(credential). SetRegionId(c.RegionId). SetProtocol(c.Protocol). SetReadTimeout(c.ClientReadTimeout). SetConnectTimeout(c.ClientConnectTimeout). SetMaxIdleConns(500) if c.SourceIp != "" { config.SetSourceIp(c.SourceIp) } if c.SecureTransport != "" { config.SetSecureTransport(c.SecureTransport) } proxyProtocol := strings.ToUpper(strings.Split(c.Proxy, ":")[0]) switch proxyProtocol { case "HTTP": config.SetHttpProxy(c.Proxy) case "HTTPS": config.SetHttpsProxy(c.Proxy) } return } func (c *Config) getCredentialConfig(stsSupported bool) *credential.Config { credentialType := "" credentialConfig := &credential.Config{} if c.AccessKey != "" && c.SecretKey != "" { credentialType = "access_key" credentialConfig.AccessKeyId = &c.AccessKey // AccessKeyId credentialConfig.AccessKeySecret = &c.SecretKey // AccessKeySecret if stsSupported && c.SecurityToken != "" { credentialType = "sts" credentialConfig.SecurityToken = &c.SecurityToken // STS Token } else if c.RamRoleArn != "" { log.Printf("[INFO] Assume RAM Role specified in provider block assume_role { ... }") credentialType = "ram_role_arn" credentialConfig.RoleArn = &c.RamRoleArn credentialConfig.RoleSessionName = &c.RamRoleSessionName credentialConfig.RoleSessionExpiration = &c.RamRoleSessionExpiration credentialConfig.Policy = &c.RamRolePolicy } } else if c.EcsRoleName != "" { credentialType = "ecs_ram_role" credentialConfig.RoleName = &c.EcsRoleName } credentialConfig.Type = &credentialType return credentialConfig }