Grant access to a specific future table in Snowflake - snowflake-cloud-data-platform

I'm currently using Fivetran to pipe data into Snowflake. Once the data has landed, every 6 hours DBT runs some simple saved queries, which appear as tables in a schema.
However, the permissions for various roles keep being reset and they can no longer access the tables in that schema that I gave them permission to see. I suspect this is because DBT is dropping and then re-creating the tables in question.
One possible solution is to grant access to future tables in the schema, e.g.:
grant select on future tables in schema myschema to role some_role;
However, I just want to give access to a single table, not all. Is that possible?

This is totally possible with post-hooks! Used in concert with {{ this }} (docs), they're a powerful and flexible tool.
You have two options for providing access on a single table using post-hooks:
as a config block at the top of the model definition file (below), or
in the dbt_project.yml
{{ config(
post_hook=[
"grant select on {{ this }} to role some_role;"
]
) }}
select ...
Here's a more in-depth guide to granting access in a dbt project
p.s. love your username!

Related

How to create view in Snowflake based on a query that uses multiple roles and multiple databases?

I have multiple Snowflake roles, each one gives me reading access to different data warehouses/databases. Also, I have one role that gives me write access to a Sandbox schema. Some of the latest projects I'm working on require manipulating and joining data across warehouses/databases. Selecting my role as ALL, I have managed to query the data and view the final result in a Snowflake worksheet. However, when it comes to creating a view in the Sandbox schema, I get the following error:
"SQL compilation error: Cannot create permanent objects while using role ALL. Use TEMPORARY keyword to create a temporary object instead." Any idea how to workaround this error?
This is an inherent limitation of the ALL role. You can get by (as the error instructs) by creating a table (first temporary, then permanent) instead of a view (temporary views are not available) if that's an option.
The use of USE ROLE ALL; shouldn't be pervasive in proper use of Snowflake, since it supports hierarchal roles, with multiple privileges granted into a single assumed role.
Very limited object-mapped roles were necessary in other DBMS that lacked role hierarchies (or limited their levels). I recommend revising your role creation and granting strategy to use Snowflake's access controls more effectively.

INFORMATION_SCHEMA.TABLES access to all schemas and tables

I am creating a user that should only have access to the database tables metadata,via INFORMATION_SCHEMA, and not the table data. So no perms to query the tables directly. The role the user will be a member of will have USAGE privileges on INFORMATION_SCHEMA schema. I tested the user with that role and it is only able to see tables within public and no where else.
I did see in Snowflake documentation:
"The output of a view or table function depend on the privileges granted to the user’s current role. When querying an INFORMATION_SCHEMA view or table function, only objects for which the current role has been granted access privileges are returned."
So, I tried to grant to the role MONITOR and USAGE on other schemas; but, that did not work either. Only when I granted a role with read access to all the tables in the schema was it able to see and query from INFORMATION_SCHEMA.TABLES the tables in that schema. This, however, is not what I want as now that user would be able to query data from the tables. I just want to set that user to be able to query and gather the metadata of tables and not allow data access. Is there a way in Snowflake to setup and perform this type of setup?
I believe the only way to do this would be to provide access to the SNOWFLAKE.ACCOUNT_USAGE share on Snowflake, which also has TABLES and would allow this user to query the metadata of all tables and columns in that Snowflake account. There is a lot more information available in that share, but at least the user would not have access to any real data, if that is what you are after.

How do I fo back and deduct the role hiearchy of my trial account?

