How to Run DDL on Snowflake SHOW <object< - snowflake-cloud-data-platform

I am not sure if it is possible but can you run DDL the SHOW Role function:
show grants to role SYSADMIN
If I run this it shows me the privs attached to the role in the results field but I would like to run a sub-query on this but it seems to always give me an error.

You can't use the rows in the show command directly (unless you're using an external client and programming the code, such as ODBC, JDBC, Python).
What you can do in a client worksheet is use the results indirectly like this:
show grants to role sysadmin;
select * from table(result_scan(last_query_id()));
To use it in a query, just alias and reference it like a table:
show grants to role sysadmin;
show grants to role my_new_role;
select NR.*
from table(result_scan(last_query_id())) NR
inner join table(result_scan(last_query_id(-2))) SA
on NR."privilege" = SA."privilege"
and NR."granted_on" = SA."granted_on"
and NR."name" = SA."name"
;
You can then use the age-old DBA trick of creating a SQL generator:
select 'grant ' || "privilege" || ' on ' || "granted_on" || ' etc.. etc...' as SQL_COMMAND
from table(result_scan(last_query_id()))
where "privilege" <> 'OWNERSHIP'
;
You can even use an SP to automate execution of the generated commands:
https://community.snowflake.com/s/article/Executing-Multiple-SQL-Statements-in-a-Stored-Procedure

Related

Cloning a role or copying grants to a new role in Snowflake

I would like to create a new role (role_new) that initially has identical grants to another role (role_old). Ideally, I would be able to clone a role. However, it doesn't look like it's possible to clone a role in Snowflake. The reason I don't want to use inheritance here is because I plan on revoking some grants from role_old, and therefore they will also get revoked from role_new.
It doesn't look like there is a way to copy grants from one role to another. Is this correct? The closest thing we have is inheritance.
Has anyone encountered something similar? Any ideas on how to handle this?
You can use a SQL generator to do this.
Step 1: Run a "show" to get the grants for a role.
Step 2: Run a SQL generator from the result_scan to create a list of grant statements.
Step 3: (Optional) Automate running them all using a stored procedure.
I haven't tested this much, but it would look a little like this:
show grants to role SYSADMIN;
select 'grant ' || "privilege" || ' on ' || "granted_on" || ' to MYNEWROLE;' as SQL_COMMAND from table(result_scan(last_query_id()));
If you want to run all your generated SQL statements, I wrote a stored procedure to do that specifically for generated commands:
https://support.snowflake.net/s/article/Executing-Multiple-SQL-Statements-in-a-Stored-Procedure
I don't think there's an easy way to clone an existing role's grants/permissions. Typically, this is a reason why I recommend people maintaining their Snowflake environment through code via Git and other tools like Flyway.
Otherwise you can view Grants and Roles by executing "Show Grants" and "Show Roles". And you can also look at using SnowReport or snowflakeinspector to visualize your security setup. But I think your best bet is to store your security framework via code so you can copy/modify/paste and execute it that way.
From post above Make sure to add the name:
show grants to role ANALYST;
select 'grant ' || "privilege" || ' on ' || "granted_on" ||' '||"name"|| ' to Genpactanalyst;' as SQL_COMMAND from table(result_scan(last_query_id()));
For the complete migration, you might want to:
// Grants to
show grants to role <old role>;
select
case
when "granted_on" = 'ROLE' then 'grant role ' || "name" || ' to role <newrole>;'
else 'grant ' || "privilege" || ' on ' || "granted_on" || ' to role <newrole>;'
end as script
from table(result_scan(LAST_QUERY_ID()))
;
// Grants on
show grants on role <old role>;
select
'grant role ' || "name" || ' to role ' || "grantee_name" ||';' as script
from table(result_scan(LAST_QUERY_ID()))
where privilege != 'OWNERSHIP'
;

SQL Server - You do not have permission to use the bulk load statement

