1

Database names and logins are anonymized in what follows. There are some answers on SO that are similar to this situation, but not exactly the same, hence my question.

Attempting to deploy an assembly to production database FOO_PROD fails with message:

Msg 33009, Level 16, State 2, Line 17
The database owner SID recorded in the master database differs from the
database owner SID recorded in database 'FOO_PROD'. You should correct
this situation by resetting the owner of database 'FOO_PROD' using the
ALTER AUTHORIZATION statement.

Indeed, the following two queries demonstrate the difference in SID. First, we look at the SID of FOO_PROD:

SELECT  SD.[SID],
        SL.Name as [LoginName]
FROM  master..sysdatabases SD INNER JOIN master..syslogins SL
    on  SD.SID = SL.SID
WHERE  SD.Name = 'FOO_PROD'

which shows the result of:

SID,                                                             LoginName

0x010500000000000515000000C4B7E63D99D15C20332A47A24B100000,      BATZ\boink

Second, we look at the SID of FOO_PROD in the master database:

SELECT  SD.[SID],
        SL.Name as [LoginName]
FROM  master..sysdatabases SD INNER JOIN master..syslogins SL
    on  SD.SID = SL.SID
WHERE  SD.Name = 'master'

which shows the result of:

SID,      LoginName

0x01,   [sa]

We notice that indeed, just as Visual Studio complained, the SIDs do not match. They must be made to match in order to proceed (apparently).

Constraints: The SID on FOO_PROD cannot be changed because several other systems that use the database expect it to have the SID and LoginName it currently has.

Question 1: Is the solution then to change the SID, LoginName on the master database? Would it hurt anything or be a bad idea to do so?

Say you respond that it is ok to change the SID, LoginName on master, then, how does one make the change to the 'master' database? Well, I've not done it before, but candidate solutions and commentary can be found here: The database owner SID recorded in the master database differs from the database owner SID

However, this situation is different from those presented in the link above, I think, in that the change must happen to/on the master database ala:

  exec sp_changedbowner [BATZ\boink]

Question 2: Is that the correct way to do it?

Naturally I'll check with stakeholders if such a change to master database will cause undesired outcomes, but I hope to get some guidance here before I even check on that.

Update based on @srutzky's updated answer:

  -- Step 1
  SELECT sd.[name], sd.[owner_sid], sp.[name]
  FROM   sys.databases sd
  INNER JOIN sys.server_principals sp
          ON sp.[sid] = sd.[owner_sid]
  WHERE  sd.[name] = N'FOO_PROD';

returns:

  name, owner_sid,  name
  FOO_PROD, 0x010500000000000515000000C4B7E63D99D15C20332A47A24B100000, BATZ\boink

Then

  -- Step 2
  USE [FOO_PROD];
  SELECT dp.[sid], sp.[name]
  FROM   sys.database_principals dp
  INNER JOIN sys.server_principals sp
          ON sp.[sid] = dp.[sid]
  WHERE  dp.[name] = N'dbo';

returns:

  sid,  name
  0x01, sa
Joe
  • 965
  • 11
  • 16
  • What version of SQL Server are you using? And is the Windows login `BATZ\boink` a valid login for this instance, AND having an SID of `0x010500000000000515000000C4B7E63D99D15C20332A47A24B100000 ` ? – Solomon Rutzky Jun 29 '17 at 22:54
  • 2012. Yes BATZ\boink is a valid login and is indeed used by another vendor working in the same environment. – Joe Jun 29 '17 at 23:00

2 Answers2

2

Yes, the SIDs really do need to match as a mismatch is an indication of a potentially harmful DB being restored to the instance; this is a safe-guard.

BUT, first we need to know exactly what we are looking at. While there is definitely a mismatch in the owner SIDs between the record in FOO_PROD and the record in master (hence the error message), your queries are not looking at the value in FOO_PROD. Your two queries are looking at the value in master for the owner of FOO_PROD, and in master (again) for the owner of master (entirely irrelevant here), respectively.

Step 1

Do not use sys* objects for anything as those are compatibility Views so that older stuff written for SQL Server 2000 and prior still work (well, dbo.sys* tables in msdb are still valid). Starting with SQL Server 2005, only sys.* objects (no need to specify master.) should be used. Meaning, use:

SELECT sd.[name], sd.[owner_sid], sp.[name]
FROM   sys.databases sd
INNER JOIN sys.server_principals sp
        ON sp.[sid] = sd.[owner_sid]
WHERE  sd.[name] = N'FOO_PROD';

Step 2

You need to check the value IN the database itself for the owner's SID as it has it recorded, which is not in sys.databases (or even in master..sysdatabases). When checking the Database's value for it's owner, you need to look in sys.database_principals for the dbo User as follows:

USE [FOO_PROD];
SELECT dp.[sid], sp.[name]
FROM   sys.database_principals dp
INNER JOIN sys.server_principals sp
        ON sp.[sid] = dp.[sid]
WHERE  dp.[name] = N'dbo';

Step 3

Using sp_changedbowner is required if you are on SQL Server 2005, but starting with SQL Server 2008 that stored procedure is deprecated in favor of the newer ALTER AUTHORIZATION (though it still works). But yes, this is the way to make them the same as it will sync both locations to whichever Login you specify.

However, you need to make sure that BATZ\boink is a valid Windows Login for the domain that the SQL Server instance belongs to, AND that this particular Windows Login has an SID of 0x010500000000000515000000C4B7E63D99D15C20332A47A24B100000. If the Login does not exist, hopefully you will be able to create it via CREATE LOGIN.