Apologies for the new question, but I am having trouble understanding the best practices for understanding the recommended role set up for my account. I am auditing what I have created to backwards engineer and correct it on a new warehouse.
So here is the situation:
I granted all permissions on all warehouses modify AND usage to the sysadmin.
When running worksheets and ./snowsql in parallel, I used the ACCOUNTADMIN for all of the sessions in snowsql.
When I use the Sysadmin to modify the tables that copied the data staged in the warehouse sometimes I have permissions and other times I don't.
I have been sifting through account history with the ACCOUNTADMIN role to view all the grants with the recommended query from the documentation below:
select *
from table(information_schema.query_history())
order by start_time;
I filtered then by the database and query_id to include grant
select *
from table(information_schema.query_history())
where database_name = 'temp_db'
and query_id like '%grant%'
order by start_time;
I did this to see if there were any differences in the grants I did between databases in the warehouse. I only set up two warehouses so it was easy to see.
Going forward, Accountadmin is used to create roles, warehouses, and databases.
To prevent the need to do an audit when switching between roles, I want to set future grants on Sysadmin to specific databases in a warehouse for modification and usage, how do I do that?
Permissions to warehouses, database, and all other objects are separate things. Granting permissions to a warehouse let's that role use or modify a warehouse, but that has nothing at all to do with creating, updating, etc. other objects like databases, schemas, tables, and views. Also, only the role that OWNS a table can drop or alter a table. So, you might want to check on the ownership of the tables between SYSADMIN and ACCOUNTADMIN. As a best practice, ACCOUNTADMIN shouldn't own anything.
It would take quite a bit more information to give you a full rundown of RBAC in Snowflake. If you are struggling with it, you might want to contact Professional Services at Snowflake and get them to come in and do an overview (QuickStart or Security package) to get you straightened out.

grant read access on a view but not on it's underlying tables from other databases

I want to grant read permissions for a user for a view which joins 2 tables from another database.
I don't want to:
give him permission on the database where the tables are or add him as an user there.
Make him the owner of the view/schema due to the security exploits.
I don't want to create first a table, or variations of a hack table with a truncate and a stored procedure which inserts the data on a trigger.
Can this be done somehow? Maybe there's something I missed and you guys might know.
I have read these posts but they didn't solve my problem:
Grant SELECT permission on a view, but not on underlying objects
Grant Select on a view not base table when base table is in a different database
https://msdn.microsoft.com/en-us/library/ms188676.aspx
https://dba.stackexchange.com/questions/89632/sql-server-grant-select-access-to-a-user-in-a-view-and-not-in-its-tables
Thank you
Edit:
The easiest solution I came up with, after some research, is activating the cross database ownership chainingoption on the database where I'm placing the views and granting the read permission to the users. This might be in contrast with my 2nd point of things I'm trying to avoid. Is this a good idea?
Give them a login to another database on the same server, and include only your single view, with the view pointing to your secure database. Don't give that login any access to anything but the database with the view in it, and only read access to that single view. Obviously, you'll have to fully qualify your table name (e.g., from SourceDB.dbo.SomeSecretTable).
What I ended up doing:
Create an active directory group.
Add users to the AD group.
Create a login for the AD group mapped for the source DB and target DB.
Add the user on the target DB and give him permissions only for the requested views.
(Optional) Added the group on all the databases to deny select.
Couldn't find a solution for my original question without the AD group.

Cross-database view permissions

I'm working with a database (let's call it DB_data) that contains all of the tables for a series of applications. In an attempt to minimize downtime during upgrades, a facade database (let's call it DB_facade) has been created which has a view for each of the tables in DB_data. It also contains all of the functions and stored procedures, which work against these views.
In trying to lock down security in DB_data we've done a DENY on all of the tables for all of the users in DB_data. All of these users have also been created in DB_facade with permissions to the views.
The problem here, is that because of cross-database ownership chaining the DENYs in DB_data are overriding the GRANTs in DB_facade.
I'd like to avoid turning on ownership chaining for both of these databases because of the potential security issues (although in my original tests, that did seem to correct the access problem). Also, we're trying to minimize impact to the applications, so requiring all access to be through stored procedures and using certificates (for example) wouldn't work.
Does anyone have any other suggestions on how to handle this?
Thanks!
Do you have this problem if you exclude the DENY on the tables in DB_data? If you don't explicitly GRANT permissions on these tables, you may be able to get the security you need and get the access rights through the views.
from what i've seen and done, sql server doesn't let you have any permissions unless explicitly told so. You should be able to grant select (or use the role datareader) in DB_Data to the users, and as long as it's the same account and it's mapped to both databases (you'll have to grant select and exec on db_facade) that should work just fine.
You can create a view in the DB_data database for each view in the DB_facade database. The new views would have rights to select from the tables. GRANT SELECT on the views in DB_data. Change the views on DB_facade to SELECT from the views on DB_data. And, the tables would have DENY set.
I recognize one disadvantage to this; the users can still interact with the DB_data database. They wouldn't be able to access the tables, but they could access the new views.

Resources