Set user permissions per connection? - sql-server

Is it somehow possible to set the user permissions per connection in SQL-Server?
for example:
DENY insert ON all TO user
DENY update ON all TO user
DENY delete ON all TO user
So, suppose a user is connected as sa (* see EDIT) in my application, can I somehow change (and possibly restore) permissions at some point for this user (so for e.g. at that point he has a read-only access)?
EDIT: sorry for giving a wrong example. the user is NOT sa but other user with full access.

As I mentioned in the comments, permissions aren't set at connection level, they are set at Login and User level.
If you have a connection, and you change the permissions of the login/user being used, those permissions will be applied immediately to that connection, and any others; thus a connection using the Login and User AppUser cannot have different permissions to another connection user the exact same Login and User.
If you need an application to have different permissions for different things, there's nothing wrong with creating multiple Logins and Users; each with their own permissions. You then control the Login the application uses my using different connection string, depending on the role needed. This is quite a common practice; for example you might have a different database for your application's security model, and thus a different login is used to make changes to that database.

there are system stored procedures about security section and i guess that would be the only way since SQL gotta be secured.
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/security-stored-procedures-transact-sql?view=sql-server-2017
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-dropsrvrolemember-transact-sql?view=sql-server-2017
EXEC sp_dropsrvrolemember 'JackO', 'sysadmin';

Related

Login and user is not there IN SQL Server 2017 then why in T-SQL it shows up?

Suppose I have a login metamanager\test which shows when I execute T-SQL, but it is not there when when I expand Security -> Login in SSMS.
Same with a database user.
I try to replicate but failed
use master
select * from sys.syslogins is used for login
use DB
select * from sys.sysusers is used for database user
A LOGIN and a USER are completely different objects.
A LOGIN is a server object, and appear in sys.syslogins, as you see.
A USER is a database object, and for a LOGIN to have access to a database, it needs to have a USER mapped to the LOGIN in that database. A LOGIN with no mapped logins in any databases, and without any server level roles, will be unable to access any of the database on the instance, apart from those that the public roles has in tempdb and master.
It appears, here, you need to create the user in the database, and then give it the appropriate permissions. You can create the USER with the following:
USE {YourDatabase};
GO
CREATE USER 'metamanager\test' FOR LOGIN 'metamanager\test';
You'll need to give it the appropriate permissions afterwards.
Also, after you have created the user, ensure you have refreshed your object explorer. Object explorer doesn't automatically refresh after you create an object.
Not sure if you explaining it correctly, but syslogins and server_principals are about the same. Only the difference that server_principals include "Roles".
As far as I know it is impossible to have something in syslogins, which does not exist in server_principals.

How to give read and write permissions to a user to my database?

I am looking for a way to guarantee read and write permissions to my database to another user in my network.
I know Microsoft SQL Server Management lets my add users by right clicking on the user section
here
and filling this
form.
Still, I am not sure what my Login name should be. For example, If I want to guarantee permission to the Administrator of a computer named GOR-PC, what should I enter?
Many Thanks.
You should use GOR-PC\Administrator.
However, adding local users to your SQL Server is generally a bad idea.
Ideally, you should use Active Directory users (in the form DomainName\UserName). This guarantees that the permissions you grant are independent of the existing of a PC or server.
First you should create a user or group for the administrator on the server level that is under the general "Security" tab below the dabases: Security->Login->create.
After tahat you can use the same login name you just created under the specific databse and Beowse the user and after that give the user read and write permission.
Hope that helps.

What SQL Server Login is used for SQL Server Authentication?

