Granular access control for shared databases in Snowflake - snowflake-cloud-data-platform

When using shared databases in Snowflake (as a data consumer), there seems to be no other way to control the access than granting IMPORTED PRIVILEGES on the DB, which effectively grants read-only access to the entire DB and all its schemas & objects.
Is there no way to grant more granular access to the schemas & objects inside a shared database? My goal would be to create roles that have access to only limited portions of the share (specific schemas or objects, like I can with a regular database).
For example, let's say I want to share a database with 10 schemas in it (as a data provider), and would like to restrict/control the access to each of these schemas on the consumer side... would there be no other option than to create 10 shares (one for each schema) on the data provider side? And so on to restrict/control access for specific tables & views?
This is assuming I have access to both accounts (the provider and the consumer), or that I can negotiate the implementation details with the provider/consumer.

Is there no way to grant more granular access to the schemas & objects inside a shared database?
Currently, there is not.
For example, let's say I want to share a database with 10 schemas in it (as a data provider), and would like to restrict/control the access to each of these schemas on the consumer side... would there be no other option than to create 10 shares (one for each schema) on the data provider side? And so on to restrict/control access for specific tables & views?
That's how you would have to do it currently.
Edit: Actually, following up on Robert's answer, if the inbound side of the share is a full account rather than a reader account, you could sort of restrict access by creating a view that filters out rows based on current_role(). It wouldn't be like a privilege, more like row level security based on role.

One approach to this problem is to block access to certain objects in the share for those roles which you don't want to allow access. If your role owns the share then you can block access by revoking privileges on the objects from the share. If your role does not own the share, but owns the objects in the share, you can block access by revoking the USAGE or SELECT privileges with CASCADE on the objects from the share owner.
Alternatively, depending on all the details, it may be easier just to create as many seperate shares as are needed.

Related

Is it a good practice to separate roles with 'usage' permissions on data warehouse compute from other roles which provide access to databases?

With the ability to allow secondary roles, is it a good practice to separate roles with 'usage' permissions on data warehouse compute from other roles which provide access to databases, schemas. tables? As example, I create a role called 'USE_DEV_DW". This role is granted usage to the DEV data warehouse compute. In parallel, I create a role that has usage on a specific set of databases and schemas. I then grant both roles to a user so that they can query the provided database tables using the separately provided compute (data warehouse). This way I can control what compute users have access to separate from what objects they can query. I don't see this being possible without the ability to provide for secondary roles? Looking to see if others have done something like this.
Even though there is no guidelines from Snowflake how to create the roles, the way you described makes sense.
When you have two layers of roles, let's call them database and functional,
it will be easier to create role hierarchies and assign them to users.
For illustration purposes assuming you have DEVELOPERS and ANALYSTS as your groups and you have SALES and PRODUCTS databases
You can create your roles and role hierarchies like this
Database Roles
R_DB_SALES_READ_WRITE
R_DB_SALES_READ
R_DB_PRODUCTS_READ_WRITE
R_DB_PRODUCTS_READ
Functional Roles
R_DEVELOPER
R_ANALYSTS
Role Hiercharchy
R_DEVELOPER
R_DB_SALES_READ_WRITE
R_DB_PRODUCTS_READ_WRITE
R_ANALYSTS
R_DB_SALES_READ
R_DB_PRODUCTS_READ
With this you only need to assign functional roles to users

Snowflake schema creation from a share

Wanted to confirm if it is not possible to create a schema from a share.
I see from the documentation that once a share (from a schema not the entire database) is created/enabled by the provider account,I/the consumer account can only leverage the share by creating a new database.
I/Consumer already have a snowflake database & would like to just point the schema from the provider that is enabled as share to a new schema on my side in the existing database. This avoids the need to maintain multiple databases.
Br,
Noor.
It is not possible.
In consumer side, the ff. command is used to consume a share:
CREATE DATABASE <name> FROM SHARE <provider_account>.<share_name>;
Hence, consumption can only be done in database level. This effectively creates a read-only database (unlike regular/local databases), all of its objects are controlled by the provider.
Additionally, IMPORTED PRIVILEGES is used to grant roles in consumer side access on shared database. Cannot grant this privilege on a Schema.

SQL Server permissions and views

