Skip to content

Commit 62d561b

Browse files
feat: Support setting storage_aws_external_id in storage integration resource (#3659)
## Summary This PR adds support for specifying the `storage_aws_external_id` field when creating and updating a Snowflake storage integration resource. Previously, the field was treated as `Computed` and could not be explicitly set via Terraform, which caused issues in scenarios involving AWS IAM role trust relationships requiring a fixed external ID. ## What was changed - Updated the Create and Alter function in sdk to pass the value to the Snowflake API if specified. - Changed `storage_aws_external_id` attribute to be `Optional`. - Added acceptance test to verify the behavior. - Updated doc of storage integration. - Add clarification of missing support for Git API integrations. ## Test Plan * [x] integration tests for storage integration * [ ] acceptance tests for storage integration ## References - #2624 --------- Co-authored-by: Jakub Michalak <[email protected]>
1 parent 640cf8c commit 62d561b

22 files changed

+687
-167
lines changed

MIGRATION_GUIDE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ for changes required after enabling given [Snowflake BCR Bundle](https://docs.sn
2121
> [!TIP]
2222
> If you're still using the `Snowflake-Labs/snowflake` source, see [Upgrading from Snowflake-Labs Provider](./SNOWFLAKEDB_MIGRATION.md) to upgrade to the snowflakedb namespace.
2323
24+
## v2.4.x ➞ v2.5.0
25+
26+
### *(new feature)* Added `storage_aws_external_id` field in the `storage_integration` resource
27+
28+
Previously, this field was read-only. In this version, this field is an optional configurable attribute. Additionally, we added a new `describe_output` field to handle this field properly (read more in our [design considerations](v1-preparations/CHANGES_BEFORE_V1.md#default-values)). Note that fields other than `storage_aws_external_id` do not leverage this field. This will be addressed during the resource rework.
29+
30+
Note that this resource is still in preview, and not officially supported. This change was requested and done by the community: [#3659](https://github.com/snowflakedb/terraform-provider-snowflake/pull/3659).
31+
2432
## v2.3.0 ➞ v2.4.0
2533

2634
### *(new feature)* snowflake_current_organization_account resource

docs/resources/api_integration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ description: |-
77

88
!> **Caution: Preview Feature** This feature is considered a preview feature in the provider, regardless of the state of the resource in Snowflake. We do not guarantee its stability. It will be reworked and marked as a stable feature in future releases. Breaking changes are expected, even without bumping the major version. To use this feature, add the relevant feature name to `preview_features_enabled` field in the [provider configuration](https://registry.terraform.io/providers/snowflakedb/snowflake/latest/docs#schema). Please always refer to the [Getting Help](https://github.com/snowflakedb/terraform-provider-snowflake?tab=readme-ov-file#getting-help) section in our Github repo to best determine how to get help for your questions.
99

10+
-> **Note** Currently, API integrations for `git_https_api` API provider are not supported. It will be added in the future.
11+
1012
# snowflake_api_integration (Resource)
1113

1214

docs/resources/storage_integration.md

Lines changed: 167 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ description: |-
77

88
!> **Caution: Preview Feature** This feature is considered a preview feature in the provider, regardless of the state of the resource in Snowflake. We do not guarantee its stability. It will be reworked and marked as a stable feature in future releases. Breaking changes are expected, even without bumping the major version. To use this feature, add the relevant feature name to `preview_features_enabled` field in the [provider configuration](https://registry.terraform.io/providers/snowflakedb/snowflake/latest/docs#schema). Please always refer to the [Getting Help](https://github.com/snowflakedb/terraform-provider-snowflake?tab=readme-ov-file#getting-help) section in our Github repo to best determine how to get help for your questions.
99

10+
-> **Note** Currently, `describe_output` field is not used in all the relevant fields (only `storage_aws_external_id` is supported). This will be addressed during the resource rework.
11+
1012
# snowflake_storage_integration (Resource)
1113

1214

@@ -29,7 +31,7 @@ resource "snowflake_storage_integration" "integration" {
2931
# storage_aws_object_acl = "bucket-owner-full-control"
3032
3133
storage_provider = "S3"
32-
storage_aws_external_id = "..."
34+
storage_aws_external_id = "ABC12345_DEFRole=2_123ABC459AWQmtAdRqwe/A=="
3335
storage_aws_iam_user_arn = "..."
3436
storage_aws_role_arn = "..."
3537
@@ -53,6 +55,7 @@ resource "snowflake_storage_integration" "integration" {
5355
- `azure_tenant_id` (String) (Default: ``)
5456
- `comment` (String) (Default: ``)
5557
- `enabled` (Boolean) (Default: `true`)
58+
- `storage_aws_external_id` (String) The external ID that Snowflake will use when assuming the AWS role.
5659
- `storage_aws_object_acl` (String) "bucket-owner-full-control" Enables support for AWS access control lists (ACLs) to grant the bucket owner full control.
5760
- `storage_aws_role_arn` (String) (Default: ``)
5861
- `storage_blocked_locations` (List of String) Explicitly prohibits external stages that use the integration from referencing one or more storage locations.
@@ -64,9 +67,9 @@ resource "snowflake_storage_integration" "integration" {
6467
- `azure_consent_url` (String, Sensitive) The consent URL that is used to create an Azure Snowflake service principle inside your tenant.
6568
- `azure_multi_tenant_app_name` (String) This is the name of the Snowflake client application created for your account.
6669
- `created_on` (String) Date and time when the storage integration was created.
70+
- `describe_output` (List of Object) Outputs the result of `DESCRIBE STORAGE INTEGRATION` for the given storage integration. (see [below for nested schema](#nestedatt--describe_output))
6771
- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
6872
- `id` (String) The ID of this resource.
69-
- `storage_aws_external_id` (String) The external ID that Snowflake will use when assuming the AWS role.
7073
- `storage_aws_iam_user_arn` (String) The Snowflake user that will attempt to assume the AWS role.
7174
- `storage_gcp_service_account` (String) This is the name of the Snowflake Google Service Account created for your account.
7275

@@ -80,6 +83,168 @@ Optional:
8083
- `read` (String)
8184
- `update` (String)
8285

86+
87+
<a id="nestedatt--describe_output"></a>
88+
### Nested Schema for `describe_output`
89+
90+
Read-Only:
91+
92+
- `azure_consent_url` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--azure_consent_url))
93+
- `azure_multi_tenant_app_name` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--azure_multi_tenant_app_name))
94+
- `comment` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--comment))
95+
- `enabled` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--enabled))
96+
- `storage_allowed_locations` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_allowed_locations))
97+
- `storage_aws_external_id` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_aws_external_id))
98+
- `storage_aws_iam_user_arn` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_aws_iam_user_arn))
99+
- `storage_aws_object_acl` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_aws_object_acl))
100+
- `storage_aws_role_arn` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_aws_role_arn))
101+
- `storage_blocked_locations` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_blocked_locations))
102+
- `storage_gcp_service_account` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_gcp_service_account))
103+
- `storage_provider` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--storage_provider))
104+
- `use_privatelink_endpoint` (List of Object) (see [below for nested schema](#nestedobjatt--describe_output--use_privatelink_endpoint))
105+
106+
<a id="nestedobjatt--describe_output--azure_consent_url"></a>
107+
### Nested Schema for `describe_output.azure_consent_url`
108+
109+
Read-Only:
110+
111+
- `default` (String)
112+
- `name` (String)
113+
- `type` (String)
114+
- `value` (String)
115+
116+
117+
<a id="nestedobjatt--describe_output--azure_multi_tenant_app_name"></a>
118+
### Nested Schema for `describe_output.azure_multi_tenant_app_name`
119+
120+
Read-Only:
121+
122+
- `default` (String)
123+
- `name` (String)
124+
- `type` (String)
125+
- `value` (String)
126+
127+
128+
<a id="nestedobjatt--describe_output--comment"></a>
129+
### Nested Schema for `describe_output.comment`
130+
131+
Read-Only:
132+
133+
- `default` (String)
134+
- `name` (String)
135+
- `type` (String)
136+
- `value` (String)
137+
138+
139+
<a id="nestedobjatt--describe_output--enabled"></a>
140+
### Nested Schema for `describe_output.enabled`
141+
142+
Read-Only:
143+
144+
- `default` (String)
145+
- `name` (String)
146+
- `type` (String)
147+
- `value` (String)
148+
149+
150+
<a id="nestedobjatt--describe_output--storage_allowed_locations"></a>
151+
### Nested Schema for `describe_output.storage_allowed_locations`
152+
153+
Read-Only:
154+
155+
- `default` (String)
156+
- `name` (String)
157+
- `type` (String)
158+
- `value` (String)
159+
160+
161+
<a id="nestedobjatt--describe_output--storage_aws_external_id"></a>
162+
### Nested Schema for `describe_output.storage_aws_external_id`
163+
164+
Read-Only:
165+
166+
- `default` (String)
167+
- `name` (String)
168+
- `type` (String)
169+
- `value` (String)
170+
171+
172+
<a id="nestedobjatt--describe_output--storage_aws_iam_user_arn"></a>
173+
### Nested Schema for `describe_output.storage_aws_iam_user_arn`
174+
175+
Read-Only:
176+
177+
- `default` (String)
178+
- `name` (String)
179+
- `type` (String)
180+
- `value` (String)
181+
182+
183+
<a id="nestedobjatt--describe_output--storage_aws_object_acl"></a>
184+
### Nested Schema for `describe_output.storage_aws_object_acl`
185+
186+
Read-Only:
187+
188+
- `default` (String)
189+
- `name` (String)
190+
- `type` (String)
191+
- `value` (String)
192+
193+
194+
<a id="nestedobjatt--describe_output--storage_aws_role_arn"></a>
195+
### Nested Schema for `describe_output.storage_aws_role_arn`
196+
197+
Read-Only:
198+
199+
- `default` (String)
200+
- `name` (String)
201+
- `type` (String)
202+
- `value` (String)
203+
204+
205+
<a id="nestedobjatt--describe_output--storage_blocked_locations"></a>
206+
### Nested Schema for `describe_output.storage_blocked_locations`
207+
208+
Read-Only:
209+
210+
- `default` (String)
211+
- `name` (String)
212+
- `type` (String)
213+
- `value` (String)
214+
215+
216+
<a id="nestedobjatt--describe_output--storage_gcp_service_account"></a>
217+
### Nested Schema for `describe_output.storage_gcp_service_account`
218+
219+
Read-Only:
220+
221+
- `default` (String)
222+
- `name` (String)
223+
- `type` (String)
224+
- `value` (String)
225+
226+
227+
<a id="nestedobjatt--describe_output--storage_provider"></a>
228+
### Nested Schema for `describe_output.storage_provider`
229+
230+
Read-Only:
231+
232+
- `default` (String)
233+
- `name` (String)
234+
- `type` (String)
235+
- `value` (String)
236+
237+
238+
<a id="nestedobjatt--describe_output--use_privatelink_endpoint"></a>
239+
### Nested Schema for `describe_output.use_privatelink_endpoint`
240+
241+
Read-Only:
242+
243+
- `default` (String)
244+
- `name` (String)
245+
- `type` (String)
246+
- `value` (String)
247+
83248
## Import
84249

85250
Import is supported using the following syntax:

examples/resources/snowflake_storage_integration/resource.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ resource "snowflake_storage_integration" "integration" {
1010
# storage_aws_object_acl = "bucket-owner-full-control"
1111

1212
storage_provider = "S3"
13-
storage_aws_external_id = "..."
13+
storage_aws_external_id = "ABC12345_DEFRole=2_123ABC459AWQmtAdRqwe/A=="
1414
storage_aws_iam_user_arn = "..."
1515
storage_aws_role_arn = "..."
1616

pkg/acceptance/helpers/storage_integration_client.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,11 @@ func (c *StorageIntegrationClient) DropFunc(t *testing.T, id sdk.AccountObjectId
7777
require.NoError(t, err)
7878
}
7979
}
80+
81+
func (c *StorageIntegrationClient) Alter(t *testing.T, request *sdk.AlterStorageIntegrationRequest) {
82+
t.Helper()
83+
ctx := context.Background()
84+
85+
err := c.client().Alter(ctx, request)
86+
require.NoError(t, err)
87+
}

0 commit comments

Comments
 (0)