Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Rework user resource #3026

Merged
merged 45 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
4999b41
rework user resource starts here
sfc-gh-asawicki Aug 23, 2024
8597e23
Initial adjustment of user's schema
sfc-gh-asawicki Aug 23, 2024
a857d11
Fix markdown for user's migration guide
sfc-gh-asawicki Aug 23, 2024
c3974f2
Add disable_mfa to the SDK
sfc-gh-asawicki Aug 23, 2024
78110f0
Add disable_mfa to schema (without logic yet)
sfc-gh-asawicki Aug 23, 2024
3cf0ffd
Remove comment
sfc-gh-asawicki Aug 23, 2024
0e5c180
Remove has_rsa_public_key computed attribute
sfc-gh-asawicki Aug 23, 2024
c7a20ba
Remove comment on specifying fp for rsa/rsa2
sfc-gh-asawicki Aug 23, 2024
4e76f6a
Test mins to bypass mfa
sfc-gh-asawicki Aug 23, 2024
5bfd3b7
Change secondary roles handling in resource and in the SDK
sfc-gh-asawicki Aug 23, 2024
c3b7889
Document login_name and display name behavior
sfc-gh-asawicki Aug 29, 2024
128ede5
Document how user's email is handled on Snowflake side
sfc-gh-asawicki Aug 29, 2024
018cbe4
Test days to expiry on the SDK level
sfc-gh-asawicki Aug 29, 2024
762df08
Document mins to unlock behavior
sfc-gh-asawicki Aug 29, 2024
455037c
Change import and create (WIP)
sfc-gh-asawicki Aug 29, 2024
e0795d1
Introduce attribute create helpers
sfc-gh-asawicki Aug 29, 2024
eaed906
Apply all attribute helpers in user resource
sfc-gh-asawicki Aug 29, 2024
34da521
Rename file and add placeholders for read and update helpers
sfc-gh-asawicki Aug 29, 2024
48a9ef2
Prepare to handle update correctly
sfc-gh-asawicki Aug 29, 2024
a1897be
Proceed with update
sfc-gh-asawicki Aug 29, 2024
072c29c
Finish with update
sfc-gh-asawicki Aug 29, 2024
589d315
Handle disable mfa after create
sfc-gh-asawicki Aug 29, 2024
5903cb6
Read user attributes (without external changes)
sfc-gh-asawicki Aug 29, 2024
88eef60
Handle external changes in read
sfc-gh-asawicki Aug 29, 2024
6f9d6da
Test days to expiry, finish import, regenerate assertions
sfc-gh-asawicki Aug 29, 2024
9631227
Update customized diffs
sfc-gh-asawicki Aug 29, 2024
c8662d5
Unskip the test for disabled attribute
sfc-gh-asawicki Aug 29, 2024
ff188f2
Solve TODOs for user parameters tests
sfc-gh-asawicki Aug 29, 2024
58863a8
Move schema parameters list to the SDK
sfc-gh-asawicki Aug 29, 2024
92bbdfc
Reuse parameterDef
sfc-gh-asawicki Aug 29, 2024
e9acc9a
Fix linter
sfc-gh-asawicki Aug 29, 2024
af3b932
Extract deprecated checkBool
sfc-gh-asawicki Aug 29, 2024
2fb0d3a
Simplify acceptance tests setups (WIP)
sfc-gh-asawicki Aug 29, 2024
e6e3a86
Add a TODO
sfc-gh-asawicki Aug 29, 2024
1b548b5
Update issue numbers in TODOs
sfc-gh-asawicki Aug 29, 2024
b8bbbbd
Handle external type change
sfc-gh-asawicki Aug 29, 2024
fabd0ed
Extract issue for policies for user
sfc-gh-asawicki Aug 30, 2024
80c287b
Replace string configs with model builders
sfc-gh-asawicki Aug 30, 2024
b190577
Replace old assertions and fix import test
sfc-gh-asawicki Aug 30, 2024
f4d7f58
Progress with basic flows test
sfc-gh-asawicki Aug 30, 2024
efae40c
Pass basic flows test
sfc-gh-asawicki Aug 30, 2024
a1bafdf
Test default secondary roles thoroughly
sfc-gh-asawicki Aug 30, 2024
4a14f26
Run make pre-push
sfc-gh-asawicki Aug 30, 2024
5a25b80
Fix after review
sfc-gh-asawicki Aug 30, 2024
0a6eeef
Fix tests
sfc-gh-asawicki Aug 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,24 +206,55 @@ The following set of [parameters](https://docs.snowflake.com/en/sql-reference/pa

Connected issues: [#2938](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2938)

### *(breaking change)* Changes in sensitiveness of name and login_name
#### *(breaking change)* Changes in sensitiveness of name, login_name, and display_name

According to https://docs.snowflake.com/en/sql-reference/functions/all_user_names#usage-notes, `NAME`s are not considered sensitive data and `LOGIN_NAME`s are. Previous versions of the provider had this the other way around. In this version, `name` attribute was unmarked as sensitive, whereas `login_name` was marked as sensitive. This may break your configuration if you were using `login_name`s before e.g. in a `for_each` loop.

The `display_name` attribute was marked as sensitive. It defaults to `name` if not provided on Snowflake side. Because `name` is no longer sensitive, we also change the setting for the `display_name`.

Connected issues: [#2662](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2662), [#2668](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2668).

### *(bugfix)* Correctly handle `default_warehouse`, `default_namespace`, and `default_role`
#### *(bugfix)* Correctly handle `default_warehouse`, `default_namespace`, and `default_role`

During the [identifiers rework](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/ROADMAP.md#identifiers-rework), we generalized how we compute the differences correctly for the identifier fields (read more in [this document](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md)). Proper suppressor was applied to `default_warehouse`, `default_namespace`, and `default_role`. Also, all these three attributes were corrected (e.g. handling spaces/hyphens in names).

Connected issues: [#2836](https://github.com/Snowflake-Labs/terraform-provider-snowflake/pull/2836), [#2942](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2942)

### *(bugfix)* Correctly handle failed update
#### *(bugfix)* Correctly handle failed update

Not every attribute can be updated in the state during read (like `password` in the `snowflake_user` resource). In situations where update fails, we may end up with an incorrect state (read more in https://github.com/hashicorp/terraform-plugin-sdk/issues/476). We use a deprecated method from the plugin SDK, and now, for partially failed updates, we preserve the resource's previous state. It fixed this kind of situations for `snowflake_user` resource.

Connected issues: [#2970](https://github.com/Snowflake-Labs/terraform-provider-snowflake/pull/2970)

#### *(breaking change)* Attributes changes

Attributes that are no longer computed:
- `login_name`
- `display_name`
- `disabled`
- `default_role`

New fields:
- `middle_name`
- `days_to_expiry`
- `mins_to_unlock`
- `mins_to_bypass_mfa`
- `disable_mfa`

Removed fields:
- `has_rsa_public_key`

Default changes:
- `must_change_password`
- `disabled`

Type changes:
- `must_change_password`: bool -> string
- `disabled`: bool -> string

Validation changes:
- `default_secondary_roles` - only 1-element lists with `"ALL"` element are now supported. Check [Snowflake docs](https://docs.snowflake.com/en/sql-reference/sql/create-user#optional-object-properties-objectproperties) for more details.

## v0.94.0 ➞ v0.94.1
### changes in snowflake_schema

Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/database_roles.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Read-Only:

- `comment` (String)
- `created_on` (String)
- `database_name` (String)
- `granted_database_roles` (Number)
- `granted_to_database_roles` (Number)
- `granted_to_roles` (Number)
Expand Down
1 change: 1 addition & 0 deletions docs/resources/database_role.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Read-Only:

- `comment` (String)
- `created_on` (String)
- `database_name` (String)
- `granted_database_roles` (Number)
- `granted_to_database_roles` (Number)
- `granted_to_roles` (Number)
Expand Down
35 changes: 21 additions & 14 deletions docs/resources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
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.
---

!> **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.

# 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).

## Example Usage

Expand Down Expand Up @@ -43,7 +43,7 @@ resource "snowflake_user" "user" {

### Required

- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. [doc](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters)
- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. Check the [docs](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters). Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"`

### Optional

Expand All @@ -59,15 +59,17 @@ resource "snowflake_user" "user" {
- `client_session_keep_alive` (Boolean) Parameter that indicates whether to force a user to log in again after a period of inactivity in the session. For more information, check [CLIENT_SESSION_KEEP_ALIVE docs](https://docs.snowflake.com/en/sql-reference/parameters#client-session-keep-alive).
- `client_session_keep_alive_heartbeat_frequency` (Number) Number of seconds in-between client attempts to update the token for the session. For more information, check [CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY docs](https://docs.snowflake.com/en/sql-reference/parameters#client-session-keep-alive-heartbeat-frequency).
- `client_timestamp_type_mapping` (String) Specifies the [TIMESTAMP_* variation](https://docs.snowflake.com/en/sql-reference/data-types-datetime.html#label-datatypes-timestamp-variations) to use when binding timestamp variables for JDBC or ODBC applications that use the bind API to load data. For more information, check [CLIENT_TIMESTAMP_TYPE_MAPPING docs](https://docs.snowflake.com/en/sql-reference/parameters#client-timestamp-type-mapping).
- `comment` (String)
- `comment` (String) Specifies a comment for the user.
- `date_input_format` (String) Specifies the input format for the DATE data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [DATE_INPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#date-input-format).
- `date_output_format` (String) Specifies the display format for the DATE data type. For more information, see [Date and time input and output formats](https://docs.snowflake.com/en/sql-reference/date-time-input-output). For more information, check [DATE_OUTPUT_FORMAT docs](https://docs.snowflake.com/en/sql-reference/parameters#date-output-format).
- `default_namespace` (String) Specifies the namespace (database only or database and schema) that is active by default for the user’s session upon login.
- `default_role` (String) Specifies the role that is active by default for the user’s session upon login.
- `default_secondary_roles` (Set of String) Specifies the set of secondary roles that are active for the user’s session upon login. Currently only ["ALL"] value is supported - more information can be found in [doc](https://docs.snowflake.com/en/sql-reference/sql/create-user#optional-object-properties-objectproperties)
- `default_warehouse` (String) Specifies the virtual warehouse that is active by default for the user’s session upon login.
- `disabled` (Boolean)
- `display_name` (String, Sensitive) Name displayed for the user in the Snowflake web interface.
- `days_to_expiry` (Number) Specifies the number of days after which the user status is set to `Expired` and the user is no longer allowed to log in. This is useful for defining temporary users (i.e. users who should only have access to Snowflake for a limited time period). In general, you should not set this property for [account administrators](https://docs.snowflake.com/en/user-guide/security-access-control-considerations.html#label-accountadmin-users) (i.e. users with the `ACCOUNTADMIN` role) because Snowflake locks them out when they become `Expired`.
- `default_namespace` (String) Specifies the namespace (database only or database and schema) that is active by default for the user’s session upon login. Note that the CREATE USER operation does not verify that the namespace exists.
- `default_role` (String) Specifies the role that is active by default for the user’s session upon login. Note that specifying a default role for a user does **not** grant the role to the user. The role must be granted explicitly to the user using the [GRANT ROLE](https://docs.snowflake.com/en/sql-reference/sql/grant-role) command. In addition, the CREATE USER operation does not verify that the role exists.
- `default_secondary_roles` (Set of String) Specifies the set of secondary roles that are active for the user’s session upon login. Currently only ["ALL"] value is supported - more information can be found in [doc](https://docs.snowflake.com/en/sql-reference/sql/create-user#optional-object-properties-objectproperties).
- `default_warehouse` (String) Specifies the virtual warehouse that is active by default for the user’s session upon login. Note that the CREATE USER operation does not verify that the warehouse exists.
- `disable_mfa` (String) Allows enabling or disabling [multi-factor authentication](https://docs.snowflake.com/en/user-guide/security-mfa). Available options are: "true" or "false". When the value is not set in the configuration the provider will put "default" there which means to use the Snowflake default for this value.
- `disabled` (String) Specifies whether the user is disabled, which prevents logging in and aborts all the currently-running queries for the user. Available options are: "true" or "false". When the value is not set in the configuration the provider will put "default" there which means to use the Snowflake default for this value.
- `display_name` (String) Name displayed for the user in the Snowflake web interface.
- `email` (String, Sensitive) Email address for the user.
- `enable_unload_physical_type_optimization` (Boolean) Specifies whether to set the schema for unloaded Parquet files based on the logical column data types (i.e. the types in the unload SQL query or source table) or on the unloaded column values (i.e. the smallest data types and precision that support the values in the output columns of the unload SQL statement or source table). For more information, check [ENABLE_UNLOAD_PHYSICAL_TYPE_OPTIMIZATION docs](https://docs.snowflake.com/en/sql-reference/parameters#enable-unload-physical-type-optimization).
- `enable_unredacted_query_syntax_error` (Boolean) Controls whether query text is redacted if a SQL query fails due to a syntax or parsing error. If `FALSE`, the content of a failed query is redacted in the views, pages, and functions that provide a query history. Only users with a role that is granted or inherits the AUDIT privilege can set the ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR parameter. When using the ALTER USER command to set the parameter to `TRUE` for a particular user, modify the user that you want to see the query text, not the user who executed the query (if those are different users). For more information, check [ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR docs](https://docs.snowflake.com/en/sql-reference/parameters#enable-unredacted-query-syntax-error).
Expand All @@ -83,13 +85,16 @@ resource "snowflake_user" "user" {
- `last_name` (String, Sensitive) Last name of the user.
- `lock_timeout` (Number) Number of seconds to wait while trying to lock a resource, before timing out and aborting the statement. For more information, check [LOCK_TIMEOUT docs](https://docs.snowflake.com/en/sql-reference/parameters#lock-timeout).
- `log_level` (String) Specifies the severity level of messages that should be ingested and made available in the active event table. Messages at the specified level (and at more severe levels) are ingested. For more information about log levels, see [Setting log level](https://docs.snowflake.com/en/developer-guide/logging-tracing/logging-log-level). For more information, check [LOG_LEVEL docs](https://docs.snowflake.com/en/sql-reference/parameters#log-level).
- `login_name` (String, Sensitive) The name users use to log in. If not supplied, snowflake will use name instead.
- `login_name` (String, Sensitive) The name users use to log in. If not supplied, snowflake will use name instead. Login names are always case-insensitive.
- `middle_name` (String, Sensitive) Middle name of the user.
- `mins_to_bypass_mfa` (Number) Specifies the number of minutes to temporarily bypass MFA for the user. This property can be used to allow a MFA-enrolled user to temporarily bypass MFA during login in the event that their MFA device is not available.
- `mins_to_unlock` (Number) Specifies the number of minutes until the temporary lock on the user login is cleared. To protect against unauthorized user login, Snowflake places a temporary lock on a user after five consecutive unsuccessful login attempts. When creating a user, this property can be set to prevent them from logging in until the specified amount of time passes. To remove a lock immediately for a user, specify a value of 0 for this parameter.
- `multi_statement_count` (Number) Number of statements to execute when using the multi-statement capability. For more information, check [MULTI_STATEMENT_COUNT docs](https://docs.snowflake.com/en/sql-reference/parameters#multi-statement-count).
- `must_change_password` (Boolean) Specifies whether the user is forced to change their password on next login (including their first/initial login) into the system.
- `must_change_password` (String) Specifies whether the user is forced to change their password on next login (including their first/initial login) into the system. Available options are: "true" or "false". When the value is not set in the configuration the provider will put "default" there which means to use the Snowflake default for this value.
- `network_policy` (String) Specifies the network policy to enforce for your account. Network policies enable restricting access to your account based on users’ IP address. For more details, see [Controlling network traffic with network policies](https://docs.snowflake.com/en/user-guide/network-policies). Any existing network policy (created using [CREATE NETWORK POLICY](https://docs.snowflake.com/en/sql-reference/sql/create-network-policy)). For more information, check [NETWORK_POLICY docs](https://docs.snowflake.com/en/sql-reference/parameters#network-policy).
- `noorder_sequence_as_default` (Boolean) Specifies whether the ORDER or NOORDER property is set by default when you create a new sequence or add a new table column. The ORDER and NOORDER properties determine whether or not the values are generated for the sequence or auto-incremented column in [increasing or decreasing order](https://docs.snowflake.com/en/user-guide/querying-sequences.html#label-querying-sequences-increasing-values). For more information, check [NOORDER_SEQUENCE_AS_DEFAULT docs](https://docs.snowflake.com/en/sql-reference/parameters#noorder-sequence-as-default).
- `odbc_treat_decimal_as_int` (Boolean) Specifies how ODBC processes columns that have a scale of zero (0). For more information, check [ODBC_TREAT_DECIMAL_AS_INT docs](https://docs.snowflake.com/en/sql-reference/parameters#odbc-treat-decimal-as-int).
- `password` (String, Sensitive) **WARNING:** this will put the password in the terraform state file. Use carefully.
- `password` (String, Sensitive) Password for the user. **WARNING:** this will put the password in the terraform state file. Use carefully.
- `prevent_unload_to_internal_stages` (Boolean) Specifies whether to prevent data unload operations to internal (Snowflake) stages using [COPY INTO <location>](https://docs.snowflake.com/en/sql-reference/sql/copy-into-location) statements. For more information, check [PREVENT_UNLOAD_TO_INTERNAL_STAGES docs](https://docs.snowflake.com/en/sql-reference/parameters#prevent-unload-to-internal-stages).
- `query_tag` (String) Optional string that can be used to tag queries and other SQL statements executed within a session. The tags are displayed in the output of the [QUERY_HISTORY, QUERY_HISTORY_BY_*](https://docs.snowflake.com/en/sql-reference/functions/query_history) functions. For more information, check [QUERY_TAG docs](https://docs.snowflake.com/en/sql-reference/parameters#query-tag).
- `quoted_identifiers_ignore_case` (Boolean) Specifies whether letters in double-quoted object identifiers are stored and resolved as uppercase letters. By default, Snowflake preserves the case of alphabetic characters when storing and resolving double-quoted identifiers (see [Identifier resolution](https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html#label-identifier-casing)). You can use this parameter in situations in which [third-party applications always use double quotes around identifiers](https://docs.snowflake.com/en/sql-reference/identifiers-syntax.html#label-identifier-casing-parameter). For more information, check [QUOTED_IDENTIFIERS_IGNORE_CASE docs](https://docs.snowflake.com/en/sql-reference/parameters#quoted-identifiers-ignore-case).
Expand Down Expand Up @@ -124,10 +129,10 @@ resource "snowflake_user" "user" {
### Read-Only

- `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).
- `has_rsa_public_key` (Boolean) Will be true if user as an RSA key set.
- `id` (String) The ID of this resource.
- `parameters` (List of Object) Outputs the result of `SHOW PARAMETERS IN USER` for the given user. (see [below for nested schema](#nestedatt--parameters))
- `show_output` (List of Object) Outputs the result of `SHOW USER` for the given user. (see [below for nested schema](#nestedatt--show_output))
- `user_type` (String) Specifies a type for the user.

<a id="nestedatt--parameters"></a>
### Nested Schema for `parameters`
Expand Down Expand Up @@ -909,6 +914,7 @@ Read-Only:
- `ext_authn_duo` (Boolean)
- `ext_authn_uid` (String)
- `first_name` (String)
- `has_mfa` (Boolean)
- `has_password` (Boolean)
- `has_rsa_public_key` (Boolean)
- `last_name` (String)
Expand All @@ -921,6 +927,7 @@ Read-Only:
- `name` (String)
- `owner` (String)
- `snowflake_lock` (Boolean)
- `type` (String)

## Import

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,18 @@ func (w *UserAssert) HasDaysToExpiryNotEmpty() *UserAssert {
w.AddAssertion(func(t *testing.T, o *sdk.User) error {
t.Helper()
if o.DaysToExpiry == "" {
return fmt.Errorf("expected days to expiry not empty; got: %v", o.DaysToExpiry)
return fmt.Errorf("expected days to expiry not empty; got empty")
}
return nil
})
return w
}

func (w *UserAssert) HasDaysToExpiryEmpty() *UserAssert {
w.AddAssertion(func(t *testing.T, o *sdk.User) error {
t.Helper()
if o.DaysToExpiry != "" {
return fmt.Errorf("expected days to expiry empty; got: %v", o.DaysToExpiry)
}
return nil
})
Expand Down
Loading
Loading