I have access to some schema in different database and as part of some migration work, I am comparing 2 schema.
I am using Syscat to compare the 2 schema. However in one of the schema, I get an error saying
"user does not have select privilege on "
I would like to know , how can I see what and all access permissions have been set up in a particular schema (basically all users who have access and the type of access for a gievn schema). The database is db2.
Please note that I am not using any tool like schema crawler etc. Instead I am writing a JDBC application which uses the Syscat to query the details like select * from syscat.tables where tabSchema = <schemaName>
Using a tool etc is a long process in terms to getting approval , justification etc (and I personally think that JDBC program should be good to start with the analysis).
In DB2 privileges granted on a schema do not give you any privileges on objects belonging to that schema (unless you created those objects yourself). You have to be granted explicit object privileges or certain database level privileges, such as DATAACCESS.
The actual DB2 error message should contain the name of the object that generates the error. Try printing the String representation of the SQLException object.
A schema is a logical group of objects. These objects can be views, tables, indexes, sequences, functions, sotred procedures, etc. Each of these objects has a different set of privileges: table has select, insert, delete and others; stored procedure has the execution and others; etc. It means that every single object has different types of privileges, and you cannot get "all privilegesfor a given schema", you have to give the type of object.
For example, in order to get the privileges on tables for a given schema, you can execute
db2 "
select substr(GRANTEE,1,16),GRANTEETYPE,substr(tabschema || '.' || tabname,1,64),
CONTROLAUTH, ALTERAUTH, DELETEAUTH, INDEXAUTH, INSERTAUTH, REFAUTH, SELECTAUTH, UPDATEAUTH
from syscat.TABAUTH
where tabschema like 'MYSCHEMA%'"
Each kind of object that a table in syscat schema that contains the privileges for that kind of object. You just have to query the table.
In a similar way, you can create the appropiated sentences in order to grant or revoke privileges on an object
select 'grant select on ' || trim(tabschema) || '.' || trim(tabname) ' to user johndoe'
from syscat.tables
where tabschema like 'MYSCHE%'
Finally, there are not only privileges (grants) on db2, there are also database level authorities, and some of them have privileges on all objects.
Related
I know I can run this:
grant select on all tables in schema whatever to "my_dev_group";
but the way I've built our CI system - we use lots of different schemas, so the schema is only known at the time of running the tests - not when the script is written. Ie we run the same script against lots of different test schemas and we set the schema name at the start...
so I am trying to achieve the equivalent of the above grant statement - but to operate on the current schema - without any success.
ie all of these were spectacularly unsuccessful
grant select on all tables in schema current to "my_dev_group";
grant select on all tables in schema current_schema() to "my_dev_group";
grant select on all tables to "my_dev_group";
is it possible to do without going into the world of executing dynamic sql, which I'd prefer not to
SQL doesn't have a notion of a “current schema”. Consequently, there is no syntax to change the permissions of all tables in the current schema.
You could loop through all schemas in the search_path or all schemas in the database and run a GRANT statement for each one. Make sure to skip system schemas like information_schema and pg_catalog.
Alternatively, you could use the current_schema() function to retrieve the first existing schema on your search_path and change permissions for that schema.
Using Vault I'm trying to create an on-demand temporary read-only users in a Postgres 11.8 instance.
I will have:
1000+ databases (one per customer aka tenant)
Each database has a public and reporting schema.
So I'm trying to find a way to grant this read-only user access to every database, and on all tables in both schemas.
While I came up with the following snippet:
-- Create a new user
CREATE ROLE "my-readonly-user" WITH LOGIN PASSWORD 'test123';
-- Grant access to the two schema's we have
GRANT USAGE ON SCHEMA public TO "my-readonly-user";
GRANT USAGE ON SCHEMA reporting TO "my-readonly-user";
-- Grant access to all tables in our two schema's
GRANT SELECT ON ALL TABLES IN SCHEMA public TO "my-readonly-user";
GRANT SELECT ON ALL TABLES IN SCHEMA reporting TO "my-readonly-user";
-- Grant access to sequences
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO "my-readonly-user";
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA reporting TO "my-readonly-user";
-- Grant access to future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO "my-readonly-user";
ALTER DEFAULT PRIVILEGES IN SCHEMA reporting GRANT SELECT ON TABLES TO "my-readonly-user";
It will only apply to 1 single database (the current one). If I login with the readonly user and switch to some databases, I don't see any tables except in the first database.
A cluster holds many databases, which hold many schemas. Schemas (even
with the same name) in different DBs are unrelated. Granting
privileges for a schema only applies to this particular schema in the
current DB (the current DB at the time of granting).
https://stackoverflow.com/a/24923877/1409047
Because of that limitation, it seems to make the grant snippet from above more complex. Should I iterate all my databases somehow and run the snippet? How would I do the database switch? Is it even possible in plain SQL (as required by Vault's API)? Anyone did this before?
Note: doing the same in MySQL only requires 2 lines of code, using wildcards *.* which is not supported in Postgres afaik:
CREATE USER '{{name}}'#'10.0.0.0/255.0.0.0' IDENTIFIED BY '{{password}}';
GRANT SELECT, SHOW DATABASES, SHOW VIEW ON *.* TO '{{name}}'#'10.0.0.0/255.0.0.0';
It is a deliberate design decision that an SQL statement cannot affect objects in a database different from the one that you are connected to.
Yes, you will have to iterate through all databases in your cluster and run your script there.
Note that there is a mistake in your script: you shouldn't grant a read-only user USAGE on sequences, else they can modify the sequence value. SELECT is fine.
What I would do is create a read_only_group (with NOLOGIN) and grant all these permissions to that role. Then, when there is a request for a read-only user, create a user and add it to that group, so that it inherits the group privileges. Don't grant anything to the user itself, so that you can easily DROP it when it is no longer needed.
If you want to grant readonly access to an user using only a Postgres script, you can do that:
CREATE EXTENSION IF NOT EXISTS dblink;
DO
$$
DECLARE nome_banco TEXT;
DECLARE template_conexao TEXT;
DECLARE string_conexao TEXT;
DECLARE nome_usuario TEXT;
BEGIN
template_conexao = 'user=foo password=bar dbname=';
nome_usuario = 'baz';
FOR nome_banco IN
SELECT datname FROM pg_database
WHERE datistemplate = false
LOOP
string_conexao = template_conexao || nome_banco;
perform dblink_exec(string_conexao, 'GRANT CONNECT ON DATABASE "' || nome_banco || '" TO ' || nome_usuario);
perform dblink_exec(string_conexao, 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO ' || nome_usuario);
END LOOP;
END
$$
--DROP EXTENSION IF EXISTS dblink;
It connects to each database, and executes the script; it can be easily adapted for other situations where you need to execute a database-local command on all of the databases.
Remember that, for security purposes, after executing the script above, you should drop the dblink extension created by the script above, unless, of course, you are already using the extension for other purposes.
When collaborating with colleagues I need to change the schema name every time I receive a SQL script (Postgres).
I am only an ordinary user of a corporate database (no permissions to change anything). Also, we are not allowed to create tables in PUBLIC schema. However, we can use (read-only) all the tables from BASE schema.
It is cumbersome for the team of users, where everybody is creating SQL scripts (mostly only for creating tables), which need to be shared amongst others. Every user has its own schema.
Is it possible to change the script below, where I will share the script to another user without the need for the other user to find/replace the schema, in this case, user1?
DROP TABLE IF EXISTS user1.table1;
CREATE TABLE user1.table1 AS
SELECT * FROM base.table1;
You can set the default schema at the start of the script (similar to what pg_dump generates):
set search_path = user1;
DROP TABLE IF EXISTS table1;
CREATE TABLE table1 AS
SELECT * FROM base.table1;
Because the search path was change to contain user1 as the first schema, tables will be searched in that schema when dropping and creating. And because the search path does not include any other schema, no other schema will be consulted.
If you
However the default search_path is "$user", public which means that any unqualified table will be searched or created in a schema with the same name as the current user.
Caution
Note that a DROP TABLE will drop the table in the first schema found in that case. So if table1 doesn't exist in the user's schema, but in the public schema, it would be dropped from the public schema. So for your use-case setting the path to exactly one schema might be more secure.
I am trying to understand the securables of SQL Server, I am not sure on what is the exact use of OwnedSchema. Can someone help me on this, where it plays a significant role?
The dialog on the picture enlist you all database's schemas and marks some schemas as "checked" if current database principal is the owner of these schemas.
So it shows you the result of this query (that you can catch using Profiler):
SELECT
s.name AS [Name],
s.schema_id AS [ID],
ISNULL(dp1.name, N'') AS [Owner],
CAST(
case when s.name in ('dbo','guest','INFORMATION_SCHEMA','sys','db_owner','db_accessadmin','db_securityadmin','db_ddladmin','db_backupoperator','db_datareader','db_datawriter','db_denydatareader', 'db_denydatawriter') then 1 else 0 end AS bit) AS [IsSystemObject]
FROM
sys.schemas AS s
LEFT OUTER JOIN sys.database_principals AS dp1
ON dp1.principal_id = s.principal_id
Using this dialog you can change the owner of the schema to current user, i.e. execute the following code:
ALTER AUTHORIZATION ON SCHEMA::[this_schema] TO [this_user]
This link is also useful to understand Ownership and User-Schema Separation in SQL Server.
Schema Owners and Permissions
Schemas can be owned by any database principal, and a single principal
can own multiple schemas. You can apply security rules to a schema,
which are inherited by all objects in the schema. Once you set up
access permissions for a schema, those permissions are automatically
applied as new objects are added to the schema. Users can be assigned
a default schema, and multiple database users can share the same
schema. By default, when developers create objects in a schema, the
objects are owned by the security principal that owns the schema, not
the developer. Object ownership can be transferred with ALTER
AUTHORIZATION Transact-SQL statement. A schema can also contain
objects that are owned by different users and have more granular
permissions than those assigned to the schema, although this is not
recommended because it adds complexity to managing permissions.
Objects can be moved between schemas, and schema ownership can be
transferred between principals. Database users can be dropped without
affecting schemas.
I've added a user to a Firebird 2.1 instance using gsec, but now I wanted to grant SELECT on all tables to this new user. I could find how to grant this permission on specific tables, but not to them all:
GRANT SELECT ON TABLE table TO USER user;
If I try to use the new user I get the following error on isql:
no permission for read/select access to TABLE table
Is there a way to do that on Firebird 2.1?
Something like this:
EXECUTE BLOCK
AS
DECLARE VARIABLE tablename VARCHAR(32);
BEGIN
FOR SELECT rdb$relation_name
FROM rdb$relations
WHERE rdb$view_blr IS NULL
AND (rdb$system_flag IS NULL OR rdb$system_flag = 0)
INTO :tablename DO
BEGIN
EXECUTE STATEMENT ('GRANT SELECT ON TABLE ' || :tablename || ' TO USER TEST');
END
END
I could find how to grant this permission on specific tables, but not to them all
You can grant specific privileges to all users, already existing and yet to be created. That is made by granting privilege to "PUBLIC" pseudo-user. Or you could grant privileges to some ROLE, then grant this ROLE to given users, then during database connection specify the option, that the user impersonate this ROLE in this session.
However there is no syntax to grant privileges to all generators or all procedures or all views or all tables, etc.
See the GRANT statement syntax in documentation.
What you can do though, is creating a simple script (anonymous and volatile aka EXECUTE BLOCK or persistent and named as STORED PROCEDURE) and that script of yours would be querying system tables to list all non-system ( COALESCE(RDB$SYSTEM_FLAG,0)=0 ) tables (together with views, or tables but not views: check if RDB$RELATION_TYPE is 0 or is 0 or 1) and then form a sequence of GRANT statements and execute them one by one.
See documentation about EXECUTE BLOCK and FOR SELECT ... INTO ... DO ... and EXECUTE STATEMENT ( or maybe FOR EXECUTE STATEMENT also, but I do not think it already was there in FB 2.1. There is unofficial wiki tracking which statements were available since which FB versions, but it is not thorough and may contain errors: http://firebirdsql.su/doku.php ).
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-security-privs.html#fblangref25-security-privs-grant
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-relations.html
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-psql-coding.html#fblangref25-psql-execstmt
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-dml-execblock.html