Setting up a user to my database in my SQL Server - sql-server

I just finished creating a new user for my database in SQL Server. I had 4 tables I wanted to grant Insert, Update, Select and delete permissions. I did this manually in the Securables area of the new user.
Is there a better way to do this that to have to touch each object? if so, how?
Thanks,
rod.

One way is use schemas such that
tables belong to a schema (let's call it data, CREATE SCHEMA)
users belong to a role (CREATE ROLE, sp_addrolemember)
permissions are assigned to the role on the schema (GRANT INSERT ON schema::data to myRole)
Now, you can add new tables or change users without losing/creating permissions

If you want finely granular control over who can do what, I don't think there's a whole lot you can do - you're doing it just fine.
gbn's approach is quite nifty - another approach for "simple" setups (when you don't need a whole lot of different permissions) is to:
grant every user (or a role) the database role db_datareader - this allows read access
(SELECT) on all tables and views
grant every user (or a role) the database role db_datawriter - this allows write access (INSERT, UPDATE, DELETE) on all tables and views
If you also need to grant execution rights on stored procedures, there's unfortunately no predefined role to use. You can however create your own database role and then grant execute permissions to that role. The great thing is: this permission to execute stored procedures also applies to all future stored procedure you might create in your database!
To define your new role, use this:
CREATE ROLE db_executor
GRANT EXECUTE TO [db_executor]
and then you can just assign db_executor to those users who need to be able to execute stored procs and stored functions in your database.

Related

Exclusive User ownership on sql server tables

Requirement: User who created tables in a particular schema, should own the tables, other users who got access to that schema should not able to perform any action on that table(including read).
Example:
Tables created by ‘User1’ in ‘Schema1’ should be exclusive to the User1 only with (SELECT, CREATE, UPDATE and DELETE)
Other Users who got access to ‘Schema1’, should not able to perform any actions on the tables created by ‘User1’
This requirement is expected to be available for users who have access to the 'schema1', so the tables they create is accessible only for them and not for other users.
For the sake of the discussion let's CREATE new LOGIN, new SCHEMA, and new USER.
use master
GO
CREATE LOGIN SO_Login WITH PASSWORD = 'Dont1Use2This3In4Production'
GO
Use AdventureWorks2019
GO
CREATE SCHEMA SO_Schema
GO
CREATE USER SO_User FOR LOGIN SO_Login;
GO
In theory, you could get what you are looking for, by simply have a rule which allows CREATE TABLE on specific schema. Something like: GRANT CREATE TABLE ON SCHEMA::SO_Schema TO public;
In this case we could give everyone the option to CREATE TABLE on the schema and use simple DDL trigger on CREATE TABLE in order to add permissions like SELECT,DELETE,INSERT,UPDATE for the user that created the table.
unfortunately, GRANT CREATE TABLE ON SCHEMA is not supported.
To CREATE TABLE you Required to have CREATE TABLE permission in the database and ALTER permission on the SCHEMA in which the table is being created.
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql?view=sql-server-ver15#permissions-1
This makes the task more complex and probably not recommended in most cases since you will need to provide more permissions than what you really want the USER to have...
If you still want to get this work (against the recommendation) then you will need to GRANT ALTER ON SCHEMA and GRANT CREATE TABLE on database to all - all means "public"
use AdventureWorks2019
GO
GRANT ALTER ON SCHEMA::SO_Schema TO public;
GO
GRANT CREATE TABLE TO public;
GO
next, you will need to DENY the unwonted permission since the above will give all USERs a lot more power than you want to!
This can be done by CREATE DDL TRIGGER on the DATABASE for any DDL_DATABASE_LEVEL_EVENTS
https://learn.microsoft.com/en-us/sql/relational-databases/triggers/ddl-event-groups?view=sql-server-ver15
inside the TRIGGER you should check what was the event. If it was something else than CREATE_SCHEMA or the USER that executed the event should not CREATE SCHEMA then you ROLLBACK TRANSACTION;.
Note! Since you do not want to change the trigger each time a new USER need to CREATE TABLE and add the USER name to the hard coded list of users which can CREATE TABLE, it is best to CREATE new ROLE and simply add each USER you need to this ROLE
CREATE ROLE ModifyTable;
GO
In this case that you based on a ROLE like above ModifyTable, you can GRANT ALTER ON SCHEMA and GRANT CREATE TABLE only to the ROLE ModifyTable instead of to public
In addition, in the same TRIGGER if the USER is one of these that should be able to CREATE the table then you should GRAND him permission to INSERT, DELETE, UPDATE, SELECT on the table which he just created.
Remember that if you forget to DENY a permission from this USER or all the rest then you might have a security issue - which is why this is not recommended procedure.
Your best option is to re-0design the system so you will not need this exact recruitment. So... you can do it as I explained here, but it is not recommended for most cases.
A much better approach is NOT to permit USERs to CREATE TABLEs except for these you can trust with all tables. You should CREATE THE TABLEs for your users directly or using application which you control, and give them the permission to use the specific table which they need. ALTER SCHEMA is not recommended permission to give to simple users!
A user with ALTER permission on a schema can create procedures, synonyms, and views that are owned by the schema's owner. Those objects will have access (via ownership chaining) to information in other schemas owned by the schema's owner. When possible, you should avoid granting ALTER permission on a schema if the schema's owner also owns other schemas.
https://learn.microsoft.com/en-us/sql/t-sql/statements/grant-schema-permissions-transact-sql?view=sql-server-ver15

