Drop Login issues for logins tied to SQL Server Availability Groups

By:   |   Updated: 2017-12-06   |   Comments (4)   |   Related: > Availability Groups


Problem

We always follow SQL Server security best practices when we grant Database Administrators (DBAs) sysadmin rights on production SQL Servers. We use a Domain Group and don't add individual logins to the sysadmins server role. The Domain Group is audited and we get alerts every time a member is added or removed to/from this group.

During our regular security reviews we have discovered that one of the SQL Servers with Availability Groups has an individual DBA's login in addition to the DBA group as a member of the sysadmin server role. The DBA is already a member of the DBA Domain group, so we are not sure why we had this login on SQL Server.

We have tried to remove the login, but couldn't remove it.

Solution

We suspect this is somehow related to the Availability Groups (AG) setup as this DBA was creating and configuring them.

We tried to remove the DBA's login as follow:

USE [master]
GO
DROP LOGIN [DOMAIN\DBAUser1]
GO   

But the login couldn't be deleted and we got the following error:

Server principal has granted one or more permission(s). Revoke the permission(s) before dropping the server principal.
Msg 15173, Level 16, State 1, Line 4
Server principal has granted one or more permission(s). Revoke the permission(s) before dropping the server principal.
 

Fixing SQL Server Permissions for Grant

First we need to find out what permissions the DBA was granted and to what login:

USE [master]
GO
SELECT pm.class, pm.class_desc, pm.major_id, pm.minor_id, 
   pm.grantee_principal_id, pm.grantor_principal_id, 
   pm.[type], pm.[permission_name], pm.[state],pm.state_desc, 
   pr.[name] AS [owner], gr.[name] AS grantee
FROM sys.server_permissions pm 
   JOIN sys.server_principals pr ON pm.grantor_principal_id = pr.principal_id
   JOIN sys.server_principals gr ON pm.grantee_principal_id = gr.principal_id
WHERE pr.[name] = N'DOMAIN\DBAuser1';   

The result shows that the DBA has granted CONNECT permissions to one of the endpoints.

SQL Server permissions granted by login

The query below displays which endpoint the DBA has granted permissions to:

USE [master]
GO
SELECT pm.class, pm.class_desc, pm.major_id, pm.minor_id, 
   pm.grantee_principal_id, pm.grantor_principal_id, 
   pm.[type], pm.[permission_name], pm.[state],pm.state_desc, 
   pr.[name] AS [owner], gr.[name] AS grantee, e.[name] AS endpoint_name
FROM sys.server_permissions pm 
   JOIN sys.server_principals pr ON pm.grantor_principal_id = pr.principal_id
   JOIN sys.server_principals gr ON pm.grantee_principal_id = gr.principal_id
   JOIN sys.endpoints e ON pm.grantor_principal_id = e.principal_id 
        AND pm.major_id = e.endpoint_id
WHERE pr.[name] = N'DOMAIN\DBAUser1';
SQL Server endpoint permissions granted

The endpoint's name is "Hadr_endpoint" which is the default name of the Availability Group (AG) endpoint. This confirms that login creation on this SQL Server is related to the AG setup.

We are going to change the owner of this endpoint to the renamed "sa" login ("rendba"):

USE [master]
GO
ALTER AUTHORIZATION ON ENDPOINT::Hadr_endpoint TO rendba;
GO   

Read this tip about securing the "sa" account (renaming it, etc.). Check this tip about issues when an endpoint owner is deleted.

Note that we have changed the ownership of the endpoint, but haven’t reassigned the granted permission (CONNECT to DOMAIN\SQL_AG1_Test-Svc). This permission was lost when we changed the owner of the endpoint. We are skipping this step in purpose to demonstrate the related error later.

Fixing SQL Server Ownership

So, we have reassigned the ownership of the AG endpoint. Let's try to drop the DBA's login again:

USE [master]
GO
DROP LOGIN [DOMAIN\DBAUser1]
GO
The server principal owns one or more availability group(s) and cannot be dropped
Msg 15141, Level 16, State 1, Line 4
The server principal owns one or more availability group(s) and cannot be dropped
   

