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: grant ownership follow-up #2658

Merged
merged 5 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
282 changes: 282 additions & 0 deletions docs/resources/grant_ownership.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,238 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "snowflake_grant_ownership Resource - terraform-provider-snowflake"
subcategory: ""
description: |-

---


!> **Warning** We're in a process of implementing this resource, so it's not available yet.

~> **Note** This is a preview resource. It's ready for general use. In case of any errors, please file an issue in our GitHub repository.
~> **Note** For more details about granting ownership, please visit [`GRANT OWNERSHIP` Snowflake documentation page](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership).




# snowflake_grant_ownership (Resource)



## Example Usage

```terraform
##################################
### on object to account role
##################################

resource "snowflake_role" "test" {
name = "test_role"
}

resource "snowflake_database" "test" {
name = "test_database"
}

resource "snowflake_schema" "test" {
name = "test_schema"
database = snowflake_database.test.name
}

resource "snowflake_grant_ownership" "test" {
account_role_name = snowflake_role.test.name
outbound_privileges = "COPY"
on {
object_type = "SCHEMA"
object_name = "\"${snowflake_database.test.name}\".\"${snowflake_schema.test.name}\""
}
}

##################################
### on object to database role
##################################

resource "snowflake_database" "test" {
name = "test_database"
}

resource "snowflake_schema" "test" {
name = "test_schema"
database = snowflake_database.test.name
}

resource "snowflake_database_role" "test" {
name = "test_database_role"
database = snowflake_database.test.name
}

resource "snowflake_grant_ownership" "test" {
database_role_name = "\"${snowflake_database_role.test.database}\".\"${snowflake_database_role.test.name}\""
outbound_privileges = "REVOKE"
on {
object_type = "SCHEMA"
object_name = "\"${snowflake_database.test.name}\".\"${snowflake_schema.test.name}\""
}
}

##################################
### on all tables in database to account role
##################################

resource "snowflake_role" "test" {
name = "test_role"
}

resource "snowflake_database" "test" {
name = "test_database"
}

resource "snowflake_grant_ownership" "test" {
account_role_name = snowflake_role.test.name
on {
all {
plural_object_type = "TABLES"
in_database = snowflake_database.test.name
}
}
}

##################################
### on all tables in schema to account role
##################################

resource "snowflake_role" "test" {
name = "test_role"
}

resource "snowflake_database" "test" {
name = "test_database"
}

resource "snowflake_schema" "test" {
name = "test_schema"
database = snowflake_database.test.name
}

resource "snowflake_grant_ownership" "test" {
account_role_name = snowflake_role.test.name
on {
all {
plural_object_type = "TABLES"
in_schema = "\"${snowflake_database.test.name}\".\"${snowflake_schema.test.name}\""
}
}
}

##################################
### on future tables in database to account role
##################################

resource "snowflake_role" "test" {
name = "test_role"
}

resource "snowflake_database" "test" {
name = "test_database"
}

resource "snowflake_grant_ownership" "test" {
account_role_name = snowflake_role.test.name
on {
future {
plural_object_type = "TABLES"
in_database = snowflake_database.test.name
}
}
}

##################################
### on future tables in schema to account role
##################################

resource "snowflake_role" "test" {
name = "test_role"
}

resource "snowflake_database" "test" {
name = "test_database"
}

resource "snowflake_schema" "test" {
name = "test_schema"
database = snowflake_database.test.name
}

resource "snowflake_grant_ownership" "test" {
account_role_name = snowflake_role.test.name
on {
future {
plural_object_type = "TABLES"
in_schema = "\"${snowflake_database.test.name}\".\"${snowflake_schema.test.name}\""
}
}
}

##################################
### RoleBasedAccessControl (RBAC example)
##################################

resource "snowflake_role" "test" {
name = "role"
}

resource "snowflake_database" "test" {
name = "database"
}

resource "snowflake_grant_ownership" "test" {
account_role_name = snowflake_role.test.name
on {
object_type = "DATABASE"
object_name = snowflake_database.test.name
}
}

resource "snowflake_grant_account_role" "test" {
role_name = snowflake_role.test.name
user_name = "username"
}

provider "snowflake" {
profile = "default"
alias = "secondary"
role = snowflake_role.test.name
}

## With ownership on the database, the secondary provider is able to create schema on it without any additional privileges.
resource "snowflake_schema" "test" {
depends_on = [snowflake_grant_ownership.test, snowflake_grant_account_role.test]
provider = snowflake.secondary
database = snowflake_database.test.name
name = "schema"
}
```

## Granting ownership on pipes
To transfer ownership of a pipe, there must be additional conditions met. Otherwise, additional manual work
will be needed afterward or in some cases, the ownership won't be transferred (resulting in error).

