github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/alicloud/connectivity/config.go (about)

     1  package connectivity
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"strings"
     9  
    10  	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
    11  	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
    12  	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
    13  	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
    14  	"github.com/jmespath/go-jmespath"
    15  )
    16  
    17  var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
    18  
    19  // Config of aliyun
    20  type Config struct {
    21  	AccessKey                string
    22  	SecretKey                string
    23  	EcsRoleName              string
    24  	Region                   Region
    25  	RegionID                 string
    26  	SecurityToken            string
    27  	OtsInstanceName          string
    28  	AccountID                string
    29  	RAMRoleArn               string
    30  	RAMRoleSessionName       string
    31  	RAMRolePolicy            string
    32  	RAMRoleSessionExpiration int
    33  	EcsEndpoint              string
    34  	RdsEndpoint              string
    35  	SlbEndpoint              string
    36  	VpcEndpoint              string
    37  	CenEndpoint              string
    38  	EssEndpoint              string
    39  	OssEndpoint              string
    40  	OnsEndpoint              string
    41  	AlikafkaEndpoint         string
    42  	DNSEndpoint              string
    43  	RAMEndpoint              string
    44  	CsEndpoint               string
    45  	CrEndpoint               string
    46  	CdnEndpoint              string
    47  	KmsEndpoint              string
    48  	OtsEndpoint              string
    49  	CmsEndpoint              string
    50  	PvtzEndpoint             string
    51  	StsEndpoint              string
    52  	LogEndpoint              string
    53  	DrdsEndpoint             string
    54  	DdsEndpoint              string
    55  	GpdbEnpoint              string
    56  	KVStoreEndpoint          string
    57  	FcEndpoint               string
    58  	ApigatewayEndpoint       string
    59  	DatahubEndpoint          string
    60  	MnsEndpoint              string
    61  	LocationEndpoint         string
    62  	ElasticsearchEndpoint    string
    63  	NasEndpoint              string
    64  	ActionTrailEndpoint      string
    65  	BssOpenAPIEndpoint       string
    66  	DdoscooEndpoint          string
    67  	DdosbgpEndpoint          string
    68  
    69  	SkipRegionValidation bool
    70  	ConfigurationSource  string
    71  }
    72  
    73  func (c *Config) loadAndValidate() error {
    74  	err := c.validateRegion()
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func (c *Config) validateRegion() error {
    83  	for _, valid := range ValidRegions {
    84  		if c.Region == valid {
    85  			return nil
    86  		}
    87  	}
    88  
    89  	return fmt.Errorf("Invalid Alibaba Cloud region: %s", c.RegionID)
    90  }
    91  
    92  func (c *Config) getAuthCredential() auth.Credential {
    93  	if c.AccessKey != "" && c.SecretKey != "" {
    94  		if c.SecurityToken != "" {
    95  			return credentials.NewStsTokenCredential(c.AccessKey, c.SecretKey, c.SecurityToken)
    96  		}
    97  		if c.RAMRoleArn != "" {
    98  			log.Printf("[INFO] Assume RAM Role specified in provider block assume_role { ... }")
    99  			return credentials.NewRamRoleArnWithPolicyCredential(
   100  				c.AccessKey, c.SecretKey, c.RAMRoleArn,
   101  				c.RAMRoleSessionName, c.RAMRolePolicy, c.RAMRoleSessionExpiration)
   102  		}
   103  		return credentials.NewAccessKeyCredential(c.AccessKey, c.SecretKey)
   104  	}
   105  	if c.EcsRoleName != "" {
   106  		return credentials.NewEcsRamRoleCredential(c.EcsRoleName)
   107  	}
   108  
   109  	return credentials.NewAccessKeyCredential(c.AccessKey, c.SecretKey)
   110  }
   111  
   112  // getAuthCredentialByEcsRoleName aims to access meta to get sts credential
   113  // Actually, the job should be done by sdk, but currently not all resources and products support alibaba-cloud-sdk-go,
   114  // and their go sdk does support ecs role name.
   115  // This method is a temporary solution and it should be removed after all go sdk support ecs role name
   116  // The related PR: https://github.com/terraform-providers/terraform-provider-alicloud/pull/731
   117  func (c *Config) getAuthCredentialByEcsRoleName() (accessKey, secretKey, token string, err error) {
   118  	if c.AccessKey != "" {
   119  		return c.AccessKey, c.SecretKey, c.SecurityToken, nil
   120  	}
   121  	if c.EcsRoleName == "" {
   122  		return
   123  	}
   124  	requestURL := securityCredURL + c.EcsRoleName
   125  	httpRequest, err := http.NewRequest(requests.GET, requestURL, strings.NewReader(""))
   126  	if err != nil {
   127  		err = fmt.Errorf("build sts requests err: %s", err.Error())
   128  		return
   129  	}
   130  	httpClient := &http.Client{}
   131  	httpResponse, err := httpClient.Do(httpRequest)
   132  	if err != nil {
   133  		err = fmt.Errorf("get Ecs sts token err : %s", err.Error())
   134  		return
   135  	}
   136  
   137  	response := responses.NewCommonResponse()
   138  	err = responses.Unmarshal(response, httpResponse, "")
   139  	if err != nil {
   140  		err = fmt.Errorf("Unmarshal Ecs sts token response err : %s", err.Error())
   141  		return
   142  	}
   143  
   144  	if response.GetHttpStatus() != http.StatusOK {
   145  		err = fmt.Errorf("get Ecs sts token err, httpStatus: %d, message = %s", response.GetHttpStatus(), response.GetHttpContentString())
   146  		return
   147  	}
   148  	var data interface{}
   149  	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
   150  	if err != nil {
   151  		err = fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error())
   152  		return
   153  	}
   154  	code, err := jmespath.Search("Code", data)
   155  	if err != nil {
   156  		err = fmt.Errorf("refresh Ecs sts token err, fail to get Code: %s", err.Error())
   157  		return
   158  	}
   159  	if code.(string) != "Success" {
   160  		err = fmt.Errorf("refresh Ecs sts token err, Code is not Success")
   161  		return
   162  	}
   163  	accessKeyID, err := jmespath.Search("AccessKeyId", data)
   164  	if err != nil {
   165  		err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeyId: %s", err.Error())
   166  		return
   167  	}
   168  	accessKeySecret, err := jmespath.Search("AccessKeySecret", data)
   169  	if err != nil {
   170  		err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeySecret: %s", err.Error())
   171  		return
   172  	}
   173  	securityToken, err := jmespath.Search("SecurityToken", data)
   174  	if err != nil {
   175  		err = fmt.Errorf("refresh Ecs sts token err, fail to get SecurityToken: %s", err.Error())
   176  		return
   177  	}
   178  
   179  	if accessKeyID == nil || accessKeySecret == nil || securityToken == nil {
   180  		err = fmt.Errorf("there is no any available accesskey, secret and security token for Ecs role %s", c.EcsRoleName)
   181  		return
   182  	}
   183  
   184  	return accessKeyID.(string), accessKeySecret.(string), securityToken.(string), nil
   185  }
   186  
   187  func (c *Config) MakeConfigByEcsRoleName() error {
   188  	accessKey, secretKey, token, err := c.getAuthCredentialByEcsRoleName()
   189  	if err != nil {
   190  		return err
   191  	}
   192  	c.AccessKey, c.SecretKey, c.SecurityToken = accessKey, secretKey, token
   193  	return nil
   194  }