diff --git a/internal/backend/remote-state/oss/backend.go b/internal/backend/remote-state/oss/backend.go index 79534ed22f..d0e6660170 100644 --- a/internal/backend/remote-state/oss/backend.go +++ b/internal/backend/remote-state/oss/backend.go @@ -24,32 +24,84 @@ import ( "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/aliyun-tablestore-go-sdk/tablestore" "github.com/hashicorp/go-cleanhttp" + "github.com/jmespath/go-jmespath" + "github.com/mitchellh/go-homedir" + "github.com/hashicorp/terraform/internal/backend" "github.com/hashicorp/terraform/internal/legacy/helper/schema" "github.com/hashicorp/terraform/version" - "github.com/jmespath/go-jmespath" - "github.com/mitchellh/go-homedir" ) +// Deprecated in favor of flattening assume_role_* options +func deprecatedAssumeRoleSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ConflictsWith: []string{"assume_role_role_arn", "assume_role_session_name", "assume_role_policy", "assume_role_session_expiration"}, + MaxItems: 1, + Deprecated: "use assume_role_* options instead", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "role_arn": { + Type: schema.TypeString, + Required: true, + Description: "The ARN of a RAM role to assume prior to making API calls.", + DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_ARN", ""), + }, + "session_name": { + Type: schema.TypeString, + Optional: true, + Description: "The session name to use when assuming the role.", + DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_SESSION_NAME", ""), + }, + "policy": { + Type: schema.TypeString, + Optional: true, + Description: "The permissions applied when assuming a role. You cannot use this policy to grant permissions which exceed those of the role that is being assumed.", + }, + "session_expiration": { + Type: schema.TypeInt, + Optional: true, + Description: "The time after which the established session for assuming role expires.", + ValidateFunc: func(v interface{}, k string) ([]string, []error) { + min := 900 + max := 3600 + value, ok := v.(int) + if !ok { + return nil, []error{fmt.Errorf("expected type of %s to be int", k)} + } + + if value < min || value > max { + return nil, []error{fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)} + } + + return nil, nil + }, + }, + }, + }, + } +} + // New creates a new backend for OSS remote state. func New() backend.Backend { s := &schema.Backend{ Schema: map[string]*schema.Schema{ - "access_key": &schema.Schema{ + "access_key": { Type: schema.TypeString, Optional: true, Description: "Alibaba Cloud Access Key ID", DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ACCESS_KEY", os.Getenv("ALICLOUD_ACCESS_KEY_ID")), }, - "secret_key": &schema.Schema{ + "secret_key": { Type: schema.TypeString, Optional: true, Description: "Alibaba Cloud Access Secret Key", DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SECRET_KEY", os.Getenv("ALICLOUD_ACCESS_KEY_SECRET")), }, - "security_token": &schema.Schema{ + "security_token": { Type: schema.TypeString, Optional: true, Description: "Alibaba Cloud Security Token", @@ -63,7 +115,7 @@ func New() backend.Backend { Description: "The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console.", }, - "region": &schema.Schema{ + "region": { Type: schema.TypeString, Optional: true, Description: "The region of the OSS bucket.", @@ -82,13 +134,13 @@ func New() backend.Backend { DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_OSS_ENDPOINT", os.Getenv("OSS_ENDPOINT")), }, - "bucket": &schema.Schema{ + "bucket": { Type: schema.TypeString, Required: true, Description: "The name of the OSS bucket", }, - "prefix": &schema.Schema{ + "prefix": { Type: schema.TypeString, Optional: true, Description: "The directory where state files will be saved inside the bucket", @@ -102,7 +154,7 @@ func New() backend.Backend { }, }, - "key": &schema.Schema{ + "key": { Type: schema.TypeString, Optional: true, Description: "The path of the state file inside the bucket", @@ -122,14 +174,14 @@ func New() backend.Backend { Default: "", }, - "encrypt": &schema.Schema{ + "encrypt": { Type: schema.TypeBool, Optional: true, Description: "Whether to enable server side encryption of the state file", Default: false, }, - "acl": &schema.Schema{ + "acl": { Type: schema.TypeString, Optional: true, Description: "Object ACL to be applied to the state file", @@ -146,8 +198,6 @@ func New() backend.Backend { return nil, nil }, }, - - "assume_role": assumeRoleSchema(), "shared_credentials_file": { Type: schema.TypeString, Optional: true, @@ -160,60 +210,53 @@ func New() backend.Backend { Description: "This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable.", DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_PROFILE", ""), }, - }, - } - - result := &Backend{Backend: s} - result.Backend.ConfigureFunc = result.configure - return result -} - -func assumeRoleSchema() *schema.Schema { - return &schema.Schema{ - Type: schema.TypeSet, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "role_arn": { - Type: schema.TypeString, - Required: true, - Description: "The ARN of a RAM role to assume prior to making API calls.", - DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_ARN", ""), - }, - "session_name": { - Type: schema.TypeString, - Optional: true, - Description: "The session name to use when assuming the role.", - DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_SESSION_NAME", ""), - }, - "policy": { - Type: schema.TypeString, - Optional: true, - Description: "The permissions applied when assuming a role. You cannot use this policy to grant permissions which exceed those of the role that is being assumed.", - }, - "session_expiration": { - Type: schema.TypeInt, - Optional: true, - Description: "The time after which the established session for assuming role expires.", - ValidateFunc: func(v interface{}, k string) ([]string, []error) { - min := 900 - max := 3600 - value, ok := v.(int) - if !ok { - return nil, []error{fmt.Errorf("expected type of %s to be int", k)} - } + "assume_role": deprecatedAssumeRoleSchema(), + "assume_role_role_arn": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"assume_role"}, + Description: "The ARN of a RAM role to assume prior to making API calls.", + DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_ARN", ""), + }, + "assume_role_session_name": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"assume_role"}, + Description: "The session name to use when assuming the role.", + DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_SESSION_NAME", ""), + }, + "assume_role_policy": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"assume_role"}, + Description: "The permissions applied when assuming a role. You cannot use this policy to grant permissions which exceed those of the role that is being assumed.", + }, + "assume_role_session_expiration": { + Type: schema.TypeInt, + Optional: true, + ConflictsWith: []string{"assume_role"}, + Description: "The time after which the established session for assuming role expires.", + ValidateFunc: func(v interface{}, k string) ([]string, []error) { + min := 900 + max := 3600 + value, ok := v.(int) + if !ok { + return nil, []error{fmt.Errorf("expected type of %s to be int", k)} + } - if value < min || value > max { - return nil, []error{fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)} - } + if value < min || value > max { + return nil, []error{fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)} + } - return nil, nil - }, + return nil, nil }, }, }, } + + result := &Backend{Backend: s} + result.Backend.ConfigureFunc = result.configure + return result } type Backend struct { @@ -228,7 +271,6 @@ type Backend struct { stateKey string serverSideEncryption bool acl string - endpoint string otsEndpoint string otsTable string } @@ -275,6 +317,7 @@ func (b *Backend) configure(ctx context.Context) error { } if v, ok := d.GetOk("assume_role"); ok { + // deprecated assume_role block for _, v := range v.(*schema.Set).List() { assumeRole := v.(map[string]interface{}) if assumeRole["role_arn"].(string) != "" { @@ -283,22 +326,28 @@ func (b *Backend) configure(ctx context.Context) error { if assumeRole["session_name"].(string) != "" { sessionName = assumeRole["session_name"].(string) } - if sessionName == "" { - sessionName = "terraform" - } policy = assumeRole["policy"].(string) sessionExpiration = assumeRole["session_expiration"].(int) - if sessionExpiration == 0 { - if v := os.Getenv("ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION"); v != "" { - if expiredSeconds, err := strconv.Atoi(v); err == nil { - sessionExpiration = expiredSeconds - } - } - if sessionExpiration == 0 { - sessionExpiration = 3600 - } + } + } else { + roleArn = d.Get("assume_role_role_arn").(string) + sessionName = d.Get("assume_role_session_name").(string) + policy = d.Get("assume_role_policy").(string) + sessionExpiration = d.Get("assume_role_session_expiration").(int) + } + + if sessionName == "" { + sessionName = "terraform" + } + if sessionExpiration == 0 { + if v := os.Getenv("ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION"); v != "" { + if expiredSeconds, err := strconv.Atoi(v); err == nil { + sessionExpiration = expiredSeconds } } + if sessionExpiration == 0 { + sessionExpiration = 3600 + } } if accessKey == "" { @@ -372,13 +421,13 @@ func (b *Backend) getOSSEndpointByRegion(access_key, secret_key, security_token, locationClient, err := location.NewClientWithOptions(region, getSdkConfig(), credentials.NewStsTokenCredential(access_key, secret_key, security_token)) if err != nil { - return nil, fmt.Errorf("Unable to initialize the location client: %#v", err) + return nil, fmt.Errorf("unable to initialize the location client: %#v", err) } locationClient.AppendUserAgent(TerraformUA, TerraformVersion) endpointsResponse, err := locationClient.DescribeEndpoints(args) if err != nil { - return nil, fmt.Errorf("Describe oss endpoint using region: %#v got an error: %#v.", region, err) + return nil, fmt.Errorf("describe oss endpoint using region: %#v got an error: %#v", region, err) } return endpointsResponse, nil } @@ -468,7 +517,7 @@ func (a *Invoker) Run(f func() error) error { catcher.RetryCount-- if catcher.RetryCount <= 0 { - return fmt.Errorf("Retry timeout and got an error: %#v.", err) + return fmt.Errorf("retry timeout and got an error: %#v", err) } else { time.Sleep(time.Duration(catcher.RetryWaitSeconds) * time.Second) return a.Run(f) @@ -578,7 +627,7 @@ func getAuthCredentialByEcsRoleName(ecsRoleName string) (accessKey, secretKey, t response := responses.NewCommonResponse() err = responses.Unmarshal(response, httpResponse, "") if err != nil { - err = fmt.Errorf("Unmarshal Ecs sts token response err : %s", err.Error()) + err = fmt.Errorf("unmarshal Ecs sts token response err : %s", err.Error()) return } diff --git a/internal/backend/remote-state/oss/backend_state.go b/internal/backend/remote-state/oss/backend_state.go index d91ed6c5c9..1d5c1ce46e 100644 --- a/internal/backend/remote-state/oss/backend_state.go +++ b/internal/backend/remote-state/oss/backend_state.go @@ -3,19 +3,18 @@ package oss import ( "errors" "fmt" + "log" + "path" "sort" "strings" "github.com/aliyun/aliyun-oss-go-sdk/oss" + "github.com/aliyun/aliyun-tablestore-go-sdk/tablestore" + "github.com/hashicorp/terraform/internal/backend" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/states/remote" "github.com/hashicorp/terraform/internal/states/statemgr" - - "log" - "path" - - "github.com/aliyun/aliyun-tablestore-go-sdk/tablestore" ) const ( @@ -43,7 +42,7 @@ func (b *Backend) remoteClient(name string) (*RemoteClient, error) { TableName: b.otsTable, }) if err != nil { - return client, fmt.Errorf("Error describing table store %s: %#v", b.otsTable, err) + return client, fmt.Errorf("error describing table store %s: %#v", b.otsTable, err) } } @@ -53,7 +52,7 @@ func (b *Backend) remoteClient(name string) (*RemoteClient, error) { func (b *Backend) Workspaces() ([]string, error) { bucket, err := b.ossClient.Bucket(b.bucketName) if err != nil { - return []string{""}, fmt.Errorf("Error getting bucket: %#v", err) + return []string{""}, fmt.Errorf("error getting bucket: %#v", err) } var options []oss.Option @@ -135,7 +134,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) { lockInfo.Operation = "init" lockId, err := client.Lock(lockInfo) if err != nil { - return nil, fmt.Errorf("Failed to lock OSS state: %s", err) + return nil, fmt.Errorf("failed to lock OSS state: %s", err) } // Local helper function so we can call it multiple places diff --git a/internal/backend/remote-state/oss/client.go b/internal/backend/remote-state/oss/client.go index ccf19576a2..78d835ae13 100644 --- a/internal/backend/remote-state/oss/client.go +++ b/internal/backend/remote-state/oss/client.go @@ -3,22 +3,21 @@ package oss import ( "bytes" "crypto/md5" + "encoding/hex" "encoding/json" "fmt" "io" - - "encoding/hex" "log" - "sync" "time" "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/aliyun-tablestore-go-sdk/tablestore" "github.com/hashicorp/go-multierror" uuid "github.com/hashicorp/go-uuid" + "github.com/pkg/errors" + "github.com/hashicorp/terraform/internal/states/remote" "github.com/hashicorp/terraform/internal/states/statemgr" - "github.com/pkg/errors" ) const ( @@ -48,8 +47,6 @@ type RemoteClient struct { lockFile string serverSideEncryption bool acl string - info *statemgr.LockInfo - mu sync.Mutex otsTable string } @@ -99,7 +96,7 @@ func (c *RemoteClient) Get() (payload *remote.Payload, err error) { func (c *RemoteClient) Put(data []byte) error { bucket, err := c.ossClient.Bucket(c.bucketName) if err != nil { - return fmt.Errorf("Error getting bucket: %#v", err) + return fmt.Errorf("error getting bucket: %#v", err) } body := bytes.NewReader(data) @@ -116,7 +113,7 @@ func (c *RemoteClient) Put(data []byte) error { if body != nil { if err := bucket.PutObject(c.stateFile, body, options...); err != nil { - return fmt.Errorf("Failed to upload state %s: %#v", c.stateFile, err) + return fmt.Errorf("failed to upload state %s: %#v", c.stateFile, err) } } @@ -124,7 +121,7 @@ func (c *RemoteClient) Put(data []byte) error { if err := c.putMD5(sum[:]); err != nil { // if this errors out, we unfortunately have to error out altogether, // since the next Get will inevitably fail. - return fmt.Errorf("Failed to store state MD5: %s", err) + return fmt.Errorf("failed to store state MD5: %s", err) } return nil } @@ -132,13 +129,13 @@ func (c *RemoteClient) Put(data []byte) error { func (c *RemoteClient) Delete() error { bucket, err := c.ossClient.Bucket(c.bucketName) if err != nil { - return fmt.Errorf("Error getting bucket %s: %#v", c.bucketName, err) + return fmt.Errorf("error getting bucket %s: %#v", c.bucketName, err) } log.Printf("[DEBUG] Deleting remote state from OSS: %#v", c.stateFile) if err := bucket.DeleteObject(c.stateFile); err != nil { - return fmt.Errorf("Error deleting state %s: %#v", c.stateFile, err) + return fmt.Errorf("error deleting state %s: %#v", c.stateFile, err) } if err := c.deleteMD5(); err != nil { @@ -413,11 +410,11 @@ func (c *RemoteClient) lockPath() string { func (c *RemoteClient) getObj() (*remote.Payload, error) { bucket, err := c.ossClient.Bucket(c.bucketName) if err != nil { - return nil, fmt.Errorf("Error getting bucket %s: %#v", c.bucketName, err) + return nil, fmt.Errorf("error getting bucket %s: %#v", c.bucketName, err) } if exist, err := bucket.IsObjectExist(c.stateFile); err != nil { - return nil, fmt.Errorf("Estimating object %s is exist got an error: %#v", c.stateFile, err) + return nil, fmt.Errorf("estimating object %s is exist got an error: %#v", c.stateFile, err) } else if !exist { return nil, nil } @@ -425,12 +422,12 @@ func (c *RemoteClient) getObj() (*remote.Payload, error) { var options []oss.Option output, err := bucket.GetObject(c.stateFile, options...) if err != nil { - return nil, fmt.Errorf("Error getting object: %#v", err) + return nil, fmt.Errorf("error getting object: %#v", err) } buf := bytes.NewBuffer(nil) if _, err := io.Copy(buf, output); err != nil { - return nil, fmt.Errorf("Failed to read remote state: %s", err) + return nil, fmt.Errorf("failed to read remote state: %s", err) } sum := md5.Sum(buf.Bytes()) payload := &remote.Payload{ @@ -452,5 +449,4 @@ This may be caused by unusually long delays in OSS processing a previous state update. Please wait for a minute or two and try again. If this problem persists, and neither OSS nor TableStore are experiencing an outage, you may need to manually verify the remote state and update the Digest value stored in the -TableStore table to the following value: %x -` +TableStore table to the following value: %x` diff --git a/website/docs/language/settings/backends/oss.html.md b/website/docs/language/settings/backends/oss.html.md index 6acc16af1c..92e0d3ab05 100644 --- a/website/docs/language/settings/backends/oss.html.md +++ b/website/docs/language/settings/backends/oss.html.md @@ -77,36 +77,41 @@ data "terraform_remote_state" "network" { The following configuration options or environment variables are supported: - * `access_key` - (Optional) Alibaba Cloud access key. It supports environment variables `ALICLOUD_ACCESS_KEY` and `ALICLOUD_ACCESS_KEY_ID`. - * `secret_key` - (Optional) Alibaba Cloud secret access key. It supports environment variables `ALICLOUD_SECRET_KEY` and `ALICLOUD_ACCESS_KEY_SECRET`. - * `security_token` - (Optional) STS access token. It supports environment variable `ALICLOUD_SECURITY_TOKEN`. - * `ecs_role_name` - (Optional, Available in 0.12.14+) The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console. - * `region` - (Optional) The region of the OSS bucket. It supports environment variables `ALICLOUD_REGION` and `ALICLOUD_DEFAULT_REGION`. - * `endpoint` - (Optional) A custom endpoint for the OSS API. It supports environment variables `ALICLOUD_OSS_ENDPOINT` and `OSS_ENDPOINT`. - * `bucket` - (Required) The name of the OSS bucket. - * `prefix` - (Opeional) The path directory of the state file will be stored. Default to "env:". - * `key` - (Optional) The name of the state file. Defaults to `terraform.tfstate`. - * `tablestore_endpoint` / `ALICLOUD_TABLESTORE_ENDPOINT` - (Optional) A custom endpoint for the TableStore API. - * `tablestore_table` - (Optional) A TableStore table for state locking and consistency. The table must have a primary key named `LockID` of type `String`. - * `encrypt` - (Optional) Whether to enable server side - encryption of the state file. If it is true, OSS will use 'AES256' encryption algorithm to encrypt state file. - * `acl` - (Optional) [Object - ACL](https://www.alibabacloud.com/help/doc-detail/52284.htm) - to be applied to the state file. - * `shared_credentials_file` - (Optional, Available in 0.12.8+) This is the path to the shared credentials file. It can also be sourced from the `ALICLOUD_SHARED_CREDENTIALS_FILE` environment variable. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used. - * `profile` - (Optional, Available in 0.12.8+) This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable. - * `assume_role` - (Optional, Available in 0.12.6+) If provided with a role ARN, will attempt to assume this role using the supplied credentials. - -The nested `assume_role` block supports the following: - -* `role_arn` - (Required) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports environment variable `ALICLOUD_ASSUME_ROLE_ARN`. +* `access_key` - (Optional) Alibaba Cloud access key. It supports environment variables `ALICLOUD_ACCESS_KEY` and `ALICLOUD_ACCESS_KEY_ID`. +* `secret_key` - (Optional) Alibaba Cloud secret access key. It supports environment variables `ALICLOUD_SECRET_KEY` and `ALICLOUD_ACCESS_KEY_SECRET`. +* `security_token` - (Optional) STS access token. It supports environment variable `ALICLOUD_SECURITY_TOKEN`. +* `ecs_role_name` - (Optional, Available in 0.12.14+) The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console. +* `region` - (Optional) The region of the OSS bucket. It supports environment variables `ALICLOUD_REGION` and `ALICLOUD_DEFAULT_REGION`. +* `endpoint` - (Optional) A custom endpoint for the OSS API. It supports environment variables `ALICLOUD_OSS_ENDPOINT` and `OSS_ENDPOINT`. +* `bucket` - (Required) The name of the OSS bucket. +* `prefix` - (Opeional) The path directory of the state file will be stored. Default to "env:". +* `key` - (Optional) The name of the state file. Defaults to `terraform.tfstate`. +* `tablestore_endpoint` / `ALICLOUD_TABLESTORE_ENDPOINT` - (Optional) A custom endpoint for the TableStore API. +* `tablestore_table` - (Optional) A TableStore table for state locking and consistency. The table must have a primary key named `LockID` of type `String`. +* `encrypt` - (Optional) Whether to enable server side + encryption of the state file. If it is true, OSS will use 'AES256' encryption algorithm to encrypt state file. +* `acl` - (Optional) [Object + ACL](https://www.alibabacloud.com/help/doc-detail/52284.htm) + to be applied to the state file. +* `shared_credentials_file` - (Optional, Available in 0.12.8+) This is the path to the shared credentials file. It can also be sourced from the `ALICLOUD_SHARED_CREDENTIALS_FILE` environment variable. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used. +* `profile` - (Optional, Available in 0.12.8+) This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable. +* `assume_role_role_arn` - (Optional, Available in 1.1.0+) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports the environment variable `ALICLOUD_ASSUME_ROLE_ARN`. Terraform executes configuration on account with provided credentials. +* `assume_role_policy` - (Optional, Available in 1.1.0+ A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use this policy to grant permissions that exceed those of the role that is being assumed. +* `assume_role_session_name` - (Optional, Available in 1.1.0+) The session name to use when assuming the role. If omitted, 'terraform' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`. +* `assume_role_session_expiration` - (Optional, Available in 1.1.0+ The time after which the established session for assuming role expires. Valid value range: [900-3600] seconds. Default to 3600 (in this case Alibaba Cloud uses its own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`. -* `policy` - (Optional) A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary - security credentials. You cannot use this policy to grant permissions which exceed those of the role that is being assumed. +* `assume_role` - (**Deprecated as of 1.1.0+**, Available in 0.12.6+) If provided with a role ARN, will attempt to assume this role using the supplied credentials. -* `session_name` - (Optional) The session name to use when assuming the role. If omitted, 'terraform' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`. + **Deprecated in favor of flattening assume_role_\* options** -* `session_expiration` - (Optional) The time after which the established session for assuming role expires. Valid value range: [900-3600] seconds. Default to 3600 (in this case Alibaba Cloud use own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`. + * `role_arn` - (Required) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports the environment variable `ALICLOUD_ASSUME_ROLE_ARN`. + Terraform executes configuration on account with provided credentials. --> **Note:** If you want to store state in the custom OSS endpoint, you can specify a environment variable `OSS_ENDPOINT`, like "oss-cn-beijing-internal.aliyuncs.com" + * `policy` - (Optional) A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use this policy to grant permissions that exceed those of the role that is being assumed. + + * `session_name` - (Optional) The session name to use when assuming the role. If omitted, 'terraform' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`. + + * `session_expiration` - (Optional) The time after which the established session for assuming role expires. Valid value range: [900-3600] seconds. Default to 3600 (in this case Alibaba Cloud uses its own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`. + +-> **Note:** If you want to store state in the custom OSS endpoint, you can specify an environment variable `OSS_ENDPOINT`, like "oss-cn-beijing-internal.aliyuncs.com"