To transfer ownership of a pipe(s) **fully automatically**, one of the following conditions has to be met:
- OPERATE and MONITOR privileges are granted to the current role on the pipe(s) and `outbound_privileges` field is set to `COPY`.
- The pipe(s) running status is paused (additional privileges and fields set are needed to pause and resume the pipe before and after ownership transfer. If it's already paused, nothing additional is needed and the pipe will remain paused after the ownership transfer).

To transfer ownership of a pipe(s) **semi-automatically** you have to:
1. Pause the pipe(s) you want to transfer ownership of (using [ALTER PIPE](https://docs.snowflake.com/en/sql-reference/sql/alter-pipe#syntax); see PIPE_EXECUTION_PAUSED).
2. Create Terraform configuration with the `snowflake_grant_ownership` resource and perform ownership transfer with the `terraform apply`.
3. To resume the pipe(s) after ownership transfer use [PIPE_FORCE_RESUME system function](https://docs.snowflake.com/en/sql-reference/functions/system_pipe_force_resume).



sfc-gh-asawicki marked this conversation as resolved.
Show resolved Hide resolved

## Granting ownership on external tables
Transferring ownership on an external table or its parent database blocks automatic refreshes of the table metadata by setting the `AUTO_REFRESH` property to `FALSE`.
Right now, there's no way to check the `AUTO_REFRESH` state of the external table and because of that, a manual step is required after ownership transfer.
To set the `AUTO_REFRESH` property back to `TRUE` (after you transfer ownership), use the [ALTER EXTERNAL TABLE](https://docs.snowflake.com/en/sql-reference/sql/alter-external-table) command.

<!-- schema generated by tfplugindocs -->
## Schema
Expand Down Expand Up @@ -62,3 +285,62 @@ Optional:

- `in_database` (String) The fully qualified name of the database.
- `in_schema` (String) The fully qualified name of the schema.

## Import

~> **Note** All the ..._name parts should be fully qualified names (where every part is quoted), e.g. for schema object it is `"<database_name>"."<schema_name>"."<object_name>"`

Import is supported using the following syntax:

`terraform import "<role_type>|<role_identifier>|<outbound_privileges_behavior>|<grant_type>|<grant_data>"`

where:
- role_type - string - type of granted role (either ToAccountRole or ToDatabaseRole)
- role_name - string - fully qualified identifier for either account role or database role (depending on the role_type)
- outbound_privileges_behavior - string - behavior specified for existing roles (can be either COPY or REVOKE)
- grant_type - enum
- grant_data - data dependent on grant_type

It has varying number of parts, depending on grant_type. All the possible types are:

### OnObject
`terraform import "<role_type>|<role_identifier>|<outbound_privileges_behavior>|OnObject|<object_type>|<object_name>"`

### OnAll (contains inner types: InDatabase | InSchema)

#### InDatabase
`terraform import "<role_type>|<role_identifier>|<outbound_privileges_behavior>|OnAll|<plural_object_type>|InDatabase|<database_name>"`

#### InSchema
`terraform import "<role_type>|<role_identifier>|<outbound_privileges_behavior>|OnAll|<plural_object_type>|InSchema|<schema_name>"`

### OnFuture (contains inner types: InDatabase | InSchema)

#### InDatabase
`terraform import "<role_type>|<role_identifier>|<outbound_privileges_behavior>|OnFuture|<plural_object_type>|InDatabase|<database_name>"`

#### InSchema
`terraform import "<role_type>|<role_identifier>|<outbound_privileges_behavior>|OnFuture|<plural_object_type>|InSchema|<schema_name>"`

### Import examples

#### OnObject on Schema ToAccountRole
`terraform import "ToAccountRole|\"account_role\"|COPY|OnObject|SCHEMA|\"database_name\".\"schema_name\""`

#### OnObject on Schema ToDatabaseRole
`terraform import "ToDatabaseRole|\"database_name\".\"database_role_name\"|COPY|OnObject|SCHEMA|\"database_name\".\"schema_name\""`

#### OnObject on Table
`terraform import "ToAccountRole|\"account_role\"|COPY|OnObject|TABLE|\"database_name\".\"schema_name\".\"table_name\""`

#### OnAll InDatabase
`terraform import "ToAccountRole|\"account_role\"|REVOKE|OnAll|TABLES|InDatabase|\"database_name\""`

#### OnAll InSchema
`terraform import "ToAccountRole|\"account_role\"||OnAll|TABLES|InSchema|\"database_name\".\"schema_name\""`

#### OnFuture InDatabase
`terraform import "ToAccountRole|\"account_role\"||OnFuture|TABLES|InDatabase|\"database_name\""`

#### OnFuture InSchema
`terraform import "ToAccountRole|\"account_role\"|COPY|OnFuture|TABLES|InSchema|\"database_name\".\"schema_name\""`
Loading
Loading