Error dropping or deleting a user from SQL Server 2012 - sql

I'm trying to drop all the logins from SQL server except the default built-in SQL server logins but I'm unable to drop the <domain>\administrator account. It gives me following error:
Server principal '<domain>\administrator' has granted one or more
permission(s). Revoke the permission(s) before dropping the server
principal.
I tried checking the permission assigned to this user using this query :
Select *
from sys.server_permissions
where grantor_principal_id =
(Select principal_id
from sys.server_principals
where name = N'<domain>\administrator')
This query returns only one record corresponding to an end-point as below:
class class_desc major_id minor_id grantee_principal_id grantor_principal_id type permission_name state state_desc
105 ENDPOINT 65536 0 269 259 CO CONNECT G GRANT
But when I try to check the rights assigned to this user on all of the existing end-points, I find none have any kind of permissions for the user I'm trying to delete.
I'm not sure what is happening and where to look for to drop this user.

I was able to solve this issue. There were following issues which were not allowing me to drop the <Domain>\administrator login from SQL server:
Owner of ReportServer and ReportServerDB databases was <Domain>\administrator user
Owner of ConfigMgrEndPoint end-point was also <Domain>\administrator user.
I changed the ownership of all the above mentioned SQL objects. I made sa user as their new owner. Then I was successfully able to drop the <Domain>\administrator user. I also got following expert comment from one of my colleagues who was helping me with this issue :
Keeping [sa] as a default owner for most sql objects is a standard
practice. Making a domain user as owner of SQL objects can affect the
working later on if that user no longer exists or is disabled in the Active Directory at any point of time

to find out what are the permissions that are preventing the dropping of the login
I am using this script:
SELECT ##SERVERNAME,##SERVICENAME
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DECLARE #GrantorName nvarchar(4000)
SET #GrantorName = 'xxx\the_login' /* Login in Question */
SELECT b.name as Grantor
, c.name as Grantee
, a.state_desc as PermissionState
, a.class_desc as PermissionClass
, a.type as PermissionType
, a.permission_name as PermissionName
, a.major_id as SecurableID
FROM sys.server_permissions a
JOIN sys.server_principals b
ON a.grantor_principal_id = b.principal_id
JOIN sys.server_principals c
ON a.grantee_principal_id = c.principal_id
WHERE grantor_principal_id =
(
SELECT principal_id
FROM sys.server_principals
WHERE name = #GrantorName
)
and sometimes this one:
--Check to see if they own the endpoint itself:
SELECT SUSER_NAME(principal_id) AS endpoint_owner ,name AS endpoint_name
FROM sys.database_mirroring_endpoints;
--If so, you'll need to change the endpoint owner. Say the endpoint is called Mirroring, and you want to change the owner to SA:
--ALTER AUTHORIZATION ON ENDPOINT::Mirroring TO sa;
or following these instrustions:
--1) Check to see if this logon only has server level permissions and check to see
--if this login has granted permissions to another server principal.
--Use this query to identify the permissions granted.
Select perm.* from sys.server_permissions perm
INNER JOIN sys.server_principals prin ON perm.grantor_principal_id = prin.principal_id
where prin.name = 'xxx\the_login' /* Login in Question */
--2) The permissions granted will need to be revoked , to allow the DROP LOGIN to complete.
--The permissions can be granted again by a suitable LOGIN.
there is also a very nice article related to this:
Drop Login issues for logins tied to SQL Server Availability Groups

You'll have to check for "server permissions" and "explicit permissions".

Related

Azure SQL Database User Not Inheriting Role Permissions

