I'll preface this with I've never been in charge of database security and this is all really new to me, so forgive the question if it's bad - I'll try to provide as much information as possible. I've searched around without much detail on my specific question.
I'm using a SQL Server 2008 R2 database and I am in need of the ability to restrict all domain users to be able to only execute certain stored procedures when explicitly defined. As in, DENY select/update/delete/etc on ALL database tables/views/stored procedures, except for SOME stored procedures where defined explicitly (grant execute on stored procedure to USER (domain users below)).
I thought this would be pretty easy with server roles but it appears custom server roles are only available in SQL Server 2012 and up and the public server role grants select access on all of my tables. I read that deny always takes precedent over grant so I setup a database role that has select access set to deny, but users are still able to query the tables.
Here is my current setup on 1 server that contains 2 databases:
Server Level:
Logins: [Domain Users] - AD group login so all users can CONNECT to the server. Has server role Public.
Database Level:
Users: [Domain Users] - AD group so all users can CONNECT to the database.
Database Roles: [SP_Reader] - [Domain Users] as a role member. Securables I have all tables set to deny access on select and my stored procedures that I want users to execute set to grant on execute.
The problem is users are still able to select from my tables as if the permissions don't exist. Any idea what I'm doing wrong here?
The problem turned out to be the 'db_datareader' role was assigned to the database user in addition to my custom database role (SP_Reader) which provides only execute on certain stored procedures.
The 'db_datareader' role went unnoticed as I was querying 'sys.database_permissions' which doesn't display permissions that are implicitly granted.
I ended up finding this Microsoft link which provides a query that returns the members of all database roles:
SELECT DP1.name AS DatabaseRoleName,
isnull (DP2.name, 'No members') AS DatabaseUserName
FROM sys.database_role_members AS DRM
RIGHT OUTER JOIN sys.database_principals AS DP1
ON DRM.role_principal_id = DP1.principal_id
LEFT OUTER JOIN sys.database_principals AS DP2
ON DRM.member_principal_id = DP2.principal_id
WHERE DP1.type = 'R'
ORDER BY DP1.name;
Alternatively this internal stored procedure returns results for whichever role you pass as a parameter:
EXEC sp_helprolemember 'db_datareader';
Related
Trying to write an audit report for user permissions and access on a SQL Server 2012 database.
Using the following tables -
sys.database_role_members
sys.database_principals
sys.login_token
sys.database_permissions
sys.columns
sys.objects
Can get all the information required, except for the Login name associated with the database User.
Can anyone point me in the direction of where this information can be found?
Select ORIGINAL_LOGIN() as [Login]
The detailed info can be found here :
Microsoft ORIGINAL_LOGIN()
To add to your comment:
You can either restrict the user from accessing the database or not.
Same is applied to the server
SQL server does not provide you with the features to "Allow him/her to access the database, but if he/she does let me know"
In that case you would need to provide some custom functionality such as creating a job that executes the query :
select login_time,original_login_name,DB_NAME(database_id) from sys.dm_exec_sessions
where original_security_id <> 0x01
And depending on condition etc (User1 logged on DB1 at xx:xx:xx time) insert into table.
You should also take a look at Logon Triggers which could prevent users from logging under a certain conditions and then recording it Microsoft Logon Triggers if that is something you might want to consider
If I have two databases 'dbA' and 'dbB' using a normal account I know I can run a query such as
SELECT *
FROM dbA.dbo.TableA a
JOIN dbB.dbo.TableB b ON a.columnA=b.columnB
But I can not figure out how to grant permissions to a loginless account
USE dbA;
CREATE USER [test_user] WITHOUT LOGIN WITH DEFAULT_SCHEMA=[dbo]
GRANT SELECT ON DATABASE::dbA TO [test_user];
I receive an error when trying to give select permission to the loginless user 'test_user' on the other database.
GRANT SELECT ON DATABASE::dbB TO [test_user];
Is it possible to do a database join using loginless users? If so what should the grant statement look like for setting correct permissions?
A user without a login can only access other databases that have the guest user enabled. You might consider using a certificate-mapped user instead if you have a cross-database requirement. See http://www.sommarskog.se/grantperm.html for code.
Users exist at the database level. Only logins exist at the server level.
I believe you can create a view in dbA like so:
use dbA;
create view dbB_TableB as
select *
from dbB.dbo.TableB;
And you can then assign SELECT permissions for the user in dbA to the view.
I'm modifying an application that was designed to work with SQL Server databases to work with Azure SQL databases.
Most of the features and functions of the application appear to work well out of the box, or with minor tweaks but I've run into a snag with the following:
The application has an administration mode which allows a user to login using an account that has server admin rights and execute database updates when update patches are released. The application currently checks whether the user is in the sysadmin or serveradmin roles using the IS_SRVROLEMEMBER function.
However, on the SQL Azure instance, this method always returns 0, regardless of the user context I execute it under.
So the question is, how can I determine if the current login is an Azure server administrator? Or get a list of the Azure administrator logins (or logins and their roles on the server)?
I guess Azure database does not have server roles at all (it only has logins). Instead you should query master database for roles.
SELECT m.name as [Member]
, r.name as [Role]
FROM sys.database_role_members as drm
INNER JOIN sys.database_principals as m
on drm.member_principal_id = m.principal_id
INNER JOIN sys.database_principals as r
on drm.role_principal_id = r.principal_id
Make sure you execute it on master database. And remember you can not use "USE [dbname]" statement. "master" should be in your connection string.
more on logins in azure
server administrator permissions of Azure SQL Server and Azure SQL DW are not being reflected as database principals. instead, a logged-in admin user is the dbo user of the database.
so, in order to identify if the user is sysadmin or serveradmin all you have to do is to query SELECT current_user; and compare the result to dbo.
I am needing to update the password of one of the users in the database security folder in SQL Server 2012. Unfortunately, we do not have a DBA in-house and consequently needing some help. I've been told that I have sysadmin privileges on this SQL Server but I cannot find WHERE to update a user's password in the database. When I googled this, msdn show me how to update a login in the SQL Server 2012 box but this user is NOT listed under the Security\Logins folder in this server but this user is only under the database\Security\Users folder.
I had tried the ALTER LOGIN username WITH PASSWORD = 'password'; command but I only got this error:
Msg 15151, Level 16, State 1, Line 2
Cannot alter the login 'ATM', because it does not exist or you do not have permission.
Any help/direction would be appreciated. Thanks.
This is the difference between logins and users and how they relate to each other:
Logins - Instance level principals that allow an entity to connect to the SQL Server instance. They do not, by their nature, grant any access to databases on the instance. The exception to this is a login with sysadmin rights can use a database because they are sysadmin, but because of sysadmin level permissions.
Users - Database level principals that allow an entity to connect to a SQL Server database. Users are associated with logins via SIDs, creating a relationship between the two and allowing a login to connect to the instance and then use the associated user to connect to the database.
What commonly happens with SQL authenticated logins and database users on a restore is that the SIDS will be out of sync or a login will not exist for a user in the database, thus breaking the relationship. This relationship must be repaired before you can connect to the database using that login, because in the eyes of SQL Server those principals are no longer connected. If the login doesn't exist, you will have to first create it in order to associate it with the user:
--Windows login (Active Directory pass through)
CREATE LOGIN [DOMAIN\foo] FROM WINDOWS;
--SQL Authenticated
CREATE LOGIN [foo] WITH PASSWORD='5+r0ngP#55w0rd';
Once the login exists, associate it with the user:
ALTER USER [foo] WITH LOGIN=[foo]
You can use the following query in the context of your database to check for orphans:
select
dp.name [user_name]
,dp.type_desc [user_type]
,isnull(sp.name,'Orhphaned!') [login_name]
,sp.type_desc [login_type]
from
sys.database_principals dp
left join sys.server_principals sp on (dp.sid = sp.sid)
where
dp.type in ('S','U','G')
and dp.principal_id >4
order by sp.name
I'm trying to execute the following query through classic asp recordset -
SQL = "Select P_Name as P_Name, P_Description as P_Description
from L_PagePermission
inner join A_Permission on p_permissionID = pp_PermissionID
inner join A_Page on P_PageID = PP_PageID
where P_PageID = 85
order by p_Name"
Although I've ran into a problem with permissions. So the error that i am receiving is -
Microsoft OLE DB Provider for ODBC
Drivers error '80040e09'
[Microsoft][ODBC SQL Server
Driver][SQL Server]SELECT permission
denied on object 'A_Permission',
database 'HRWB_3_0', schema 'dbo'.
How would I go about executing this query without changing permission settings. How can I do this with a stored procedure? (Can someone provide an example too)
I can't change the database settings I have to deal with what I got. I've looked through a lot of the websites files and it seems to be mostly dependent on stored procedures.
You're not going to be able to get around that permissions error unless you grant select access on the L_PagePermission and A_Permission tables to the login that you are using to connect to the database, or unless you use a different login that already has select access to those tables.
Another approach would be to write a new stored procedure and grant EXECUTE access to that stored procedure. The SQL to grant permissions in either case is simple:
To grant SELECT access to a table:
GRANT SELECT ON [TableName] TO [loginName]
To grant EXECUTE access to a stored procedure:
GRANT EXECUTE ON [procedureName] TO [loginName]
One more approach that could work but has obvious security implications is to add the login you are using to the db_owner role for that database. That should work, but is NOT recommended unless you are comfortable with the security risks that presents.
If you don't have permission to select from the table, there won't be any way to work around the absence of permission other than connecting to the DBMS as a user who has permission to select from the table. That's the point of the permissions system - to prevent the unauthorized from doing what they are not allowed to do.