@@ -2057,9 +2057,16 @@ CDWPG
20572057package tencentcloud
20582058
20592059import (
2060+ "encoding/json"
2061+ "fmt"
2062+ "io/ioutil"
20602063 "net/url"
20612064 "os"
2065+ "runtime"
20622066 "strconv"
2067+ "strings"
2068+
2069+ "github.com/mitchellh/go-homedir"
20632070
20642071 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
20652072 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
@@ -2079,6 +2086,13 @@ const (
20792086 PROVIDER_ASSUME_ROLE_ARN = "TENCENTCLOUD_ASSUME_ROLE_ARN"
20802087 PROVIDER_ASSUME_ROLE_SESSION_NAME = "TENCENTCLOUD_ASSUME_ROLE_SESSION_NAME"
20812088 PROVIDER_ASSUME_ROLE_SESSION_DURATION = "TENCENTCLOUD_ASSUME_ROLE_SESSION_DURATION"
2089+ PROVIDER_SHARED_CREDENTIALS_DIR = "TENCENTCLOUD_SHARED_CREDENTIALS_DIR"
2090+ PROVIDER_PROFILE = "TENCENTCLOUD_PROFILE"
2091+ )
2092+
2093+ const (
2094+ DEFAULT_REGION = "ap-guangzhou"
2095+ DEFAULT_PROFILE = "default"
20822096)
20832097
20842098type TencentCloudClient struct {
@@ -2090,13 +2104,13 @@ func Provider() *schema.Provider {
20902104 Schema : map [string ]* schema.Schema {
20912105 "secret_id" : {
20922106 Type : schema .TypeString ,
2093- Required : true ,
2107+ Optional : true ,
20942108 DefaultFunc : schema .EnvDefaultFunc (PROVIDER_SECRET_ID , nil ),
20952109 Description : "This is the TencentCloud access key. It must be provided, but it can also be sourced from the `TENCENTCLOUD_SECRET_ID` environment variable." ,
20962110 },
20972111 "secret_key" : {
20982112 Type : schema .TypeString ,
2099- Required : true ,
2113+ Optional : true ,
21002114 DefaultFunc : schema .EnvDefaultFunc (PROVIDER_SECRET_KEY , nil ),
21012115 Description : "This is the TencentCloud secret key. It must be provided, but it can also be sourced from the `TENCENTCLOUD_SECRET_KEY` environment variable." ,
21022116 Sensitive : true ,
@@ -2109,11 +2123,10 @@ func Provider() *schema.Provider {
21092123 Sensitive : true ,
21102124 },
21112125 "region" : {
2112- Type : schema .TypeString ,
2113- Required : true ,
2114- DefaultFunc : schema .EnvDefaultFunc (PROVIDER_REGION , nil ),
2115- Description : "This is the TencentCloud region. It must be provided, but it can also be sourced from the `TENCENTCLOUD_REGION` environment variables. The default input value is ap-guangzhou." ,
2116- InputDefault : "ap-guangzhou" ,
2126+ Type : schema .TypeString ,
2127+ Optional : true ,
2128+ DefaultFunc : schema .EnvDefaultFunc (PROVIDER_REGION , nil ),
2129+ Description : "This is the TencentCloud region. It must be provided, but it can also be sourced from the `TENCENTCLOUD_REGION` environment variables. The default input value is ap-guangzhou." ,
21172130 },
21182131 "protocol" : {
21192132 Type : schema .TypeString ,
@@ -2167,6 +2180,18 @@ func Provider() *schema.Provider {
21672180 },
21682181 },
21692182 },
2183+ "shared_credentials_dir" : {
2184+ Type : schema .TypeString ,
2185+ Optional : true ,
2186+ DefaultFunc : schema .EnvDefaultFunc (PROVIDER_SHARED_CREDENTIALS_DIR , nil ),
2187+ Description : "The directory of the shared credentials. It can also be sourced from the `TENCENTCLOUD_SHARED_CREDENTIALS_DIR` environment variable. If not set this defaults to ~/.tccli." ,
2188+ },
2189+ "profile" : {
2190+ Type : schema .TypeString ,
2191+ Optional : true ,
2192+ DefaultFunc : schema .EnvDefaultFunc (PROVIDER_PROFILE , nil ),
2193+ Description : "The profile name as set in the shared credentials. It can also be sourced from the `TENCENTCLOUD_PROFILE` environment variable. If not set, the default profile created with `tccli configure` will be used." ,
2194+ },
21702195 },
21712196
21722197 DataSourcesMap : map [string ]* schema.Resource {
@@ -3825,12 +3850,68 @@ func Provider() *schema.Provider {
38253850}
38263851
38273852func providerConfigure (d * schema.ResourceData ) (interface {}, error ) {
3828- secretId := d .Get ("secret_id" ).(string )
3829- secretKey := d .Get ("secret_key" ).(string )
3830- securityToken := d .Get ("security_token" ).(string )
3831- region := d .Get ("region" ).(string )
3832- protocol := d .Get ("protocol" ).(string )
3833- domain := d .Get ("domain" ).(string )
3853+ //var getProviderConfig = func(str string, key string) string {
3854+ // if str == "" {
3855+ // value, err := getConfigFromProfile(d, key)
3856+ // if err == nil && value != nil {
3857+ // str = value.(string)
3858+ // }
3859+ // }
3860+ //
3861+ // return str
3862+ //}
3863+
3864+ var getProviderConfig = func (key string ) string {
3865+ var str string
3866+ value , err := getConfigFromProfile (d , key )
3867+ if err == nil && value != nil {
3868+ str = value .(string )
3869+ }
3870+
3871+ return str
3872+ }
3873+
3874+ var (
3875+ secretId string
3876+ secretKey string
3877+ securityToken string
3878+ region string
3879+ protocol string
3880+ domain string
3881+ )
3882+
3883+ if v , ok := d .GetOk ("secret_id" ); ok {
3884+ secretId = v .(string )
3885+ } else {
3886+ secretId = getProviderConfig ("secretId" )
3887+ }
3888+
3889+ if v , ok := d .GetOk ("secret_key" ); ok {
3890+ secretKey = v .(string )
3891+ } else {
3892+ secretKey = getProviderConfig ("secretKey" )
3893+ }
3894+
3895+ if v , ok := d .GetOk ("security_token" ); ok {
3896+ securityToken = v .(string )
3897+ }
3898+
3899+ if v , ok := d .GetOk ("region" ); ok {
3900+ region = v .(string )
3901+ } else {
3902+ region = getProviderConfig ("region" )
3903+ if region == "" {
3904+ region = DEFAULT_REGION
3905+ }
3906+ }
3907+
3908+ if v , ok := d .GetOk ("protocol" ); ok {
3909+ protocol = v .(string )
3910+ }
3911+
3912+ if v , ok := d .GetOk ("domain" ); ok {
3913+ domain = v .(string )
3914+ }
38343915
38353916 // standard client
38363917 var tcClient TencentCloudClient
@@ -3845,37 +3926,66 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
38453926 Domain : domain ,
38463927 }
38473928
3848- envRoleArn := os .Getenv (PROVIDER_ASSUME_ROLE_ARN )
3849- envSessionName := os .Getenv (PROVIDER_ASSUME_ROLE_SESSION_NAME )
3929+ var (
3930+ assumeRoleArn string
3931+ assumeRoleSessionName string
3932+ assumeRoleSessionDuration int
3933+ assumeRolePolicy string
3934+ )
3935+
3936+ // get assume role from credential
3937+ if providerConfig ["role-arn" ] != nil {
3938+ assumeRoleArn = providerConfig ["role-arn" ].(string )
3939+ }
3940+
3941+ if providerConfig ["role-session-name" ] != nil {
3942+ assumeRoleSessionName = providerConfig ["role-session-name" ].(string )
3943+ }
3944+
3945+ if assumeRoleArn != "" && assumeRoleSessionName != "" {
3946+ assumeRoleSessionDuration = 7200
3947+ assumeRolePolicy = ""
3948+
3949+ _ = genClientWithSTS (& tcClient , assumeRoleArn , assumeRoleSessionName , assumeRoleSessionDuration , assumeRolePolicy )
3950+ }
38503951
38513952 // get assume role from env
3953+ envRoleArn := os .Getenv (PROVIDER_ASSUME_ROLE_ARN )
3954+ envSessionName := os .Getenv (PROVIDER_ASSUME_ROLE_SESSION_NAME )
38523955 if envRoleArn != "" && envSessionName != "" {
3853- var assumeRoleSessionDuration int
38543956 if envSessionDuration := os .Getenv (PROVIDER_ASSUME_ROLE_SESSION_DURATION ); envSessionDuration != "" {
38553957 var err error
38563958 assumeRoleSessionDuration , err = strconv .Atoi (envSessionDuration )
38573959 if err != nil {
38583960 return nil , err
38593961 }
38603962 }
3963+
38613964 if assumeRoleSessionDuration == 0 {
38623965 assumeRoleSessionDuration = 7200
38633966 }
38643967
38653968 _ = genClientWithSTS (& tcClient , envRoleArn , envSessionName , assumeRoleSessionDuration , "" )
38663969 }
38673970
3868- // get assume role from tf config
3869- assumeRoleList := d .Get ("assume_role" ).(* schema.Set ).List ()
3870- if len (assumeRoleList ) == 1 {
3871- assumeRole := assumeRoleList [0 ].(map [string ]interface {})
3872- assumeRoleArn := assumeRole ["role_arn" ].(string )
3873- assumeRoleSessionName := assumeRole ["session_name" ].(string )
3874- assumeRoleSessionDuration := assumeRole ["session_duration" ].(int )
3875- assumeRolePolicy := assumeRole ["policy" ].(string )
3971+ // get assume role from tf
3972+ if v , ok := d .GetOk ("assume_role" ); ok {
3973+ assumeRoleList := v .(* schema.Set ).List ()
3974+ if len (assumeRoleList ) == 1 {
3975+ assumeRole := assumeRoleList [0 ].(map [string ]interface {})
3976+ assumeRoleArn = assumeRole ["role_arn" ].(string )
3977+ assumeRoleSessionName = assumeRole ["session_name" ].(string )
3978+ assumeRoleSessionDuration = assumeRole ["session_duration" ].(int )
3979+ assumeRolePolicy = assumeRole ["policy" ].(string )
3980+
3981+ _ = genClientWithSTS (& tcClient , assumeRoleArn , assumeRoleSessionName , assumeRoleSessionDuration , assumeRolePolicy )
3982+ }
3983+ }
38763984
3877- _ = genClientWithSTS (& tcClient , assumeRoleArn , assumeRoleSessionName , assumeRoleSessionDuration , assumeRolePolicy )
3985+ if secretId == "" || secretKey == "" {
3986+ return nil , fmt .Errorf ("Please set your `secret_id` and `secret_key`." )
38783987 }
3988+
38793989 return & tcClient , nil
38803990}
38813991
@@ -3888,16 +3998,107 @@ func genClientWithSTS(tcClient *TencentCloudClient, assumeRoleArn, assumeRoleSes
38883998 if assumeRolePolicy != "" {
38893999 request .Policy = helper .String (url .QueryEscape (assumeRolePolicy ))
38904000 }
4001+
38914002 ratelimit .Check (request .GetAction ())
38924003 response , err := tcClient .apiV3Conn .UseStsClient ().AssumeRole (request )
38934004 if err != nil {
38944005 return err
38954006 }
4007+
38964008 // using STS credentials
38974009 tcClient .apiV3Conn .Credential = common .NewTokenCredential (
38984010 * response .Response .Credentials .TmpSecretId ,
38994011 * response .Response .Credentials .TmpSecretKey ,
39004012 * response .Response .Credentials .Token ,
39014013 )
4014+
39024015 return nil
39034016}
4017+
4018+ var providerConfig map [string ]interface {}
4019+
4020+ func getConfigFromProfile (d * schema.ResourceData , ProfileKey string ) (interface {}, error ) {
4021+ if providerConfig == nil {
4022+ var (
4023+ profile string
4024+ sharedCredentialsDir string
4025+ credentialPath string
4026+ configurePath string
4027+ )
4028+
4029+ if v , ok := d .GetOk ("profile" ); ok {
4030+ profile = v .(string )
4031+ } else {
4032+ profile = DEFAULT_PROFILE
4033+ }
4034+
4035+ if v , ok := d .GetOk ("shared_credentials_dir" ); ok {
4036+ sharedCredentialsDir = v .(string )
4037+ }
4038+
4039+ tmpSharedCredentialsDir , err := homedir .Expand (sharedCredentialsDir )
4040+ if err != nil {
4041+ return nil , err
4042+ }
4043+
4044+ if tmpSharedCredentialsDir == "" {
4045+ credentialPath = fmt .Sprintf ("%s/.tccli/%s.credential" , os .Getenv ("HOME" ), profile )
4046+ configurePath = fmt .Sprintf ("%s/.tccli/%s.configure" , os .Getenv ("HOME" ), profile )
4047+ if runtime .GOOS == "windows" {
4048+ credentialPath = fmt .Sprintf ("%s/.tccli/%s.credential" , os .Getenv ("USERPROFILE" ), profile )
4049+ configurePath = fmt .Sprintf ("%s/.tccli/%s.configure" , os .Getenv ("USERPROFILE" ), profile )
4050+ }
4051+ } else {
4052+ credentialPath = fmt .Sprintf ("%s/%s.credential" , sharedCredentialsDir , profile )
4053+ configurePath = fmt .Sprintf ("%s/%s.configure" , sharedCredentialsDir , profile )
4054+ }
4055+
4056+ providerConfig = make (map [string ]interface {})
4057+ _ , err = os .Stat (credentialPath )
4058+ if ! os .IsNotExist (err ) {
4059+ data , err := ioutil .ReadFile (credentialPath )
4060+ if err != nil {
4061+ return nil , err
4062+ }
4063+
4064+ config := map [string ]interface {}{}
4065+ err = json .Unmarshal (data , & config )
4066+ if err != nil {
4067+ return nil , err
4068+ }
4069+
4070+ for k , v := range config {
4071+ providerConfig [k ] = strings .TrimSpace (v .(string ))
4072+ }
4073+ }
4074+
4075+ _ , err = os .Stat (configurePath )
4076+ if ! os .IsNotExist (err ) {
4077+ data , err := ioutil .ReadFile (configurePath )
4078+ if err != nil {
4079+ return nil , err
4080+ }
4081+
4082+ config := map [string ]interface {}{}
4083+ err = json .Unmarshal (data , & config )
4084+ if err != nil {
4085+ return nil , err
4086+ }
4087+
4088+ outerLoop:
4089+ for k , v := range config {
4090+ if k == "_sys_param" {
4091+ tmpMap := v .(map [string ]interface {})
4092+ for tmpK , tmpV := range tmpMap {
4093+ if tmpK == "region" {
4094+ providerConfig [tmpK ] = strings .TrimSpace (tmpV .(string ))
4095+ break outerLoop
4096+ }
4097+ }
4098+ }
4099+ }
4100+ }
4101+ }
4102+
4103+ return providerConfig [ProfileKey ], nil
4104+ }
0 commit comments