-
Notifications
You must be signed in to change notification settings - Fork 427
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add service user and legacy service user resources (#3119)
Introduce `snowflake_service_user` and `snowflake_legacy_service_user` resources: - Add new resources (almost the same schema and the same limitations as `snowflake_user` resource - read below) - Adjust datasource and add `type` to the `describe_output` - Adjust SDK: handling types - Add SDK integration tests to validate and document the Snowflake behavior of handling user types (create, alter set, alter unset, and parameters) - Fix `TestAcc_User_issue2970` test - Add migration guide - Generate models and assertions for the new resources - Fix sweepers References: #2951 ##### Implementation considerations Users of different types differ in Snowflake just slightly - a few fields are restricted from SERVICE and LEGACY_SERVICE type users. We decided to split Snowflake resources into multiple resources on our route to V1, to simplify the logic and usage (in this case, not to handle the type changes which are followed by attributes being hidden/revealed). That led to three choices for the implementation, to reuse the existing resource: - copy-paste `snowflake_user` resource - parameterized handling methods of `snowflake_user` resource with the user type - enrich the helper methods with the knowledge of the schema (i.e. to change the logic of setting a field to always check first if the attribute exists in the given schema) Ultimately, the second option was picked for the current implementation. More details of pros and cons of each solution are presented in points below. ###### copy-paste Pros: - Fastest implementation - We plan to ultimately generate the resources, so at the end the implementation would be close to duplicated resources Cons: - Need to alter the logic in three different places - Separate implementation of resources would require separate complete set of tests ###### parameterized handling methods Pros: - user object handled in "one" place - implementation reused, so only smoke acceptance tests are justified Cons: - more complex logic in user resource, spread over multiple handling methods ###### enrich the helper methods Pros: - user resource implementation could stay the same in helper methods (because the checks would be delegated to helper methods) - solution that can be reused in more resources - only smoke tests would be justified Cons: - SDKv2 does not allow to fetch the schema in context of helper methods without exposing unexported fields - "unsafe" solution potentially used in the majority of resources (because helper methods should be reused more and more)
- Loading branch information
1 parent
97fa9b4
commit 0e88e08
Showing
40 changed files
with
9,312 additions
and
524 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,67 @@ resource "snowflake_stream_on_table" "stream" { | |
|
||
Then, follow our [Resource migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/resource_migration.md). | ||
|
||
### *(new feature)* new snowflake_service_user and snowflake_legacy_service_user resources | ||
|
||
Release v0.95.0 introduced reworked `snowflake_user` resource. As [noted](#note-user-types), the new `SERVICE` and `LEGACY_SERVICE` user types were not supported. | ||
|
||
This release introduces two new resources to handle these new user types: `snowflake_service_user` and `snowflake_legacy_service_user`. | ||
|
||
Both resources have schemas almost identical to the `snowflake_user` resource with the following exceptions: | ||
- `snowflake_service_user` does not contain the following fields (because they are not supported for the user of type `SERVICE` in Snowflake): | ||
- `password` | ||
- `first_name` | ||
- `middle_name` | ||
- `last_name` | ||
- `must_change_password` | ||
- `mins_to_bypass_mfa` | ||
- `disable_mfa` | ||
- `snowflake_legacy_service_user` does not contain the following fields (because they are not supported for the user of type `LEGACY_SERVICE` in Snowflake): | ||
- `first_name` | ||
- `middle_name` | ||
- `last_name` | ||
- `mins_to_bypass_mfa` | ||
- `disable_mfa` | ||
|
||
`snowflake_users` datasource was adjusted to handle different user types and `type` field was added to the `describe_output`. | ||
|
||
If you used to manage service or legacy service users through `snowflake_user` resource (e.g. using `lifecycle.ignore_changes`) or `snowflake_unsafe_execute`, please migrate to the new resources following [our guidelines on resource migration](docs/technical-documentation/resource_migration.md). | ||
|
||
E.g. change the old config from: | ||
|
||
```terraform | ||
resource "snowflake_user" "service_user" { | ||
lifecycle { | ||
ignore_changes = [user_type] | ||
} | ||
name = "Snowflake Service User" | ||
login_name = "service_user" | ||
email = "[email protected]" | ||
rsa_public_key = "..." | ||
rsa_public_key_2 = "..." | ||
} | ||
``` | ||
|
||
to | ||
|
||
``` | ||
resource "snowflake_service_user" "service_user" { | ||
name = "Snowflake Service User" | ||
login_name = "service_user" | ||
email = "[email protected]" | ||
rsa_public_key = "..." | ||
rsa_public_key_2 = "..." | ||
} | ||
``` | ||
|
||
Then, follow our [resource migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/resource_migration.md). | ||
|
||
Connected issues: [#2951](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2951) | ||
|
||
## v0.95.0 ➞ v0.96.0 | ||
|
||
### snowflake_masking_policies data source changes | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
page_title: "snowflake_user Resource - terraform-provider-snowflake" | ||
subcategory: "" | ||
description: |- | ||
Resource used to manage user objects. For more information, check user documentation https://docs.snowflake.com/en/sql-reference/commands-user-role. | ||
Resource used to manage user objects. For more information, check user documentation https://docs.snowflake.com/en/sql-reference/commands-user-role#user-management. | ||
--- | ||
|
||
!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v094x--v0950) to use it. | ||
|
@@ -11,36 +11,113 @@ description: |- | |
|
||
-> **Note** Attaching user policies will be handled in the following versions of the provider which may still affect this resource. | ||
|
||
-> **Note** `service` and `legacy_service` user types are currently not supported. They will be supported in the following versions as separate resources (namely `snowflake_service_user` and `snowflake_legacy_service_user`). | ||
-> **Note** Other two user types are handled in separate resources: `snowflake_service_user` for user type `service` and `snowflake_legacy_service_user` for user type `legacy_service`. | ||
|
||
-> **Note** External changes to `days_to_expiry`, `mins_to_unlock`, and `mins_to_bypass_mfa` are not currently handled by the provider (because the value changes continuously on Snowflake side after setting it). | ||
|
||
# snowflake_user (Resource) | ||
|
||
Resource used to manage user objects. For more information, check [user documentation](https://docs.snowflake.com/en/sql-reference/commands-user-role). | ||
Resource used to manage user objects. For more information, check [user documentation](https://docs.snowflake.com/en/sql-reference/commands-user-role#user-management). | ||
|
||
## Example Usage | ||
|
||
```terraform | ||
# minimal | ||
resource "snowflake_user" "minimal" { | ||
name = "Snowflake User - minimal" | ||
} | ||
# with all attributes set | ||
resource "snowflake_user" "user" { | ||
name = "Snowflake User" | ||
login_name = "snowflake_user" | ||
comment = "A user of snowflake." | ||
password = "secret" | ||
disabled = false | ||
display_name = "Snowflake User" | ||
email = "[email protected]" | ||
first_name = "Snowflake" | ||
middle_name = "Middle" | ||
last_name = "User" | ||
comment = "User of snowflake." | ||
password = "secret" | ||
disabled = "false" | ||
display_name = "Snowflake User display name" | ||
email = "[email protected]" | ||
default_warehouse = "warehouse" | ||
default_secondary_roles_option = "ALL" | ||
default_role = "role1" | ||
default_namespace = "some.namespace" | ||
default_warehouse = "warehouse" | ||
default_secondary_roles = "ALL" | ||
default_role = "role1" | ||
mins_to_unlock = 9 | ||
days_to_expiry = 8 | ||
mins_to_bypass_mfa = 10 | ||
rsa_public_key = "..." | ||
rsa_public_key_2 = "..." | ||
must_change_password = false | ||
must_change_password = "true" | ||
disable_mfa = "false" | ||
} | ||
# all parameters set on the resource level | ||
resource "snowflake_user" "u" { | ||
name = "Snowflake User with all parameters" | ||
abort_detached_query = true | ||
autocommit = false | ||
binary_input_format = "UTF8" | ||
binary_output_format = "BASE64" | ||
client_memory_limit = 1024 | ||
client_metadata_request_use_connection_ctx = true | ||
client_prefetch_threads = 2 | ||
client_result_chunk_size = 48 | ||
client_result_column_case_insensitive = true | ||
client_session_keep_alive = true | ||
client_session_keep_alive_heartbeat_frequency = 2400 | ||
client_timestamp_type_mapping = "TIMESTAMP_NTZ" | ||
date_input_format = "YYYY-MM-DD" | ||
date_output_format = "YY-MM-DD" | ||
enable_unload_physical_type_optimization = false | ||
enable_unredacted_query_syntax_error = true | ||
error_on_nondeterministic_merge = false | ||
error_on_nondeterministic_update = true | ||
geography_output_format = "WKB" | ||
geometry_output_format = "WKB" | ||
jdbc_treat_decimal_as_int = false | ||
jdbc_treat_timestamp_ntz_as_utc = true | ||
jdbc_use_session_timezone = false | ||
json_indent = 4 | ||
lock_timeout = 21222 | ||
log_level = "ERROR" | ||
multi_statement_count = 0 | ||
network_policy = "BVYDGRAT_0D5E3DD1_F644_03DE_318A_1179886518A7" | ||
noorder_sequence_as_default = false | ||
odbc_treat_decimal_as_int = true | ||
prevent_unload_to_internal_stages = true | ||
query_tag = "some_tag" | ||
quoted_identifiers_ignore_case = true | ||
rows_per_resultset = 2 | ||
search_path = "$public, $current" | ||
simulated_data_sharing_consumer = "some_consumer" | ||
statement_queued_timeout_in_seconds = 10 | ||
statement_timeout_in_seconds = 10 | ||
strict_json_output = true | ||
s3_stage_vpce_dns_name = "vpce-id.s3.region.vpce.amazonaws.com" | ||
time_input_format = "HH24:MI" | ||
time_output_format = "HH24:MI" | ||
timestamp_day_is_always_24h = true | ||
timestamp_input_format = "YYYY-MM-DD" | ||
timestamp_ltz_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timestamp_ntz_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timestamp_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timestamp_type_mapping = "TIMESTAMP_LTZ" | ||
timestamp_tz_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timezone = "Europe/Warsaw" | ||
trace_level = "ON_EVENT" | ||
transaction_abort_on_error = true | ||
transaction_default_isolation_level = "READ COMMITTED" | ||
two_digit_century_start = 1980 | ||
unsupported_ddl_action = "FAIL" | ||
use_cached_result = false | ||
week_of_year_policy = 1 | ||
week_start = 1 | ||
} | ||
``` | ||
-> **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources). | ||
|
@@ -942,5 +1019,5 @@ Read-Only: | |
Import is supported using the following syntax: | ||
|
||
```shell | ||
terraform import snowflake_user.example userName | ||
terraform import snowflake_user.example '"<user_name>"' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
terraform import snowflake_legacy_service_user.example '"<user_name>"' |
92 changes: 92 additions & 0 deletions
92
examples/resources/snowflake_legacy_service_user/resource.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# minimal | ||
resource "snowflake_legacy_service_user" "minimal" { | ||
name = "Snowflake Legacy Service User - minimal" | ||
} | ||
|
||
# with all attributes set | ||
resource "snowflake_legacy_service_user" "user" { | ||
name = "Snowflake Legacy Service User" | ||
login_name = "legacy_service_user" | ||
comment = "A legacy service user of snowflake." | ||
password = "secret" | ||
disabled = "false" | ||
display_name = "Snowflake Legacy Service User display name" | ||
email = "[email protected]" | ||
|
||
default_warehouse = "warehouse" | ||
default_secondary_roles_option = "ALL" | ||
default_role = "role1" | ||
default_namespace = "some.namespace" | ||
|
||
mins_to_unlock = 9 | ||
days_to_expiry = 8 | ||
|
||
rsa_public_key = "..." | ||
rsa_public_key_2 = "..." | ||
|
||
must_change_password = "true" | ||
} | ||
|
||
# all parameters set on the resource level | ||
resource "snowflake_legacy_service_user" "u" { | ||
name = "Snowflake Legacy Service User with all parameters" | ||
|
||
abort_detached_query = true | ||
autocommit = false | ||
binary_input_format = "UTF8" | ||
binary_output_format = "BASE64" | ||
client_memory_limit = 1024 | ||
client_metadata_request_use_connection_ctx = true | ||
client_prefetch_threads = 2 | ||
client_result_chunk_size = 48 | ||
client_result_column_case_insensitive = true | ||
client_session_keep_alive = true | ||
client_session_keep_alive_heartbeat_frequency = 2400 | ||
client_timestamp_type_mapping = "TIMESTAMP_NTZ" | ||
date_input_format = "YYYY-MM-DD" | ||
date_output_format = "YY-MM-DD" | ||
enable_unload_physical_type_optimization = false | ||
enable_unredacted_query_syntax_error = true | ||
error_on_nondeterministic_merge = false | ||
error_on_nondeterministic_update = true | ||
geography_output_format = "WKB" | ||
geometry_output_format = "WKB" | ||
jdbc_treat_decimal_as_int = false | ||
jdbc_treat_timestamp_ntz_as_utc = true | ||
jdbc_use_session_timezone = false | ||
json_indent = 4 | ||
lock_timeout = 21222 | ||
log_level = "ERROR" | ||
multi_statement_count = 0 | ||
network_policy = "BVYDGRAT_0D5E3DD1_F644_03DE_318A_1179886518A7" | ||
noorder_sequence_as_default = false | ||
odbc_treat_decimal_as_int = true | ||
prevent_unload_to_internal_stages = true | ||
query_tag = "some_tag" | ||
quoted_identifiers_ignore_case = true | ||
rows_per_resultset = 2 | ||
search_path = "$public, $current" | ||
simulated_data_sharing_consumer = "some_consumer" | ||
statement_queued_timeout_in_seconds = 10 | ||
statement_timeout_in_seconds = 10 | ||
strict_json_output = true | ||
s3_stage_vpce_dns_name = "vpce-id.s3.region.vpce.amazonaws.com" | ||
time_input_format = "HH24:MI" | ||
time_output_format = "HH24:MI" | ||
timestamp_day_is_always_24h = true | ||
timestamp_input_format = "YYYY-MM-DD" | ||
timestamp_ltz_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timestamp_ntz_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timestamp_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timestamp_type_mapping = "TIMESTAMP_LTZ" | ||
timestamp_tz_output_format = "YYYY-MM-DD HH24:MI:SS" | ||
timezone = "Europe/Warsaw" | ||
trace_level = "ON_EVENT" | ||
transaction_abort_on_error = true | ||
transaction_default_isolation_level = "READ COMMITTED" | ||
two_digit_century_start = 1980 | ||
unsupported_ddl_action = "FAIL" | ||
use_cached_result = false | ||
week_of_year_policy = 1 | ||
week_start = 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
terraform import snowflake_service_user.example '"<user_name>"' |
Oops, something went wrong.