I am trying to figure out what SQL Server Login gets used when I connect to SQL Server, in code, via a connection string that specifies Integrated Security=No and then specifies a user and password.
Note that I don't mean the user I'm specifying (I do know that of course), but the login that user maps to. I'm just now reading about logins vs users in SQL Server, and one point that is hammered home is that you always, always, always need a login to connect, and then a user per database that login needs to access. So I am looking in SSMS for the login that maps to the user I always specify on the databases I care about, but I see no such login.
Fyi, the reason I am asking, is I need to permission a new legacy app for this database, and the app is coded to use SQL Server authentication. I am trying to determine if I simply need users on the necessary database, or if I need to create a login. But now I've gotten myself curious about the general question itself.
Edit - a quick query of syslogins shows only 2 logins. So, my theory that SQLS was maintaining trivial '1 per user' logins but SSMS was hiding them, appears not to be the case
Edit - Querying syslogins, or sys.server_principals, appears to be misleading. On a database for which I have 2 different working SQLS (not Win) logins, I logged in as each and did select * from sys.server_principals. Two different answers: each time I got sa and the login I was logged in as. I would not see the 'other' login, though it was clearly there. I am guessing this may have something to do with schemas, which I also know little about. In any case, I am guessing that generally, logins do in fact exist for all users, though I will not see all these logins when I connect to SSMS as any one login. Does this sound right?
Solved (sort of)
From playing around, on a database on which I have sa, it is clear that SSMS only shows you all logins if you are sa, or perhaps have that specific permission. Otherwise, your view of logins is restricted. Therefore there is no real mystery as to why I was not seeing logins I was expecting. Apparently SSMS hides them. I say 'sort of' and 'apparently' because I never came across anything documenting this. It is just an observation.
Thanks to all for your help.
It is a server-level login unless you are connecting to a contained database. If you mean the database user that the server-level login maps to, you can find out using:
SELECT u.name
FROM sys.server_principals AS l
INNER JOIN sys.database_principals AS u
ON l.sid = u.sid
WHERE l.name = 'user id in your connection string';
If you are not using a contained database, this is how you would provision your user:
USE master;
GO
CREATE LOGIN your_login_name
WITH PASSWORD = 'f00b#r!', CHECK_POLICY = OFF;
GO
USE your_database;
GO
CREATE USER your_login_name -- doesn't have to match, but should for sanity
FROM LOGIN [your_login_name];
GO
-- then apply permissions of course.
In general logins maps to a database user
So for instance if by some unfortunate circumstance the app expected database owner access
You'd create this here login on the server (if it's not already there) and then map it to the dbo user in the database in question.
If it's not a built in user, then you are going to have to look at a db that this legacy app can already access, find out which user it's mapped to
Create that user on your new DB, set the required permission roles etc
Then map the login to it.
There are some subtle differences between sql server versions, so it's hard to do a step by step
If the user the apps login maps to is a custom one, then you are going to have to figure out an equivalent in the new database. Doesn't have to have the same name though (unless the app is using that) and it could even have more permissions.

Preserving SQLServer permissions

How can I stop a particular user from accessing the database for a period of time but at the same time not lose the permissions the user has on db objects.
Basically when he comes back (ie when access is given back) he should have all the permissions he had before his access was cut off. If I use sp_revokedbaccess 'myuser' the user myuser loses all permissions he had on db objects.
Is there a way to preserve myuser's permissions without resorting to cumbersome backup permissions and restore permissions kind of workarounds?
Thoughts:
DENY CONNECT user or DENY CONNECT SQL TO login (sp_revokedbaccess is deprecated)
You cannot use ALTER_LOGIN with the DISABLE argument to deny access to a Windows group (quoted from link)
Assign all rights to a database role, then revoke rights from user. Add user to role when needed. It's a bad idea to assign object rights to users directly anyway.
If user has sysadmin rights, you can't deny them anything at all (perhaps CONNECT SQL?)
If user has db_owner rights (assumes set up in DB), you can't deny them anything in the database except CONNECT
The simplest way i see it is to disable the login. You can do this on the login properties in SSMS under the status page.
You can achieve the same thing with the following T-SQL:
Assuming your login is bob a sql login, but can also be a windows login
ALTER LOGIN bob DISABLE
Then, to enable the login
ALTER LOGIN bob enable
You should be able to explicitly DENY him a permission, then revoke the deny.
You can also disable the login with ALTER LOGIN ... DISABLE, but will block at server level, not database level.
A hack solution is to map the user to a different login, then map him back (ALTER USER .. LOGIN = ...), but is a hack and I'm not sure even works correctly.
How is the user accessing the database? If via an application, then just log the user out and require the user to re-authenticate.
we want to remove access during maintenance but bring him back after it is done.
Have the maintenance process acquire exclusive locks on whatever tables it is processing. This locks everyone out until the processing is complete.
Can you switch the database to single user mode? http://msdn.microsoft.com/en-us/library/ms345598.aspx
Or script up the permissions before you remove them: http://www.sql-server-performance.com/articles/dba/object_permission_scripts_p1.aspx. I know this is "backup permissions and restore permissions" - but this script makes the process a lot less cumbersome.
If the current password is known, change the password to a temporary value during the maintenance window. Re-setting the password to its initial value serves this purpose without making any material changes to the account.
If you are using Windows authentication and you can lock out this user from everything on the domain, you can set the times the user is allowed to log on in Active Directory. I can't provide detailed instructions but there should be something on ServerFault by now.