I have created contained database roles in an Azure SQL database, granted permissions to the roles, and created database users mapped to Azure Active Directory, and added the database users to the applicable roles. However, the users don't appear to be automatically inheriting the permissions of the roles (I've confirmed they were successfully added). Am I missing a step?
CREATE USER [User.Name#Company.com] FROM EXTERNAL PROVIDER
ALTER ROLE [DATABASE-ROLE] ADD MEMBER [User.Name#Company.com]
Note: The roles have Select and View Definition permissions, but the users are only showing Connect permissions.
I have the same issue. I run ran the command as below to create a role which has select permission and assign the role to a Azure AD user.
CREATE ROLE testrole AUTHORIZATION [dbo]
GO
-- Grant access rights to a specific schema in the database
GRANT
SELECT,
VIEW DEFINITION
ON SCHEMA:: [dbo]
TO testrole
GO
create user [jim#hanxia.onmicrosoft.com] from EXTERNAL PROVIDER
GO
ALTER ROLE testrole ADD MEMBER [jim#hanxia.onmicrosoft.com]
GO
Then I run the command :
SELECT p.NAME
,m.NAME
FROM sys.database_role_members rm
JOIN sys.database_principals p
ON rm.role_principal_id = p.principal_id
JOIN sys.database_principals m
ON rm.member_principal_id = m.principal_id
GO
SELECT DISTINCT pr.principal_id, pr.name, pr.type_desc,
pr.authentication_type_desc, pe.state_desc, pe.permission_name
FROM sys.database_principals AS pr
JOIN sys.database_permissions AS pe
ON pe.grantee_principal_id = pr.principal_id;
It shows that I have assigned the role to the user ans the use only has connect permission.
But I run the command:
EXECUTE AS user = 'jim#hanxia.onmicrosoft.com'
select * from student
It shows that the user has select permission.
So I think Transact-SQL support Azure AD user in Azure SQL database is not perfect. Is that right? Can someone explain it?

SQL Server : permissions to only allow execute on some stored procedures

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';

SQL User Cannot Select Objects from sysobjects where UID = User

I'm working with a legacy system that attempts to execute schema changes in SQL for specific users by first querying sysobjects as that user to determine if the object exists. If it does it creates an ALTER VIEW statement otherwise it creates a CREATE VIEW statement. In this case the view exists, but the query continues to fail to list the object.
For example:
setuser 'APPLICATION_DEV'
Select * from sysobjects o, sysusers u
where u.uid = o.uid
and u.name = N'APPLICATION_DEV'
The problem is that certain accounts in this database can run this query without error and it returns all of the objects owned by that user. Other accounts however get no records returned by this query. If I setuser to SA and run the query all of that users objects appear. The affected user is the owner of the schema and has create view permissions on the schema. I cannot find any differences in permissions between a working user and a non-working user account.
Is there a permission that I am missing that would restrict a user from querying their own objects in sysobjects?
Yes, I know sysobjects is obsolete, but I have no control over the actual code here and instead have to fix the database so their code will work as expected.
EDIT: Additional findings.
To complicate matters I can run this succesfully:
setuser 'APPLICATION_DEV'
Select * from sysusers
Where name = 'APPLICATION_DEV'
I can also execute this succesfully:
setuser 'APPLICATION_DEV'
Select * from sysobjects
Where uid = 308 --308 is the uid of the APPLICATION_DEV user
However, when I use a join either in the where clause or via INNER JOIN I then get no records. What would restrict my access to records purely based on the join? Index permissions?? I'm baffled.
For the particular user in user mapping check whether you have checked all the checkboxes apart from db_denydatareader and db_denydatawriter.
also check this
The SELECT permission was denied on the object 'sysobjects', database 'mssqlsystemresource', schema 'sys'
http://social.msdn.microsoft.com/Forums/en/sqlsecurity/thread/a2befd20-2a9b-4a60-95a9-3a80a1a99ea1

How to check if the USER is already created in the database or not in SQL?

Is there is a way that from it I can know if the user(not the login) is already created in the database? I mean the user not the login, since, I know how to check for the login. I need to check for the user that is created inside a specific DB & a role assigned to it.
This is the code for checking for the login:
SELECT name FROM sys.server_principals WHERE name = 'test_user'
but how about the user? Since I need to create the user and assign a role to it if its not created. Otherwise, I will continue without creating.
Thanks
How about:
USE (your database you want to check the user's existence in)
SELECT *
FROM sys.database_principals
WHERE name = '(your user name to check here)'
sys.server_principals shows you the logins defined on the server level - sys.database_principals shows you the principals (e.g. user accounts) on a database level.
This will tell you the matching user name for a given login name
USE MyDB
SELECT
sp.name AS ServerLoginName,
dp.name AS DBUserName
FROM
sys.server_principals sp
LEFT JOIN
sys.database_principals dp ON sp.sid = dp.sid
WHERE
sp.name = 'MyLogin'
use SomeDatabase
go
/* built-in system function */
select database_principal_id('UserNameHere')
/* check if exists and drop */
if database_principal_id('UserNameHere') is not null
drop user 'UserNameHere'
go
If you've found sys.server_principals, I'm surprised you haven't found sys.database_principals. You can join the views based on the sid column.
You might care for this method as well...
IF DATABASE_PRINCIPAL_ID('domain\lanid') IS NULL
BEGIN
CREATE USER [domain\lanid] FOR LOGIN [domain\lanid] WITH DEFAULT_SCHEMA=[dbo]
EXEC sp_addrolemember N'db_ApplicationUserRole', N'domain\lanid'
END

SQL Server: How to check if a windows user exists in the database but under a different user name

I am trying to create a user via a T-SQL script in SQL Server 2005/2008. I run the following SQL to check if the user exists and create the user if it does not:
IF NOT EXISTS (SELECT *
FROM sys.database_principals
WHERE name = N'MyDomain\MyUser')
BEGIN
CREATE USER [MyDomain\MyUser] FOR LOGIN [MyDomain\MyUser] WITH default_schema=[dbo];
SELECT 1;
END
ELSE
BEGIN
SELECT 0;
END
Unfortunately, this does not work when the windows account MyDomain\MyUser is already in the database but under a different name. An example of this would be if MyDomain\MyUser was the account that created the database then it will already be in the database under the dbo user. When this is the case I get the following error:
Msg 15063, Level 16, State 1, Line 1
The login already has an account under
a different user name.
How can I check if the windows user MyDomain\MyUser is already a user in the database even if it is under a different user name?
Do the testing for windows user vs sys.database_principals using the SID rather than the name/user_id:
select * from sys.database_principals where sid = SUSER_SID(N'MyDomain\MyUser')
Since this uses the SID of the login ID, it doesn't matter what name it was mapped to in the database.