There is a specific need to clean up logins from the SQL Servers after migration from one domain say abc
to new domain foo
.
After migration as we still have those old logins and users under naming of abc\login1, abc\login2… and so on.
How can I perform this clean up to delete all the logins from the server, which has Windows logins say with domain abc\..
and within same script to delete all the related users within the instance for all databases.
I've searched the link SQL Server script to delete accounts no longer in Active Directory but it does not help in deleting users.
Note: These are just Windows logins and not part of any AD group. Just want to drop logins and the db users associated with it. Other domain AD users have been taken care by our AD and wintel team and users are all set. Just doing the clean up here.
Best Answer
This is a much more complicated answer than you might expect. The high-level construct is pretty simple. In this order:
abc
domainabc
domainIt has to be in this order -- either one step of [all the database users from all the databases] and then one step of [all the logins], or repeated steps of [each login's database user] and then [each login]. One way to do this is using dynamic SQL, but the nested single quotes gut pretty ugly pretty fast. To drop the users inside each database:
Then to drop the logins at the server level:
There are complications, of course.
You might find that the above commands fail, for some or all users/logins. Reasons may vary. For example:
What if a database user was created from a Windows login, but without the
domain\login
convention? For example:In this case, because the server-level login doesn't have to exist first, you can't tell whether that login is from domain
abc
orfoo
. So, the important question here is:Is this database user safe to drop? Maybe you can determine this based on
create_date
ormodify_date
insys.database_principals
, some pattern in the aliased user name, or external documentation.What if a login owns/controls objects? schemas? jobs? databases? Example:
All of these things can block the attempt to drop either the database user or the server-level login. I can't drop
login2
from the server because they own a database and a job. I can't droplogin3
from the database because they own a schema.When I try to drop the login
abc\login2
:If the login doesn't own a database but owns a job:
If I try to drop the user
abc\login3
:So, the important question here is:
What must I do to drop this login?
You must first:
Drop the server-level login.
.
All of which isn't hard, for this one account. What if you have 50 or 100 of these, across 50 or 100 databases?
We need to extend our script.
First, before we drop a user from the database, we need to switch any of their schemas to someone else (let's say
dbo
for simplicity):For logins, we need to transfer databases and jobs to a different owner, let's say
sa
(again, for simplicity):That is not exhaustive. There are probably other security-related things that can prevent a user or login from being dropped, but those are the main ones I could think of.
And again, if you have the scenario above where you have a user in a database that is mapped to a server-level domain login but the user name does not contain the domain name prefix, you're going to have to add rules to capture them.