Using SQL Server 2016, I am trying to configure a user other than 'SA' to import a file. The code I am executing is as follows:
EXECUTE AS USER = 'DataImports';
SELECT CURRENT_USER;
EXEC xp_cmdshell 'TYPE myFileNameHere.txt'
BULK INSERT DataImports.staging_AddressBook
FROM 'myFileNameHere.txt'
WITH (DATAFILETYPE = 'char'
, FIRSTROW = 2
, FIELDTERMINATOR = ' '
, ROWTERMINATOR = '\n');
The error that I get is:
Msg 4834, Level 16, State 1, Line 20
You do not have permission to use the bulk load statement.
I have validated the following:
I do have access to the file as the user required - The cmdshell TYPE returns the rows expected. I do not appear to have a file access issue.
I have INSERT permission on the database in general.
I tested by using:
SELECT
[DatabaseUserName] = princ.[name],
[PermissionType] = perm.[permission_name],
[PermissionState] = perm.[state_desc]
FROM
sys.database_principals princ
LEFT JOIN
sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id]
WHERE
princ.[name] = 'DataImports';`
I do have the bulk admin role
SELECT
r.name AS [RoleName],
m.name AS [MemberName],
CASE
WHEN m.name IS NOT NULL THEN 1 ELSE 0
END AS IsMember
FROM
sys.server_principals r
LEFT JOIN
sys.server_role_members rm ON (r.principal_id = rm.role_principal_id)
LEFT JOIN
sys.server_principals m ON (rm.member_principal_id = m.principal_id)
WHERE
r.type = 'R' AND m.name = 'Dataimports';
I have even configured the user to be a sys-admin (not part of the long term plan) but I'm still getting the error.
These are the main points that have been highlighted in the other SO tickets and general searches I have performed. I can import the table as SA but not as DataImports despite what appears to be correct configuration.
This is part of a job that is being run and currently we are having to give SA access just to read a file. Security wise this is less than ideal but I cannot work out what is missing.
Any suggestions of what else to check would be gratefully received - all the basics seem to be in place.
Any suggestions
of what else to check would be gratefully received - all the basics
seem to be in place.
Few things:
GRANT ADMINISTER BULK OPERATIONS TO Dataimports
If the destination table contains triggers or checks constraints
GRANT ALTER ON TABLE DataImports.staging_AddressBook TO Dataimports
And
ALTER DATABASE [yourDB] SET TRUSTWORTHY ON;
Because of:
For security considerations, the server-scoped permissions are
stripped down when you impersonate a database user unless the system
administrator has explicitly set SQL Server to trust the impersonated
context at the server-scope. In this case, a login with the control
server server-scoped permission has no permissions to access any
particular database. Therefore, the trigger module that is executed as
this login cannot run.

How to access IBM DB2 warehouse on cloud as administrator

I'm currently using a free DB2 warehouse on cloud provided by IBM. What I'm trying to do is to create a new table in the database. However, an error message pops up saying that
To resolve this, I open the web console and run the following command: create tablespace mytablespace pagesize 4096. Then, another error message pops up:
Based on what I have googled, it looks like I need to grant administrator role for the user "DASH******". So I do this by adding an optional parameter to the credentials:
But it doesn't work. Is there any way to workaround this?
EDIT1: I create the table using the following command:
Users are not allowed to create their own tablespaces in free DB2WoC systems, since they don't have the SYSCTRL or SYSADM authorities there. You have to use existing tablespaces where you are allowed to create your tables.
Run the following statement from your DASH*** user.
This statement returns all the tablespaces, where your user is allowed to create tables.
If it doesn't return any rows, then this means, that you should open a ticket to the IBM support. Support should create it for you and grant your user the USE privilege on this tablespace.
SELECT
T.DATATYPE
--, P.PRIVILEGE
--, P.OBJECTTYPE
--, P.OBJECTSCHEMA
, P.OBJECTNAME
, U.AUTHID, U.AUTHIDTYPE
FROM SYSIBMADM.PRIVILEGES P
CROSS JOIN TABLE(VALUES USER) A (AUTHID)
JOIN TABLE (
SELECT GROUP, 'G' FROM table(AUTH_LIST_GROUPS_FOR_AUTHID(A.AUTHID))
UNION ALL
select ROLENAME, 'R' from table(AUTH_LIST_ROLES_FOR_AUTHID(A.AUTHID, 'U'))
UNION ALL
SELECT * FROM TABLE(VALUES ('PUBLIC', 'G'), (A.AUTHID, 'U')) T (AUTHID, AUTHIDTYPE)
) U (AUTHID, AUTHIDTYPE) ON U.AUTHID=P.AUTHID AND U.AUTHIDTYPE=P.AUTHIDTYPE
JOIN SYSCAT.TABLESPACES T ON T.TBSPACE=P.OBJECTNAME
WHERE P.OBJECTTYPE='TABLESPACE' AND T.DATATYPE IN ('A', 'L')

DB2 IBM everytime I create a view in my database the permissions are limited to the user that created, I want to be for everyone

DB2 IBM everytime I create a view in my database the permissions are limited to the user that created, I want to be for everyone:
create view stkqry.aaa as SELECT ... from ...
Now this "aaa" is protected. I would like to be available for everyone by default.. how to do? thanks
(This answer assumes you're using DB2 for Linux/Unix/Windows)
You have to use GRANT to assign the special AuthID "PUBLIC" (everyone) permissions to the view.
GRANT SELECT ON stkqry.aaa TO PUBLIC
I don't think that there's a way to automatically mark all views as readable by public, but if you need to go back and mark all of them, you could use something like this to generate the statement for you:
SELECT 'GRANT SELECT ON ' ||
TRIM(VIEWSCHEMA) || '.' ||
TRIM(VIEWNAME) || ' TO PUBLIC'
FROM SYSCAT.VIEWS
WHERE DEFINER <> 'SYSIBM'

In SQL Server 2005, is there an easy way to "copy" permissions on an object from one user/role to another?

I asked another question about roles and permissions, which mostly served to reveal my ignorance. One of the other outcomes was the advice that one should generally stay away from mucking with permissions for the "public" role.
OK, fine, but if I've already done so and want to re-assign the same permissions to a custom/"flexible" role, what's the best way to do that? What I've done so far is to run the Scripting wizard, and tell it to script object permissions without CREATE or DROP, then run a find-replace so that I wind up with a lot of "GRANT DELETE on [dbo.tablename] TO [newRole]". It gets the job done, but I feel like it could be prettier/easier. Any "best practice" suggestions?
Working from memory (no SQL on my gaming 'pooter), you can use sys.database_permissions
Run this and paste the results into a new query.
Edit, Jan 2012. Added OBJECT_SCHEMA_NAME.
You may need to pimp it to support schemas (dbo.) by joining onto sys.objects
SET NOCOUNT ON;
DECLARE #NewRole varchar(100), #SourceRole varchar(100);
-- Change as needed
SELECT #SourceRole = 'Giver', #NewRole = 'Taker';
SELECT
state_desc + ' ' +
permission_name + ' ON ' +
OBJECT_SCHEMA_NAME(major_id) + '.' + OBJECT_NAME(major_id) +
' TO ' + #NewRole
FROM
sys.database_permissions
WHERE
grantee_principal_id = DATABASE_PRINCIPAL_ID(#SourceRole)
AND
-- 0 = DB, 1 = object/column, 3 = schema. 1 is normally enough
class <= 3;
The idea of having a role is that you only need to setup the permissions once. You can then assign users, or groups of users to that role.
It's also possible to nest roles, so that a role can contain other roles.
Not sure if its best practice, but it makes sense that if you have a complex set of permissions, with groups of users that need access to multiple applications you go something like:
NT User -> NT Security Group -> SQL Server Role -> SQL Server Role A, Role B ...

Resources