Skip to content

feat: Implement rotating pats #3843

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

Merged
merged 41 commits into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
933886c
Add managing PATs to SDK
sfc-gh-jmichalak Jun 27, 2025
315e697
Merge remote-tracking branch 'origin/dev' into 06-27-add_managing_pat…
sfc-gh-jmichalak Jun 30, 2025
0fe0778
Review suggestions
sfc-gh-jmichalak Jul 1, 2025
1600962
Deref functions
sfc-gh-jmichalak Jul 1, 2025
eacd4d0
Merge remote-tracking branch 'origin/dev' into 06-27-add_managing_pat…
sfc-gh-jmichalak Jul 2, 2025
74aae0f
Add PAT integration tests
sfc-gh-jmichalak Jul 2, 2025
420b229
Impl
sfc-gh-jmichalak Jul 3, 2025
4469c34
Add managing PATs to SDK
sfc-gh-jmichalak Jun 27, 2025
7515251
Review suggestions
sfc-gh-jmichalak Jul 1, 2025
a3c7354
Deref functions
sfc-gh-jmichalak Jul 1, 2025
f9ec8eb
Add PAT integration tests
sfc-gh-jmichalak Jul 2, 2025
98641e3
Merge remote-tracking branch 'origin/add-pat-integration-tests' into …
sfc-gh-jmichalak Jul 3, 2025
a8b45bd
Implement User Programmatic Access Tokens data source
sfc-gh-jmichalak Jul 3, 2025
964de07
Implement rotating PATs
sfc-gh-jmichalak Jul 7, 2025
c416df3
Merge remote-tracking branch 'origin/dev' into add-pat-resource
sfc-gh-jmichalak Jul 14, 2025
e21eeda
Cleanup
sfc-gh-jmichalak Jul 14, 2025
8b88f60
Merge remote-tracking branch 'origin/add-pat-resource' into add-pat-ds
sfc-gh-jmichalak Jul 14, 2025
1eebc5a
Merge remote-tracking branch 'origin/dev' into add-pat-resource
sfc-gh-jmichalak Jul 15, 2025
84bb8b9
Review suggestions
sfc-gh-jmichalak Jul 15, 2025
aa7301a
Merge remote-tracking branch 'origin/add-pat-resource' into add-pat-ds
sfc-gh-jmichalak Jul 15, 2025
72cb45d
Review suggestions
sfc-gh-jmichalak Jul 15, 2025
7c5a266
Update poc schema
sfc-gh-jmichalak Jul 15, 2025
d4e5cee
Merge remote-tracking branch 'origin/dev' into add-pat-resource
sfc-gh-jmichalak Jul 16, 2025
a015a80
Merge remote-tracking branch 'origin/add-pat-resource' into add-pat-ds
sfc-gh-jmichalak Jul 16, 2025
c189c52
Merge remote-tracking branch 'origin/add-pat-ds' into implement-rotat…
sfc-gh-jmichalak Jul 16, 2025
5fc8194
Update docs
sfc-gh-jmichalak Jul 16, 2025
7c57253
Cleanup
sfc-gh-jmichalak Jul 16, 2025
7889ea9
Merge remote-tracking branch 'origin/dev' into add-pat-ds
sfc-gh-jmichalak Jul 17, 2025
5415e10
Adjust tests
sfc-gh-jmichalak Jul 17, 2025
9ea1611
Update poc schema
sfc-gh-jmichalak Jul 17, 2025
9d94ace
Merge remote-tracking branch 'origin/add-pat-ds' into implement-rotat…
sfc-gh-jmichalak Jul 17, 2025
7b016e9
Add labels
sfc-gh-jmichalak Jul 17, 2025
86d0285
Cleanup
sfc-gh-jmichalak Jul 17, 2025
26fb62f
Merge remote-tracking branch 'origin/dev' into add-pat-ds
sfc-gh-jmichalak Jul 17, 2025
31a14f5
Review suggestions
sfc-gh-jmichalak Jul 17, 2025
f99e307
Merge remote-tracking branch 'origin/add-pat-ds' into implement-rotat…
sfc-gh-jmichalak Jul 17, 2025
8a6e3fd
Review suggestions
sfc-gh-jmichalak Jul 17, 2025
feb3998
Review suggestions
sfc-gh-jmichalak Jul 22, 2025
e772b93
Merge remote-tracking branch 'origin/dev' into implement-rotating-pats
sfc-gh-jmichalak Jul 22, 2025
a34a12a
Fix an assert
sfc-gh-jmichalak Jul 22, 2025
a13e3c8
Cleanups
sfc-gh-jmichalak Jul 22, 2025
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
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/01-bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ body:
- resource:user
- resource:user_authentication_policy_attachment
- resource:user_password_policy_attachment
- resource:user_programmatic_access_token
- resource:user_public_keys
- resource:view
- resource:warehouse
Expand Down Expand Up @@ -275,6 +276,7 @@ body:
- data_source:tables
- data_source:tags
- data_source:tasks
- data_source:user_programmatic_access_tokens
- data_source:users
- data_source:views
- data_source:warehouses
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/02-general-usage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ body:
- resource:user
- resource:user_authentication_policy_attachment
- resource:user_password_policy_attachment
- resource:user_programmatic_access_token
- resource:user_public_keys
- resource:view
- resource:warehouse
Expand Down Expand Up @@ -273,6 +274,7 @@ body:
- data_source:tables
- data_source:tags
- data_source:tasks
- data_source:user_programmatic_access_tokens
- data_source:users
- data_source:views
- data_source:warehouses
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/03-documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ body:
- resource:user
- resource:user_authentication_policy_attachment
- resource:user_password_policy_attachment
- resource:user_programmatic_access_token
- resource:user_public_keys
- resource:view
- resource:warehouse
Expand Down Expand Up @@ -183,6 +184,7 @@ body:
- data_source:tables
- data_source:tags
- data_source:tasks
- data_source:user_programmatic_access_tokens
- data_source:users
- data_source:views
- data_source:warehouses
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/04-feature-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ body:
- resource:user
- resource:user_authentication_policy_attachment
- resource:user_password_policy_attachment
- resource:user_programmatic_access_token
- resource:user_public_keys
- resource:view
- resource:warehouse
Expand Down Expand Up @@ -232,6 +233,7 @@ body:
- data_source:tables
- data_source:tags
- data_source:tasks
- data_source:user_programmatic_access_tokens
- data_source:users
- data_source:views
- data_source:warehouses
Expand Down
13 changes: 12 additions & 1 deletion MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,20 @@ for changes required after enabling given [Snowflake BCR Bundle](https://docs.sn

## v2.3.0 ➞ v2.4.0

### *(new feature)* snowflake_user_programmatic_access_token resource
### *(new feature)* Handling Programmatic Access Tokens
As we announced in our [roadmap](https://github.com/snowflakedb/terraform-provider-snowflake/blob/main/ROADMAP.md#pat-support), we implemented handling Programmatic Access Tokens (PATs) in the provider. In [v2.3.0](#v220--v230), we already added `PROGRAMMATIC_ACCESS_TOKEN` authenticator option.
In this version, we enhanced the provider capabilities with handling PATs in a new resource and data source. See more in our [Authentication Methods guide](https://registry.terraform.io/providers/snowflakedb/snowflake/2.4.0/docs/guides/authentication_methods#pat-personal-access-token).

#### New `snowflake_user_programmatic_access_tokens` data source
Added a new preview data source for user programmatic access tokens. See reference [docs](https://docs.snowflake.com/en/sql-reference/sql/show-user-programmatic-access-tokens).

This feature will be marked as a stable feature in future releases. Breaking changes are expected, even without bumping the major version. To use this feature, add `snowflake_user_programmatic_access_tokens_datasource` to `preview_features_enabled` field in the provider configuration.

#### New `snowflake_user_programmatic_access_token` resource
Added a new preview resource for managing users' programmatic access tokens. See reference [docs](https://docs.snowflake.com/en/sql-reference/sql/alter-user-add-programmatic-access-token) and a [user guide](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens) for more details.

This resource also supports token rotation. See our [Authentication Methods guide](https://registry.terraform.io/providers/snowflakedb/snowflake/latest/docs/guides/authentication_methods#managing-pats) and the [resource documentation](https://registry.terraform.io/providers/snowflakedb/snowflake/2.4.0/docs/resources/user_programmatic_access_token).

This feature will be marked as a stable feature in future releases. Breaking changes are expected, even without bumping the major version. To use this feature, add `snowflake_user_programmatic_access_token` to `preview_features_enabled` field in the provider configuration.

## v2.2.0 ➞ v2.3.0
Expand Down
85 changes: 85 additions & 0 deletions docs/data-sources/user_programmatic_access_tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
page_title: "snowflake_user_programmatic_access_tokens Data Source - terraform-provider-snowflake"
subcategory: "Preview"
description: |-
Data source used to get details of filtered user programmatic access tokens. Filtering is aligned with the current possibilities for SHOW USER PROGRAMMATIC ACCESS TOKENS https://docs.snowflake.com/en/sql-reference/sql/show-user-programmatic-access-tokens query. The results of SHOW are encapsulated in one output collection user_programmatic_access_tokens.
---

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

# snowflake_user_programmatic_access_tokens (Data Source)

Data source used to get details of filtered user programmatic access tokens. Filtering is aligned with the current possibilities for [SHOW USER PROGRAMMATIC ACCESS TOKENS](https://docs.snowflake.com/en/sql-reference/sql/show-user-programmatic-access-tokens) query. The results of SHOW are encapsulated in one output collection `user_programmatic_access_tokens`.

## Example Usage

```terraform
# Simple usage
data "snowflake_user_programmatic_access_tokens" "simple" {
for_user = "<user_name>"
}

output "simple_output" {
value = data.snowflake_user_programmatic_access_tokens.simple.user_programmatic_access_tokens
}

# Ensure the number of user programmatic access tokens is equal to at least one element (with the use of postcondition)
data "snowflake_user_programmatic_access_tokens" "assert_with_postcondition" {
for_user = "<user_name>"
lifecycle {
postcondition {
condition = length(self.user_programmatic_access_tokens) > 0
error_message = "there should be at least one user programmatic access token"
}
}
}

# Ensure the number of user programmatic access tokens is equal to exactly one element (with the use of check block)
check "user_programmatic_access_token_check" {
data "snowflake_user_programmatic_access_tokens" "assert_with_check_block" {
for_user = "<user_name>"
}

assert {
condition = length(data.snowflake_user_programmatic_access_tokens.assert_with_check_block.user_programmatic_access_tokens) == 1
error_message = "user programmatic access tokens filtered by '${data.snowflake_user_programmatic_access_tokens.assert_with_check_block.for_user}' returned ${length(data.snowflake_user_programmatic_access_tokens.assert_with_check_block.user_programmatic_access_tokens)} user programmatic access tokens where one was expected"
}
}
```

-> **Note** If a field has a default value, it is shown next to the type in the schema.

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `for_user` (String) Returns programmatic access tokens for the specified user.

### Read-Only

- `id` (String) The ID of this resource.
- `user_programmatic_access_tokens` (List of Object) Holds the aggregated output of all user programmatic access tokens details queries. (see [below for nested schema](#nestedatt--user_programmatic_access_tokens))

<a id="nestedatt--user_programmatic_access_tokens"></a>
### Nested Schema for `user_programmatic_access_tokens`

Read-Only:

- `show_output` (List of Object) (see [below for nested schema](#nestedobjatt--user_programmatic_access_tokens--show_output))

<a id="nestedobjatt--user_programmatic_access_tokens--show_output"></a>
### Nested Schema for `user_programmatic_access_tokens.show_output`

Read-Only:

- `comment` (String)
- `created_by` (String)
- `created_on` (String)
- `expires_at` (String)
- `mins_to_bypass_network_policy_requirement` (Number)
- `name` (String)
- `role_restriction` (String)
- `rotated_to` (String)
- `status` (String)
- `user_name` (String)
73 changes: 71 additions & 2 deletions docs/guides/authentication_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,77 @@ You must fulfill the following prerequisites to generate and use programmatic ac
- [Network policy requirements](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens#label-pat-prerequisites-network)
- [Authentication policy requirements](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens#label-pat-prerequisites-authentication)

To generate PAT, you use a special [ALTER USER](https://docs.snowflake.com/en/sql-reference/sql/alter-user-add-programmatic-access-token) command.
It will generate a new token and return it in the output console. To use it in the provider, you have the following options:
#### Managing PATs

Managing the whole PAT lifecycle is implemented in the provider with the [snowflake_programmatic_access_token](../resources/user_programmatic_access_token) resource.
For example, to create a new PAT, you can use the following code:
```terraform
resource "snowflake_user_programmatic_access_token" "example" {
user = snowflake_user.user.name
name = "TOKEN"
}
```

You can also rotate the PAT by using the `keepers` attribute and connecting it to a resource providing changing a value, like [time_rotating](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/rotating) resource from the `time` provider.
```terraform
# note this requires the terraform to be run regularly
resource "time_rotating" "my_token_rotation" {
rotation_days = 30
}

resource "snowflake_user_programmatic_access_token" "example" {
user = snowflake_user.user.name
name = "TOKEN"

# Use the keepers map to force token rotation. If any key or value in the map changes, the token will be rotated.
keepers = {
# here we use the time_rotating's rotation_rfc3339 field which provides a new timestamp every 30 days.
rotation_time = time_rotating.my_token_rotation.rotation_rfc3339
}
}
```
In this example, after 30 days pass, you will see terraform plan output similar to:
```
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
~ update in-place

Terraform will perform the following actions:

# snowflake_user_programmatic_access_token.complete_with_external_references will be updated in-place
~ resource "snowflake_user_programmatic_access_token" "example" {
id = "\"PAT\"|\"TOKEN\""
~ keepers = {
- "rotation_time" = "2025-07-17T12:20:51Z"
} -> (known after apply)
name = "TOKEN"
# (10 unchanged attributes hidden)
}

# time_rotating.my_token_rotation will be created
+ resource "time_rotating" "my_token_rotation" {
+ day = 30
+ hour = (known after apply)
+ id = (known after apply)
+ minute = (known after apply)
+ month = (known after apply)
+ rfc3339 = (known after apply)
+ rotation_minutes = (known after apply)
+ rotation_rfc3339 = (known after apply)
+ second = (known after apply)
+ unix = (known after apply)
+ year = (known after apply)
}

Plan: 1 to add, 1 to change, 0 to destroy.
```

If you do not want to manage PATs in Terraform, you can simply use a special [ALTER USER](https://docs.snowflake.com/en/sql-reference/sql/alter-user-add-programmatic-access-token) command.
It will generate a new token and return it in the output console.

#### Authenticating with PATs

To use PATs in the provider, you have the following options:
- Follow the [user + password](#snowflake-authenticator-flow-login--password) authentication workflow,
but instead of password, use the generated token.
- Use the `PROGRAMMATIC_ACCESS_TOKEN` authenticator and pass the generated token in the `token` field, like:
Expand Down
Loading