I'm curious if there is a way for a user to use a view in database A (they have permission to database A) that accesses tables in database B (and/or additional databases they don't have permission to) without the user having access to database B?
My scenario:
We currently have a database (database A) where most of the views are housed. Most users across the team also have access to database A. We are wanting to split out our data tables from database A into their own databases (on the same server). When we do this, of course, the views will break because the tables they access will now be in database B. Since there are so many views, I'm looking for an easier way. My thought was to use database A as the hub for the views and as the views are accessed, permissions are granted to the various databases for the user(s) - without giving them direct access to the other databases.
Thank you in advance.
I think a database role would be better than a database as the container for view access.
It might be easier to delete objects than to move them. A backup-restore can create a copy of the database. Then delete the tables and views that don't belong in each database.
Cutting corners on security or integration can come back to bite. If the tables are distinctly part of different systems, then the views should go with the tables. Security and integration between systems by cross database references will tie all those systems to the same server. (Linked servers would be a performance and DTC nightmare.) We have several "separate" justice applications (e.g., DA, Public Defender, Probation, etc.) that do this. Security is still detailed via the use of database roles for each use. The integration is great, but it's a nightmare to migrate because it's all at once and together. If done correctly (e.g., connections strings to each database), we would be able to move one database at a time and update and test one system at a time. As it is now, it takes a lot of project management and a long time to get everybody ready.
If the tables are part of the same system, then schemas could be an option to segregate them if database roles are to tedious to manage. Is it more work to segregate the objects into databases or schemas than to manage a role?
Also, if you use SSDT db projects, then those cross database references (circular?) can be a pain.
For security, I would suggest a database role for each group that needs access. There is no "magic" database level container just for views. The best you can do is SELECT which includes tables and views. For just views, a script is not hard to create to grant a db role select access to all views in the db. I would not ever use grant select and then a DENY on tables because it can prevent access to table for users that should have access. If one or more schemas are used for the views, a role can be granted SELECT access to the schema. This might be the best option. If the view schema and the objects accessed by the view have the same owner, the ownership chain should allow access via the view to tables. For example, if the "view" schema is owned by "dbo", views in the "view" schema should be able to access tables in the "dbo" schema without the user being granted access to those tables. (I have not tried it.)
It would be nice if there was a second flavor of INSERT, UPDATE, etc. permissions that applied to views only, but there isn't.

How to share SNOWFLAKE.ACCOUNT_USAGE schema using managed/reader account?

I am trying to share my Snowflake Database(default metadata)--> Account_Usage schema --> Query_History table to another managed account (i.e. reader account) but the data is not visible in another account.
is there any way to share the snowflake database without duplicating the data?
I am getting error as Already Imported Database (i.e) SNowflake cannot be shared for Datashare option.
for a Managed account for usage, I Snowflake database and schemas are available but are not able to see the data which is available.
According to the documentation you can't re-share any database that is shared with you:
Shared databases and all the objects in the database cannot be forwarded (i.e. re-shared with other accounts).
Since the Snowflake database is one that is shared to you from Snowflake, this is probably why you're having issues.
If you need to do this your best bet is to create a table and populate it with the data you need from the Snowflake database and share that table instead. Although it is strange that you'd want to share this info with another account.
Your other option would be to create database/schema in your account with views over the account usage data that you want to share, create a role that can access only that, and then provide a user login with that role only to the group needing to do analytics on your data.

Understanding access when there is database chaining

I am new to SQL Server database and I am struggling to figure out the access issue for one of the user on a particular view. I don't want to expose any of my base tables.
The scenario is: I have 3 databases, DB one, two and three
Database one has 2 base tables
Database two has one view on top of those tables (tables in database one)
Database three has one view which is on top of the view of database two
Database three is our data warehouse. So, I would like to know if I give select permission on only database three's view, will that suffice?
The catch is I don't want to expose any of my base tables in database one
If I grant select permission to user1 on datawarehouse view (view in database three) and deny all the permissions to the base tables (in database 1), then is it possible?
Thanks
Ownership chaining allows access to data via the view without permissions on the underlying tables as long as all objects are owned by the same security principal. There is no need for an explicit GRANT or DENY on the indirectly used objects with an unbroken ownership chain since permissions are checked only on the directly access view. The object owner is typically inherited from the schema owner.
To allow ownership chaining to extend across multiple database:
The DB_CHAINING database option must be ON for the databases involved.
The user must be able to use the databases (have a user account in each database with CONNECT permissions), although only permissions on directly accessed objects are needed.
In the case of dbo-owned objects, the databases must be owned by the same login (AUTHORIZATION) since the dbo schema owner is the database owner. For other schemas, the schema owner must map to the same login.
DB_CHAINING should be enabled only when you fully trust highly-privileged users (those with permissions to create database objects).

Resources