Solomon Rutzky
  • 46,688
  • 9
  • 128
  • 171
  • Thanks, as usual @srutsky, for your help. Would altering the authorization, i.e., ownership, be orthogonal to the login BATZ\boink used by the other vendor I referenced in my other comment? That is my primary problem here. I have to ensure that software that the other vendor configured to expect the login BATZ\boink is not disrupted. I'll confirm everything with them of course regardless of answers here. – Joe Jun 29 '17 at 23:04
  • If the SIDs are the same in both DBs then it is a non-issue. It would only be a problem if the SID is different in one of the places that they are stored (i.e. master, database A, and database B). – Solomon Rutzky Jun 29 '17 at 23:05
  • And why does the `dbo` SID matter in the first place for these two different 3rd party vendors? That seems odd to me. Are they using database ownership chaining? – Solomon Rutzky Jun 29 '17 at 23:07
  • Well, the SID, LoginName tuples are as I've indicated in the answer. The SID, LoginName tuple is different in master than FOO_PROD – Joe Jun 29 '17 at 23:07
  • I don't mean the currently listed SIDs, I mean the SID associated with the `BATZ\boink` Login. As long as `BATZ\boink` = `0x010500000000000515000000C4B7E63D99D15C20332A47A24B100000 ` in all cases, then there is nothing to worry about. – Solomon Rutzky Jun 29 '17 at 23:08
  • Ok, that is what I thought you meant and I figured my comment would cement that and it did. Thanks so much. I'll have to check further with the other vendor to see what kind of dependency their configurations have: on ownership or on login to see if this change matters for them. From what I am gathering, it would seem not to matter. I just can't disrupt their configurations of third party software and I don't know exactly what they have done. Our systems are orthogonal otherwise, we just happen to work in the same SAP ecosystem on the same server. – Joe Jun 29 '17 at 23:09
  • Hold on. I just noticed a problem with your original research queries. I will update my answer and then you need to run another query before we can be certain. – Solomon Rutzky Jun 29 '17 at 23:14
  • Ok, thanks for that. Checking the column owner_sid on sys.databases for master and FOO_PROD reveal the same outcome. Thanks for being careful though, appreciate it a lot. – Joe Jun 29 '17 at 23:24
  • So, executing the alter authorization would only change the ownership, but not the login? Just being very redundant and careful here. (I am guessing they want to preserve the login - though I haven't yet double checked with them). – Joe Jun 29 '17 at 23:27
  • I just finished. Please review steps 1 and 2 carefully. The owner of the `master` DB was never part of this. And I am not sure of what you are getting at with that last question, but ALTER AUTHORIZATION just changes the owner record in `master` (i.e. in `sys.databases`) if need be, and in the database itself (i.e. in `sys.database_principals` for the `dbo` User) if need be. No changes are made to the Login (i.e. `sys.server_principals`). – Solomon Rutzky Jun 29 '17 at 23:39
  • Ok, thanks for the @srutsky. I am going to add an updated section to my question with the output of your updated answer shortly. – Joe Jun 29 '17 at 23:46
  • No problem, and sounds good. Also, just FYI, the 3rd to last character in my login is a `z`, not an `s`. I doesn't bother me that it is being misspelled, but functionally speaking, the system won't alert me to messages if it isn't spelled correctly. I am only getting the notifications now due to you posting on my answer and the O.P. of what is being commented on (question or answer) is always notified. ;-). – Solomon Rutzky Jun 29 '17 at 23:48
  • FYI, I updated my question with the results of step 1 and step 2. – Joe Jun 30 '17 at 00:02
  • I see that. So, same underlying value, but that is just coincidental. At least now we are looking at the correct thing now :-). And so yes, either `sp_changedbowner` or `ALTER AUTHORIZATION` will do the trick. But if I were you, I would get confirmation from the vendors as to why they need that specific owner as it seems suspicious to me. Ideally you would have the DB owned by a low-privileged User. Do these 2 DBs have `TRUSTWORTHY` set to `ON`? – Solomon Rutzky Jun 30 '17 at 00:11
  • FOO_PROD would have TRUSTWORTHY set to ON, though I could possibly get the asembly to work with EXTERNAL ACCESS. It does interact with the file system in one particular directory to write a csv and later, approximately 6 seconds later on average, to read a csv, its results, as part of the same procedure call. – Joe Jun 30 '17 at 00:41
  • What do you mean? Is it currently using `UNSAFE`? You should use the narrowest set of permissions possible, so if `EXTERNAL_ACCESS` works then by all means please use that. If `TRUSTWORTHY` is `ON` only to get the SQLCLR objects to work, and if this is your companies custom code, then you should instead sign the Assembly, create an Asymmetric Key from it (in `master`), create a Login from that Key, grant the Login `EXTERNAL ACCESS ASSEMBLY`, and then turn `TRUSTWORTHY OFF`. Please see the series I am writing on this: [Stairway to SQLCLR](http://www.sqlservercentral.com/stairway/105855/) – Solomon Rutzky Jun 30 '17 at 15:51
  • Yes, I plan to follow the security recommendations of your Stairway to SQLCLR article series once I actually go into production. – Joe Jul 03 '17 at 22:14
1

Since the owner in the database is SA, and you want to change the owner recorded in Master to SA, just run

alter authorization on database::[foo_prod] to sa
David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67