As we can see from this error, the DBA owns one (or more) Availability Groups and we still not able to drop the login.

Let's get a list of Availability Groups owned by the login:

USE [master]
GO
SELECT ag.[name] AS AG_name, ag.group_id, r.replica_id, r.owner_sid, p.[name] as owner_name 
FROM sys.availability_groups ag 
   JOIN sys.availability_replicas r ON ag.group_id = r.group_id
   JOIN sys.server_principals p ON r.owner_sid = p.[sid]
WHERE p.[name] = 'DOMAIN\DBAUser1'
GO   
SQL Server Availalbility Group Name and owner

Now we will re-assign the AG's ownership to the renamed "sa" login:

USE [master]
GO
ALTER AUTHORIZATION ON AVAILABILITY GROUP::SQLAG1 TO rendba;
GO

When we've tried to drop the login on the secondary replica we get another error:

USE [master]
GO
DROP LOGIN [DOMAIN\DBAUser1]
GO
Login owns one or more database(s). Change the owner of the database(s) before dropping login.
Msg 15174, Level 16, State 1, Line 4
Login owns one or more database(s). Change the owner of the database(s) before dropping login.

This error looks more familiar. We need to change databases owner of these databases.

Let's find databases which have our DBA as an owner:

USE [master]
GO
SELECT [name] AS dbname FROM sys.databases WHERE SUSER_SNAME(owner_sid) = 'DOMAIN\DBAUser1'
GO

And change the owner of the AGTest (the database that was returned by the query above):

USE [AGTst]
GO
ALTER AUTHORIZATION ON DATABASE::AGTst TO rendba;
GO

Here is an error we get when we try to update the database owner on the secondary replica that is setup as read-only:

Failed to update database because the database is read-only
Msg 3906, Level 16, State 1, Line 51
Failed to update database because the database is read-only.

When the secondary replica is setup as non-readable you will get this error:

target database is participating in an availability group and is currently not accessible for queries
Msg 976, Level 14, State 1, Line 24
The target database is participating in an availability group and is currently not accessible for queries. Either data movement is suspended or the availability replica is not enabled for read access. To allow read-only access to this and other databases in the availability group, enable read access to one or more secondary replicas in the group.

In order to change the database owner on the secondary replica we have to make this database available for writes. It means we have to fail over the AG:

USE [master]
GO
ALTER AVAILABILITY GROUP SQLAG1 FORCE_FAILOVER_ALLOW_DATA_LOSS;  
GO

Now we can try to drop the DBA's login again:

USE [master]
GO
DROP LOGIN [DOMAIN\DBAUser1]
GO

"Side Effects"

At this point we are able to drop the DBA's login, but when you restart the SQL Server service you may get this error in SQL Server error log:

Connection handshake failed (error severity 10)
Connection handshake failed (error severity 10)

We get the same error when we check the AG state with sys.dm_hadr_availability_replica_state DMV:

SELECT agr.replica_server_name, 
   agr.[endpoint_url],
   agrs.connected_state_desc, 
   agrs.last_connect_error_description, 
   agrs.last_connect_error_number, 
   agrs.last_connect_error_timestamp 
FROM sys.dm_hadr_availability_replica_states agrs 
JOIN sys.availability_replicas agr ON agrs.replica_id = agr.replica_id
WHERE agrs.is_local = 1
SQL Server Availability Group replica state

Remember the permission we didn’t grant when we reassigned the endpoint’s ownership at the beginning of the tip?

To fix this error we need to grant this missing permission to the Service Account listed in the error:

USE [master]
GO
GRANT CONNECT ON ENDPOINT::Hadr_endpoint TO [DOMAIN\sql_service_account_test];
GO

One of the Next Steps

To make sure we catch these and other connection issues we will create alerts for severity 10 and 16 errors containing "Connection handshake failed" in error messages:

