-
Notifications
You must be signed in to change notification settings - Fork 428
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add grant ownership examples to the guides
- Loading branch information
1 parent
1642c15
commit 4c89d0a
Showing
4 changed files
with
522 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,259 @@ | ||
--- | ||
page_title: "Grant ownership - common use cases" | ||
subcategory: "" | ||
description: |- | ||
--- | ||
# Grant ownership - common use cases | ||
|
||
That is a follow-up for the [grant_ownership resource overview](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/grant_ownership_resource_overview.md) document. | ||
Those examples should help you to work with difficulties imposed by Snowflake role management and Terraform. | ||
Here's a list of grant ownership common use cases: | ||
|
||
- [Basic RBAC example](#basic-rbac-example) | ||
- [Granting ownership with a less privileged role (granting MANAGED ACCESS)](#granting-ownership-with-a-less-privileged-role-granting-managed-access) | ||
- [Modifying objects you don't own after transferring the ownership](#modifying-objects-you-dont-own-after-transferring-the-ownership) | ||
|
||
#### Basic RBAC example | ||
Here's an easy example of using RBAC. Of course, there are many ways to perform RBAC, and here, we are not proposing any | ||
option over the other. It only supposed to show, more or less, how the grant_ownership could be used in such a scenario. | ||
Keep in mind that this example uses highly privileged role (ACCOUNTADMIN) and for lower privileges roles, you should look into | ||
other examples to see what else is needed to perform the same actions. | ||
|
||
##### First deployment | ||
This configuration imitates the "main" Terraform deployment that manages the account | ||
|
||
```terraform | ||
provider "snowflake" { | ||
role = "ACCOUNTADMIN" | ||
# ... | ||
} | ||
resource "snowflake_account_role" "team_a" { | ||
name = "TEAM_A_ROLE" | ||
} | ||
resource "snowflake_account_role" "team_b" { | ||
name = "TEAM_B_ROLE" | ||
} | ||
resource "snowflake_grant_account_role" "grant_team_a_role" { | ||
role_name = snowflake_account_role.team_a.name | ||
user_name = "<team_a_user>" | ||
} | ||
resource "snowflake_grant_account_role" "grant_team_b_role" { | ||
role_name = snowflake_account_role.team_a.name | ||
user_name = "<team_b_user>" | ||
} | ||
resource "snowflake_database" "team_a_database" { | ||
name = "TEST_DATABASE" | ||
} | ||
resource "snowflake_grant_ownership" "grant_team_a_database" { | ||
account_role_name = snowflake_account_role.team_a.name | ||
on { | ||
object_type = "DATABASE" | ||
object_name = snowflake_database.team_a_database.name | ||
} | ||
} | ||
``` | ||
|
||
##### Second deployment | ||
If the second deployment uses different user, then the TEST_A_ROLE should be granted to that user in the first deployment first. | ||
By using our ownership of the TEST_DATABASE, we can manage its further access to other teams. | ||
|
||
```terraform | ||
provider "snowflake" { | ||
role = "TEAM_A_ROLE" | ||
# ... | ||
} | ||
resource "snowflake_schema" "team_b_schema" { | ||
database = "TEST_DATABASE" | ||
name = "TEAM_B_SCHEMA" | ||
} | ||
resource "snowflake_grant_privileges_to_account_role" "grant_privileges_to_team_b" { | ||
account_role_name = "TEAM_B_ROLE" | ||
privileges = ["USAGE", "CREATE TABLE", "CREATE VIEW"] | ||
on_schema { | ||
schema_name = snowflake_schema.team_b_schema.fully_qualified_name | ||
} | ||
} | ||
``` | ||
|
||
Then a team using TEAM_B_ROlE can take it from here and create all the tables / views they need. | ||
|
||
#### Granting ownership with a less privileged role (granting MANAGED ACCESS) | ||
|
||
This example shows how less privileged can be used to transfer ownership of the objects they currently own. | ||
Read more in the [official Snowflake documentation](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege#access-control-requirements). | ||
For this setup, the necessary objects were created by running: | ||
|
||
```snowflake | ||
USE ROLE ACCOUNTADMIN; | ||
CREATE ROLE LESS_PRIVILEGED_ROLE; | ||
CREATE ROLE ANOTHER_LESS_PRIVILEGED_ROLE; | ||
GRANT ROLE LESS_PRIVILEGED_ROLE TO USER '<your_terraform_user>'; | ||
GRANT CREATE DATABASE, MANAGE GRANTS ON ACCOUNT TO ROLE LESS_PRIVILEGED_ROLE; | ||
``` | ||
|
||
and after the initial, setup the following configuration can be tested: | ||
|
||
```terraform | ||
provider "snowflake" { | ||
role = "LESS_PRIVILEGED_ROLE" | ||
} | ||
resource "snowflake_database" "test_database" { | ||
name = "TEST_DATABASE" | ||
} | ||
resource "snowflake_grant_ownership" "grant_ownership_to_another_role" { | ||
account_role_name = "ANOTHER_LESS_PRIVILEGED_ROLE" | ||
on { | ||
object_type = "DATABASE" | ||
object_name = snowflake_database.test_database.name | ||
} | ||
} | ||
``` | ||
|
||
The ownership transfer is possible because here you have both: | ||
- Ownership of the created above database. | ||
- MANAGE GRANTS privilege on the currently used role. | ||
|
||
Once the ownership is taken away, you still must be able to take the ownership away, so that | ||
the Terraform is able to perform successful delete operation once the resource is removed from the configuration. | ||
That being said, granting ownership would be still possible without MANAGE GRANTS, but you wouldn't be able to grant | ||
the ownership back to the original role. This is a common mistake when dealing with ownership transfers. With Terraform, you have to think | ||
about ownership when it's taken away from the current role, and what will happen when you would like to take it back. | ||
|
||
Currently, the least privileged role that is able to transfer ownership has to have at least MANAGE GRANTS privilege. | ||
In the future, we are planning to support other mechanisms that would allow you to use roles without MANAGE GRANTS. | ||
However, other assumptions would be imposed, e.g., that the current user is granted to the role it transfers the ownership to. | ||
|
||
#### Modifying objects you don't own after transferring the ownership | ||
|
||
By transferring ownership of an object to another role, you are limiting currently used role's access control on this object. | ||
This can lead to another common error of updating object after its ownership was transferred to another role. Note that | ||
every object has its access requirements and privileges needed to perform certain actions could be different in your case. | ||
The example was also done on ACCOUNTADMIN role, which means depending on the use case; additional privileges could be necessary for a given action to run successfully. | ||
Imagine you have the following configuration, and you want to change the comment parameter of the database: | ||
|
||
```terraform | ||
provider "snowflake" { | ||
role = "ACCOUNTADMIN" | ||
} | ||
resource "snowflake_database" "test" { | ||
name = "test_database" | ||
} | ||
resource "snowflake_account_role" "test" { | ||
name = "test_role" | ||
} | ||
resource "snowflake_grant_ownership" "test" { | ||
account_role_name = snowflake_account_role.test.name | ||
on { | ||
object_type = "DATABASE" | ||
object_name = snowflake_database.test.name | ||
} | ||
} | ||
``` | ||
|
||
Then, some day you would like to change the comment property of the database like so: | ||
|
||
```terraform | ||
# ... | ||
resource "snowflake_database" "test" { | ||
name = "test_database" | ||
comment = "new comment" | ||
} | ||
# ... | ||
``` | ||
|
||
With the current setup, you will encounter the following error (or similar one): | ||
```text | ||
│ Error: 003001 (42501): SQL access control error: | ||
│ Insufficient privileges to operate on database 'test_database' | ||
``` | ||
|
||
This happened, because now, you don't own this database, and your current role cannot perform any actions on it. | ||
To let the current role modify the database it doesn't own you possibly have a few choices. One of the possible options | ||
is to grant the currently used role with necessary privilege (we chose this one in the examples below). | ||
Another one could be to create a hierarchy of roles that would possibly allow you to possess certain privileges to the database. | ||
There are possibly more paths that lead to the same place, but to keep it simple, we focus on less extreme cases. | ||
|
||
Also, keep in mind that the currently used role has MANAGE GRANTS privilege which makes it easier. | ||
For less privileged roles, your options are very limited, and it would be easier to grant ownership back for a second, | ||
perform the necessary action and grant the ownership back. For a less invasive approach, you could perform grants manually and import | ||
the necessary resources into your configuration. | ||
|
||
Going back to the example, firstly, you have to revert the database change and grant the correct privilege (MODIFY) to be able to set the comment on the database. | ||
|
||
```terraform | ||
# ... | ||
resource "snowflake_database" "test" { | ||
name = "test_database" | ||
# comment = "new comment" | ||
} | ||
resource "snowflake_grant_privileges_to_account_role" "test" { | ||
account_role_name = "ACCOUNTADMIN" | ||
privileges = [ "MODIFY" ] | ||
on_account_object { | ||
object_type = "DATABASE" | ||
object_name = snowflake_database.test.name | ||
} | ||
} | ||
resource "snowflake_grant_ownership" "test" { | ||
depends_on = [ snowflake_grant_privileges_to_account_role.test ] | ||
# ... | ||
} | ||
# ... | ||
``` | ||
|
||
After that, you should be able to set the comment of your database, here's how the complete configuration should look like: | ||
|
||
```terraform | ||
provider "snowflake" { | ||
role = "ACCOUNTADMIN" | ||
} | ||
resource "snowflake_database" "test" { | ||
name = "test_database" | ||
comment = "new comment" | ||
} | ||
resource "snowflake_account_role" "test" { | ||
name = "test_role" | ||
} | ||
resource "snowflake_grant_privileges_to_account_role" "test" { | ||
account_role_name = "ACCOUNTADMIN" | ||
privileges = [ "MODIFY" ] | ||
on_account_object { | ||
object_type = "DATABASE" | ||
object_name = snowflake_database.test.name | ||
} | ||
} | ||
resource "snowflake_grant_ownership" "test" { | ||
depends_on = [ snowflake_grant_privileges_to_account_role.test ] | ||
account_role_name = snowflake_account_role.test.name | ||
on { | ||
object_type = "DATABASE" | ||
object_name = snowflake_database.test.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
Oops, something went wrong.