SQL Server roles and permissions

I really need some advice about adding roles at the server level and apply some permissions that will be applicable to each database on my server.
Basically I need to two roles read only and read write.
The read will have permissions to select and see any object
The write will have permissions to select/insert/delete and execute any object
I want to create a server role, then a login associated to this role (which can be a AD group) and after that for each database create a user that will inherits all permissions from the server role.
So on each database, I will have each user that belongs to the server role created, the problem is to clearly define the permissions, is not straight forward in my opinion.
What I can see, I cannot assign read or write to a role and then use it on each db, on the contrary on the General tab of the server role I have a bunch of permissions that is not clear which one to use for this purpose.
Maybe I'm doing it wrong but I want to have something at the server level and not define the same role on each db for that purpose. I'm using SQL server 2014.
The short answer is you can't.
Generally, server-level permissions are not propagated down to individual objects within databases. The only exception is a sysadmin role, which I would strongly encourage you not to use for this purpose, as you would essentially give up the control of the entire server instance to every member of it.
As a kind of a shorthand, you can use built-in database roles to save yourself a bit of trouble. For read-only access, a membership in db_datareader role is usually enough, unless you have stored procedures that return datasets which this role is supposed to be able to execute. There is also a similar role for modification, db_datawriter, but it doesn't cover the execute permission. So you will have to create a custom role for that:
create role [DataChanger] authorization [dbo];
go
alter role [db_datareader] add member [DataChanger];
go
alter role [db_datawriter] add member [DataChanger];
go
grant execute to [DataChanger];
go
-- Now you can add your members. Here is a reader
create user [Domain\MyUser1] from login [Domain\MyUser1];
go
alter role [db_datareader] add member [Domain\MyUser1];
go
-- Writer
create user [Domain\MyUser2] from login [Domain\MyUser2];
go
alter role [DataChanger] add member [Domain\MyUser2];
go
These permissions will automatically pick up newly created objects, without you having to explicitly add new permissions after every schema modification.
You will have to do this in the context of every user database that you want to manage in this way. You can probably create a SQL Agent job which will run periodically and introduce these changes in any user databases which don't have them already (for example, if a database has been restored from earlier backup, or brought from another server, or a new one was created). Also, since you can't loop through databases in static code, you will need to wrap it into a dynamic SQL and loop through sys.databases, or maybe via an undocumented sp_MSforeachdb system stored procedure. Oh, and don't forget to remove all these go statements from dynamic code, as they are not part of SQL, and are only recognised by SSMS and sqlcmd.
P.S. All that being said, I hope you are not going to manage any production databases in this manner. I don't even know where to start on how insecure this approach is.

SQL Server - What role to use for application access?

What Server Role(s) and/or Database Role(s) must a SQL Login have to do the following:
Read Data (including Temp tables)
Write Data (including Temp tables)
Execute any SP within a database which they are granted access
We are migrating from SQL 2000 to 2008 and I'm going through all the Logins and have noticed they are all set to sysadmin & db_owner, which isn't good. Our apps that use these logins will only do what I've listed above so that's why I'm wondering. I know I can set each Login with a Database Role of db_datareader & db_datawriter but that doesn't include executing SP's. We've got close to 300 SP's in 2 or our DB's and to have to go through each SP and set the login permissions in the Extended Properties would be WAY too long and tedious.
Any help is greatly appreciated!
to have to go through each SP and set the login permissions in the Extended Properties would be WAY too long and tedious
And yet, this would also be the most secure.
Using the built in roles exposes too much of your database to your application.
Can you give the db_datareader and/or db_datawriter execute rights? This will give the user rights to execute any stored procedures in databases it has access to. If you have views you will also need to grant them select rights.
GRANT EXECUTE TO db_datawriter
I would either just deal with it and set the permissions manually or (my preference) create database roles that have the types of permissions you want to give, and assign logins to those. That way if multiple logins need the same set of permissions, you just give them the same role.
As a bonus, if your programmability objects have some sort of prefix naming convention so that (for example) procedures that read from your login information tables all start with something like pAccount_ or something, then you can dynamically do GRANTs to roles based on the prefix of the routine.

Grant user DDL permissions on specific schema

Using SQL Server (2008), is it possible to grant a specific user full control of the objects under a specific schema? This includes create/drop/alert table. Its important that this user isn't not given db_ddladmin role because that would give him access to other tables.
You can create a role in the database, assign all appropriate permissions(SELECT, UPDATE, DELETE, EXECUTE, etc.) to the role, and then assign the user to that role.

How to grant permissions to developers to grant permissions to users?

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:

Resources