USE msdb 
GO
EXEC dbo.sp_add_alert @name=N'_Connection handshake failed Error: Sev 10', 
      @message_id=0, 
      @severity=10, 
      @enabled=1, 
      @delay_between_responses=120, 
      @include_event_description_in=1, 
      @event_description_keyword=N'Connection handshake failed'
GO
EXEC dbo.sp_add_alert @name=N'_Connection handshake failed Error: Sev 16', 
      @message_id=0, 
      @severity=16, 
      @enabled=1, 
      @delay_between_responses=120, 
      @include_event_description_in=1, 
      @event_description_keyword=N'Connection handshake failed'
GO
EXEC dbo.sp_add_notification @alert_name=N'_Connection handshake failed Error: Sev 10', 
      @operator_name=N'DBA_Operator', 
      @notification_method = 1
GO 
EXEC dbo.sp_add_notification @alert_name=N'_Connection handshake failed Error: Sev 16', 
      @operator_name=N'DBA_Operator', 
      @notification_method = 1
GO   

Here is an example of the email alert:

Alert email example for the connection error

All in one script

You may or may not have issues with databases ownership, so we haven't included the ownership changes step in this script.

USE [master]
GO
ALTER AUTHORIZATION ON ENDPOINT::Hadr_endpoint TO rendba;
GO 
GRANT CONNECT ON ENDPOINT::Hadr_endpoint TO [DOMAIN\sql_service_account_test];
GO
ALTER AUTHORIZATION ON AVAILABILITY GROUP::SQLAG1 TO rendba;
GO
DROP LOGIN [DOMAIN\DBAUser1]
GO

If you still can't drop the login because it owns databases you will need to re-assign the databases ownership. But keep in mind that the new owner could be different from "sa". This will depend on the application's security requirements.

Next Steps
  • Check out more security tips here.
  • Here is the link to the Microsoft resource about Security Catalog Views.
  • Read this tip about security audit/reviews.
  • This tip has scripts to help you with your security reviews.
  • Use this checklist to harden your new SQL Server security.
  • Find more information about setting up SQL Server alerts here.


sql server categories

sql server webinars

subscribe to mssqltips

sql server tutorials

sql server white papers

next tip



About the author
MSSQLTips author Svetlana Golovko Svetlana Golovko is a DBA with 13 years of the IT experience (including SQL Server and Oracle) with main focus on performance.

This author pledges the content of this article is based on professional experience and not AI generated.

View all my tips


Article Last Updated: 2017-12-06

Comments For This Article




Wednesday, July 31, 2024 - 9:00:30 AM - Danil Back To Top (92427)
Also you may need to reassign all jobs from user

View all user's jobs:

SELECT s.name AS JobName, l.name AS JobOwner
FROM msdb..sysjobs s
LEFT JOIN master.sys.syslogins l ON s.owner_sid = l.sid
WHERE l.name = N'domain\username'
ORDER by l.name

Change ownership:
USE msdb ;
GO
EXEC dbo.sp_manage_jobs_by_login
@action = N'REASSIGN',
@current_owner_login_name = N'domain\username',
@new_owner_login_name = N'sa';
GO

Wednesday, March 13, 2024 - 11:01:38 PM - Svetlana Golovko Back To Top (92068)
Good point. Yes, generally it's not a good idea to use this failover option. The assumption is that this is done during the outage with all applications disconnected and no activity on databases. To make sure it's safe is_failover_ready column of the sys.dm_hadr_database_replica_cluster_states DMV can be checked. If it's equal to 1 then there is no data loss with "FORCE_FAILOVER_ALLOW_DATA_LOSS" used.

Wednesday, September 20, 2023 - 9:28:43 AM - Wilfred van Dijk Back To Top (91582)
Is "ALTER AVAILABILITY GROUP SQLAG1 FORCE_FAILOVER_ALLOW_DATA_LOSS;" really a good idea? Will you lose data with this option?

Thursday, October 17, 2019 - 12:19:09 PM - atbin sadeghzadeh Back To Top (82810)

This Doc helped me a lot ... you saved me Svetlana,

Thanks !!















get free sql tips
agree to terms