I'm running these queries with the ACCOUNTADMIN role - as this is a stated requirement here TABLE_STORAGE_METRICS View.
If I run this query it returns records as expected:
select *
from snowflake.account_usage.table_storage_metrics
where TABLE_CATALOG = 'OPENBANKING'
limit 10;
However, if I try and query the table in the INFORMATION_SCHEMA in the database then the query runs but returns no data. I get the same result in every database I have tried.
select *
from "OPENBANKING"."INFORMATION_SCHEMA"."TABLE_STORAGE_METRICS";
Does anyone know why I can't see the data in the xxx.INFORMATION_SCHEMA.TABLE_STORAGE_METRICS views - or why there is no data in these views?
You can only see records in the Information_Schema for those objects your current role has access privileges to, see here: https://docs.snowflake.com/en/sql-reference/info-schema.html#general-usage-notes
Maybe accidentally your role on the worksheet-level is not set to ACCOUNTADMIN and you have to run a USE ROLE ACCOUNTADMIN; in front.
Related
I have created a new user 'u' using my 'security_admin' role, and assigned role 'r' (which already has some select/usage permission on few tables) to the user. Now I want add more permissions to the role. I have ran below statement:
grant select on all tables in schema db_name.schema_name to role r;
The above statement gives necessary permission to the user 'u', i have checked with show grants to role r statement. However the granted permission is valid only for one day, the next day the user does not have the permission that is granted using above statement. It keeps happening for sometime. I do not know what the problem is. I do not have any automated SQL script to recreate users & grants daily.
If you could share the actual error message you get, that would be helpful for us to understand where the problem lies. But I suspect that it's just a case of not having access on FUTURE TABLES (tables that has been created after the grants was applied).
These commands should cover you:
use role securityadmin;
grant usage on database db_name to role r;
grant usage on schema db_name.schema_name to role r;
grant select on all tables in schema db_name.schema_name to role r;
grant select on future tables in schema db_name.schema_name to role r;
One plausible scenario is that tables are recreated with CREATE OR REPLACE TABLE command. It could be checked using query history view.
SELECT *
FROM snowflake.account_usage.query_history
WHERE DATABASE_NAME = 'DATABASE_NAME_HERE'
AND QUERY_TEXT ILIKE '%CREATE%OR%REPLACE%TABLE%'
ORDER BY START_TIME DESC;
In such case the permissions may not be preserved, unless specyfing COPY GRANTS option.
Optional parameters:
COPY GRANTS
Specifies to retain the access privileges from the original table when a new table is created using any of the following CREATE TABLE
variants:
CREATE OR REPLACE TABLE
CREATE TABLE … LIKE
CREATE TABLE … CLONE
I've been reading many answers but I am too weak at TSQL to filter out what I need.
I created a contained user for 1 DB...
CREATE USER appuser WITH PASSWORD = 'strongpwd';
So I need to allow a user in to read only the contents of 1 table - tableA (there are others in the DB) and do absolutely nothing else in the DB.
I do not want to affect any other users. I just want the user to be able to access the DB via say SSMS, see only tableA (well this is not that important), read it.
There are two ways one is to directly grant explicit SELECT only on Table 1 and the second one is to create a role, grant SELECT to role and addd the user to the role. Typically second way is the preferred way and can be done as below
CREATE ROLE [role_name]
GRANT SELECT ON [Table] to [role_name]
EXEC sp_addrolemember '[role_name]', 'appuser'
We have a requirement to provide customer access to a staging database so that they can extract their data into their own servers, but every table contains all customers data. All of the tables have a 'CustomerID' column. Customers should only see rows where the customerID is the same as theirs.
I am not looking for suggestions to create separate databases or views for each customer as both suggestions are high maintenance and low efficiency.
My solution has to work with:
100GB database
400 Tables
Updates every 30 minutes from the core transaction database
Quarterly schema changes (Application is in continuous Development).
Can anyone give me a definitive answer as to why the following method is not secure or will not work?:
I've set up a database user for each customer, with their customerID as an extended property.
I've created a view of every table that dynamically selects * from the table where the customerID column is the same as the extended property CustomerID of the logged in user. The code looks like this and appears to work well:
CREATE VIEW [CustomerAccessDatabase].[vw_Sales]
AS SELECT * FROM [CustomerAccessDatabase].[Sales]
WHERE [Sales].[CustomerID]=
(SELECT CONVERT(INT,p.value) AS [Value]
FROM sys.extended_properties
JOIN sys.sysusers ON extended_properties.major_id=sysusers.[uid]
AND extended_properties.name = 'CustomerID'
AND sysusers.[SID]=(SELECT suser_sid())
);
GO
To provide access to the views I've created a generic database role 'Customer_Access_Role'. This role has access granted to all of the table views, but access to the database tables themselves is denied.
To prevent users from changing their own customerID I've denied access to the extended properties like so:
USE [master];
GO
DENY EXEC ON sys.sp_addextendedproperty to [public];
GO
DENY EXEC ON sys.sp_dropextendedproperty to [public];
GO
DENY EXEC ON sys.sp_updateextendedproperty to [public];
GO
The end result is that I only need one database, and one set of permissions.
To add a new customer all I would need to do is create a new user with their customerID as an extended attribute and add them to the Customer_Access_Role. Thats it!
I am going to reiterate what everyone is stating already and sum it up.
You are making your job harder than it has to be.
Create a View, that is just their data and then give them Security access to that View.
Alternatively, extract all their data out of the "Core" database and into their own and give them the necessary access to that data.
When I want to select from table Y in database X I can use
select * from [X].[dbo].[Y]
or
USE X
select * from [Y]
Is there any reason to prefer one over the other?
dbo
Using dbo as the owner of all the database objects can simplify managing the objects. You will always have a dbo user in the database. Users in the database will be able to access any object owned by dbo without specifying the owner as long as the user has appropriate permission.
USE X
When a SQL Server login connects to SQL Server, the login is automatically connected to its default database and acquires the security context of a database user. If no database user has been created for the SQL Server login, the login connects as guest. If the database user does not have CONNECT permission on the database, the USE statement will fail. If no default database has been assigned to the login, its default database will be set to master.
Understanding the Difference between Owners and Schemas in SQL Server
USE (Transact-SQL)
I'd tend to use [server].[database].[schema].[table] in instances where a script may query mutliple tables from multiple databases.
The USE [database] would typically be used in scenarios where all statements were to apply to the same database and you needed to make sure they were applied to the correct database. Have you ever connected to a server and run a script only to find you ran it on the master database?
USE X will change the context to X and all the following statements will execute under the context X.
But X.dbo.Y will access the object Y without changing the current context.
Eg: Let us consider there is two databases DB1 and DB2. DB1 contains table T1 & T2 and DB2 contains tables U1 & U2.
Now,
USE DB1 -- here context set to DB1
select * from T1 -- works fine
select * from U1 -- gives error, because U1 is not in current context
select * from DB2.dbo.U1 -- works fine, because it access the context DB2 from current content context DB1
select * from T2 -- works fine
USE DB2 -- here context changed to DB2
select * from U2 -- works fine
select * from T1 -- gives error, because T1 is not in current context
select * from DB1.dbo.T1 -- works fine, because it access the context DB1 from current content context DB2
by using first Query you can perform that selection from other databases.In the same window you can have the selection for other data beses also.
But By using second selection, From the same window you can have selection for that(USE X) databse only.
Sometimes you want the schema and database to be dictated by the login, and in this case you should simply use the object name. That's one reason to not fully qualify them.
How can I restrict some users in DB2, not to see the table structure. I set the user privilege and restrict user from table access. so that user can not select data or change table but still can see the table structure or describe it.
This problem refers to row access in tables which is added in db2 version 10.
I had this problem too.
you can use this version - if applicable- and restrict user access from specific table structures.
You need to remove the select grant on catalog tables. For example, the following query should return 0 rows when executing with q restricted user.
db2 "select tabschema, tabname from syscat.tables"
All tables and views in the following schemas should not have select on public, nor in any group the restrictive user is in.
sysibm
syscat
db2 revoke select on SYSIBM.SYSTABLES from username