SQL Server 2005 "public" database role doesn't seem to apply?

I have a SQL Server 2005 database that I'm trying to access as a limited user account, using Windows authentication. I've got BUILTIN\Users added as a database user (before I did so, I couldn't even open the database). I'm working under the assumption that everybody is supposed to have permissions for the "public" role applied to them, so I didn't do anything with role assignment. Under tblFoo, I can use the SSMS Properties dialog (Permissions page) to add "public", then set explicit permissions. Among these is "Grant" for SELECT. But running
SELECT * from tblFoo;
as a limited (BUILTIN\Users) account gives me an error "Select permission denied on object 'tblFoo', database 'bar', schema 'dbo'". In the properties dialog, there's an "Effective Permissions button, but it's greyed out.
Further, I tried creating a non-priv account called "UserTest", adding that at the server level, then mapping it down to the "bar" database. This let me add UserTest to the "Users or Roles" list, which let me run "Effective Permissions" for the account. No permissions are listed at all -- this doesn't seem right. The account must be in public, and public grants (among other things) Select on tblFoo, so why doesn't the UserTest account show an effective permission? I feel like I'm going a bit crazy here.
ASIDE: I am aware that many people don't like using the "public" role to set permissions. This is just my tinkering time; in final design I'm sure we'll have several flexible (custom) database roles. I'm just trying to figure out the behavior I'm seeing, so please no "don't do that!" answers.
UPDATE: Apparently I know just enough SQL Server to be a danger to myself and others. In setting permissions (as I said, "among others"), I had DENY CONTROL. When I set this permission, I think I tried to look up what it did, had a vague idea, and decided on DENY. I cannot currently recall why this seemed the thing to do, but it would appear that that was the reason I was getting permission failures. So I'm updating my question: can anyone explain the "CONTROL" permission, as it pertains to tables?
You only need to have SELECT rights. In raw SQL (see the "script" icon/button in your dialogue box), it's GRANT SELECT ON dbo.tblFoo to public. This is the only permission needed to view the data,
In this case, the error message explicitly mentions "deny". "DENY" is a right in itself, so it mentions it,
If you had no rights, you'd get the message (very approximately) "tblFoo does not exist or you do not have rights"
"DENY CONTROL" is mentioned here. In this case, you denied all rights to the public role.
The grantee effectively has all
defined permissions on the securable
Assuming "UserTest" is a domain user account, connect as a member of the sysadmin role and run
EXEC MASTER.dbo.xp_logininfo 'Domain\UserTest', 'all'
(substituting your domain name for "Domain")
this will display the Windows groups etc. that the account is inheriting security permissions from and the level of access, e.g. you would expect to see something like:
account name type privilege mapped login name permission path
domain\usertest user user domain\usertest BUILTIN\Users
This will help troubleshoot where the account is inheriting permissions from, e.g. which Windows groups it is part of that have permissions to the database. If this all looks OK then I would follow your own advice and not mess with the public role.
Create a database role in your
database
Assign explicit permissions for that
role
Create a server login for your user
account
Open the server login, go to the
User Mapping section, click on the
database and select the database
role you created

Resources