How do I replace the ALL permission now that it has been revoked:
REVOKE ALL ON dbo.MyObject TO MyUser
I'm looping through all the objects in a database and revoking all permissions for a specific user. So if I had to be specific about which permission to revoke, it would be a real hassle because I would have to find out what object I have and then revoke every possible permission for that type of object. Instead of just REVOKE ALL.
You can't revoke all on schema::dbo to your user but you can...
REVOKE select,update,delete,insert,execute,references on schema::DBO to USER
If you want to get a list of securables to which a database principal has been granted permission, look no further than sys.database_permissions. How to interpret the major_id and minor_id columns depends on the value of the class column (for instance, if class = 1, then major_id = object_id and minor_id = column_id). I leave that as an exercise to the reader (check out the BOL entry for it here: http://msdn.microsoft.com/en-us/library/ms187719.aspx).
Another option might be just to drop and re-add the principal. Dropping the principal would get rid of any permissions associated directly to it and re-adding it doesn't grant any (unless you specifically grant some). That might be another option (but test it first!).
You really need to have some idea what permissions you want the user to have. the pattern you have there is "Just revoke everything, then later put back whatever was there before...".
If you really need to do that, then you will have to keep your own record of what the permissions were to begin with.
A better solution would be to have some idea what the permissions ought to be. Who knows? They may have been wrong before!
Related
So, I'm trying to figure out how to properly administer a postgresql database.
I'm new with postgres and DBA in general.
I'm currently trying to have a dedicated role for a specific database.
I also want to have other user with a grant on that role so that I could do SET ROLE my_db_role and be able to manipulate this specific database from there.
However, I've got permission leakage, meaning that I can manipulate my database without having to do this SET ROLE my_db_role command.
Here are the commands I do to get my unssuccessful result :
=# CREATE ROLE test NOINHERIT;
=# CREATE USER myuser;
=# CREATE DATABASE test OWNER test;
=# \c test
=# DROP SCHEMA public;
=# CREATE SCHEMA AUTHORIZATION test;
=# GRANT test TO myuser;
=# \c test myuser
=> CREATE TABLE test.mytable(id integer);
CREATE TABLE
Temps : 46,469 ms
Why did the last commands succeeded ?
In my opinion, myuser should have no right on test database/schema, as test role has the NOINHERIT flag, so this CREATE command should not be possible.
It should need to do SET ROLE test to succeed which is not the case here.
What am I missing ?
On a side note, I have a hard time finding good source of information on how to administer properly postgresql apart from the official doc. If you can share some good material about it, you're more than welcome.
I'm afraid I don't know of any particularly good resource covering role management and administration. The standards here show all the signs of having to please several stake-holders and are flexible but confusing.
As to your immediate question though, the issue is that the "NOINHERIT" is on the wrong role. However, this feature is not really a security constraint.
test=# ALTER USER myuser NOINHERIT;
test=# \c - myuser
You are now connected to database "test" as user "myuser".
test=> CREATE TABLE test.mytable(id int);
ERROR: permission denied for schema test
LINE 1: CREATE TABLE test.mytable(id int);
^
test=> SET ROLE test;
SET
test=> CREATE TABLE test.mytable(id int);
CREATE TABLE
As you can see, myuser doesn't inherit the permissions of test but there is nothing to stop you switching directly to that role.
If you find this fiddly and confusing, then you are far from alone. I find it useful to add some tests to check any configuration I set up.
Because test is the owner of the database, it basically have all privileges on it on its subsequent objects.
As pointed out by #Richard Huxton setting NOINHERIT on test role prevent it to inherit form other roles, but does not prevent its privileges to be inherited to another roles.
When you issue:
GRANT test TO myuser;
You just grant the same privileges as the owner to myuser, therefore myuser can create object, actually it can do whatever the owner can.
It is not an issue of PostgreSQL it is the way ownership works. Anyway you can explicitly revoke privileges from owner (eg. not destroying an important object by mistake).
But you should consider other Privileges Policies for the role myuser, making it not inheriting from the owner but granting what it needs only. If the user can create a table, it should be blessed with:
GRANT CREATE ON SCHEMA test TO myuser;
I understand you are bit disappointed with PostgreSQL Privileges Management, at the very begging it can seem hard to understand through the documentation. To better learn how it actually works, you should issue:
REVOKE ALL ON DATABASE test FROM public;
Then all roles will need explicit privileges to CONNECT and SCHEMA USAGE. You will then discover the dependencies between objects and privileges. Reading more and more the GRANT page should be enough even if it is succinct.
About the SET ROLE security "issue", it is limited to all roles the current role is member of:
The specified role_name must be a role that the current session user
is a member of. (If the session user is a superuser, any role can be
selected.)
Therefore an user cannot override its privileges, it just can endorse other identity it has been granted with.
Essentially -- In postgres , how to give a db user ability to create object in a schema but not able to grant permissions on that object to others users.
Sounds like a "default permission" (IE, permissions on NEW objects). The "Grant option" needs to be revoked.
Keep in mind that this only affects NEW tables/objects. You'll have to go back and manually alter the permissions on older objects manually or create a script to do it.
alter default permissions
for USER_HERE
revoke grant option for all
The docs say
The special privileges of the object owner (i.e., the right to do DROP, GRANT, REVOKE, etc.) are always implicit in being the owner, and cannot be granted or revoked.
Since these special privileges cannot be revoked, I think the only way to prevent the object owner from granting or revoking privileges is to take ownership away (make some other user the owner) after the object is created.
But this seems a strange thing to do, and I think you'll probably get better answers by asking about the real problem rather than asking about one solution. That is, "How do I prevent an object's owner from granting privileges?" is not the real problem--it's one "solution" to an unstated problem. Think about what the real problem is.
I need to grant object privileges to a user but I'm not the owner of the schema.
I've tried doing it with the System user but I can't either.
My long shot was using the Sys user (other than System) but it is deactivated and there is no way I'll be able to activate it with my user.
Is there any way I grant that privilege to a user? I can't ask the owner of the schema to do that because she resigned today... and I don't wanna change the pwd of her DB user.
I know that at some point I'll need to create a new DBAdmin user and create a backup of those schemas because when the SAP user of my colleague be deleted, it'll delete the Hana user and the DB user with all of the objects, roles and privileges created and granted with it.
Oh oh!
Be very careful here with the deletion of the user since - as you correctly write - the deletion will have a cascading effect.
Also:
you have to either have the ownership for the objects OR the privileges you want to grant with grant option.
Using the SYSTEM user won't help with that and SYS can never be used to logon to the database anyway.
Since there is also no way to take over ownership, the only actual way really is to find out which objects and privilege grants the user has created/performed.
Then logon to the user and refactor the grants to roles that cover the object privileges.
As a next step, you may consider creating a non-logon user to own the objects and then perform a import/export of the users' objects.
Finally you may create design time roles with the required privileges to the objects. This allows granting/revoking of the privileges by a user with the ROLE ADMIN privilege, which makes management a lot easier and better structured.
Sure:
(
SELECT "SCHEMA_NAME",
'' AS "OBJECT_NAME",
'SCHEMA' AS "OBJECT_TYPE", "SCHEMA_OWNER" as "OWNER_NAME"
FROM "PUBLIC"."SCHEMAS"
WHERE SCHEMA_OWNER = 'A' UNION ALL
SELECT "SCHEMA_NAME", "OBJECT_NAME",
"OBJECT_TYPE", "OWNER_NAME" FROM "PUBLIC"."OWNERSHIP"
WHERE
"SCHEMA_NAME" IN
( SELECT "SCHEMA_NAME" from "PUBLIC"."SCHEMAS"
WHERE "SCHEMA_OWNER" = 'A' ) OR "OWNER_NAME" = 'A'
) ORDER BY "SCHEMA_NAME" ASC, "OBJECT_NAME" ASC;
You find this and lots of other useful stuff in the SAP HANA book I wrote: https://www.sap-press.com/sap-hana-administration_3506/
I have a table and I want to deny its modification to all users except one. One obvious solution is to create a special denying role and add all other roles to it. But in that case new roles will be still able to modify the table, unless added to this role. What is the decent way do set such permissions?
You should GRANT rights (INSERT,UPDATE,DELETE) to the one special "write" role only. And no other rights except SELECT
There is no need to DENY because users do not have rights by default: DENY would be needed only if you GRANT rights in the first place.
Keep it simple.
Notes:
If writes are via a stored procedure (with same owner), permissions won't be checked at all
dbo etc will always have rights (unless you use a trigger, but dbo can disable or drop it)
Is there a way I can give developers permission to grant a user permissions over objects without giving them the option to create users or functions?
I'm trying to limit developers permissions, I recently found out that developers had db_owner permissions in dev and prod environments! So I'm doing my best to stop this madness.
Any good article about this matter?
You can make them members of the "db_securityadmin" database role
As said, if someone could hand out permissions, they could hand out permissions to themselves (or a dummy account). I'm not sure if there is a trick in SQL Server to provide "give user permissions less then me".
The way I would do it is with stored procedures.
Create a stored procedure that gives a specified user a specific right or set of rights (those rights are the ones that regular users are allowed to have). Then give the developers execute access to this stored procedure. In effect you use stored procedures to create a limited version of GRANT, while keeping the full GRANT command to yourself.
If someone can give someone else permissions, he can also give himself the permission to do what he wants. So what is this good for? Probably I don't understand your situation.
Owners of objects can grant permissions on those objects. Provided your developers don't need to grant things like CREATE TABLE rights, you might be able to give them ownership of the objects that you want them to grant permission on.
As Stefan said, giving them grant permissions would effectively give them all permissions, since if they want to do something all they have to do is grant themselves the permissions to do it.
Rather than considering the developers the enemy, though, you may want to consider giving the developers a second user account that's used to administer the database. It's pretty common not to give developers ANY permissions to production, at least on their development account.
Setting permission on objects like stored procedures can be accomplished with "GRANT EXECUTE ON . to ;
However, you may also want to grant security rights at both the login and user level. You will want to determine and grant ONLY the necessary rights for the objects that require access (such as execution). Consider use of the "EXECUTE AS" capability which enables impersonation of another user to validate permissions that are required to execute the code WITHOUT having to grant all of the necessary rights to all of the underlying objects (e.g. tables). The EXECUTE AS can be added to stored procs, functions, triggers, etc.
Add to the code as follows right within the Stored Procedure: CREATE PROCEDURE dbo.MyProcedure WITH EXECUTE AS OWNER
In this case you are impersonating the owner of the module being called. You can also impersonate SELF, OR the user creating or altering the module OR... imperonate CALLER , which will enable to module to take on the permissionsof the current user, OR... impersonate OWNER, which will take on the permission of the owner of the procedure being called OR... impersonate 'user_name', which will impersonate a specific user OR... impersonate 'login_name' with will impersonate a specific login.
MOST of the time, you will only need to grant EXECUTE rights to stored procs and then rights are granted to all objects referenced within the stored proc.
In this way, you DO NO need to give implicit rights (example: to update data or call additional procs). Ownership chaining handles this for you. This is especially helpful for dynamic sql or if you need to create elevated security tasks such as CREATE TABLE. EXECUTE AS is a handy tool to consider for these.
This example may help clarify all of this:
Create a user called NoPrivUser with public access to a database (e.g. dbadb)
USE [master] GO CREATE LOGIN [NoPrivUser] WITH PASSWORD=N'ABC5%', DEFAULT_DATABASE=[dbadb], CHECK_EXPIRATION=ON, CHECK_POLICY=ON GO USE [DBAdb] GO CREATE USER [NoPrivUser] FOR LOGIN [NoPrivUser] GO
NOTE: CREATOR OR OWNER OF THIS PROCEDURE WILL REQUIRE CREATE TABLE RIGHTS within the target database.
use DBAdb go CREATE PROCEDURE dbo.MyProcedure WITH EXECUTE AS OWNER AS IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].MyTable') AND type in (N'U')) CREATE TABLE MyTable (PKid int, column1 char(10)) INSERT INTO MyTable VALUES (1,'ABCDEF')
GO
GRANT EXEC ON dbo.MyProcedure TO NoPrivUser; GO
-- Now log into your database server as NoPrivUser and run the following.
use dbadb go
EXEC dbo.MyProcedure
(1 row(s) affected)
Now try to select from the new table while logged on as NoPrivuser.
You will get the following:
select * from MyTable go
Msg 229, Level 14, State 5, Line 1 The SELECT permission was denied on the object 'MyTable', database 'DBAdb', schema 'dbo'.
That is expected since you only ran the procedure under the security context of Owner while logged on as NoPrivUser.
NoPrivUser as no rights to actually read the table. Just to execute the procedure which creates and inserts the rows.
With the EXECUTE AS clause the stored procedure is run under the context of the object owner. This code successfully creates dbo.MyTable and rows are inserted successfully. In this example, the user "NoPrivUser" has absolutey no granted rights to modify the table, or read or modify any of the data in this table.
It only takes on the rights needed to complete this specific task coded WITHIN the context of this procedure.
This method of creating stored procedures that can perform tasks that require elevated security rights without permanently assigning those rights come be very useful.
I've found that the most dangerous aspect of the db_owner role is that if you issue a deny on a permissions, then the members of the role can grant it back to themselves. I've just started reading about this and I'm testing this
Create role db_ControlDatabase
grant control to db_ControlDatabase
deny backup database to db_ControleDatabase
alter role db_ControlDatabase add member TestUser
So far, I've found that the subject TestUser has permissions without being able to add or remove members of the fixed database roles. You should be able to deny whatever you need at this point like backup certificate, backup master key, etc.
Here is a list of permissions that can be denied or granted: