由于不匹配的SID导致程序集部署失败

时间:2017-06-29 21:43:03

标签: sql-server security sqlclr database-security

数据库名称和登录在以下内容中是匿名的。有一些答案 在SO上与这种情况类似,但不完全相同,因此我的问题。

尝试将程序集部署到生产数据库FOO_PROD失败,并显示消息:

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.

实际上,以下两个查询证明了SID的不同之处。 首先,我们来看看FOO_PROD的SID:

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'

显示结果:

SID,                                                             LoginName

0x010500000000000515000000C4B7E63D99D15C20332A47A24B100000,      BATZ\boink

其次,我们在master数据库中查看FOO_PROD的SID:

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'

显示结果:

SID,      LoginName

0x01,   [sa]

我们注意到,就像Visual Studio抱怨的那样,SID确实没有 比赛。它们必须匹配才能继续(显然)。

约束:由于其他几个系统,无法更改FOO_PROD上的SID 使用数据库期望它具有当前具有的SID和LoginName。

问题1:解决方案是否更改主数据库上的SID,LoginName?将 这样做会伤害什么或者是个坏主意吗?

假设您回复说可以在master上更改SID,LoginName,然后, 如何更改“主”数据库?好吧,我 以前没做过,但可以在这里找到候选解决方案和评论: The database owner SID recorded in the master database differs from the database owner SID

但是,这种情况与上面链接中提到的情况不同,我 认为,改变必须发生在主数据库ala上:

  exec sp_changedbowner [BATZ\boink]

问题2:这是正确的方法吗?

当然,如果对master数据库进行此类更改,我将与利益相关方核实 导致意想不到的结果,但我希望在此之前得到一些指导 检查一下。

根据@ srutzky的更新答案进行更新:

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

返回:

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

然后

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

返回:

  sid,  name
  0x01, sa

2 个答案:

答案 0 :(得分:2)

是的,SID确实需要匹配,因为不匹配表明可能有害的数据库被恢复到实例;这是一个安全保护。

但是,首先我们需要确切地知道我们正在看什么。虽然FOO_PROD中的记录与master中的记录(因此错误消息)之间的所有者SID肯定不匹配,但您的查询不会查看FOO_PROD中的值。您的两个查询分别针对master的所有者FOO_PROD以及master(再次)针对master的所有者(此处完全不相关)查看值

第1步

不要将sys*个对象用于任何内容,因为它们是兼容性视图,因此为SQL Server 2000编写的旧内容仍然可用(dbo.sys*中的msdb表仍然有效)。从SQL Server 2005开始,只应使用sys.*个对象(无需指定master.)。意思是,使用:

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

第2步

您需要检查数据库本身的值 IN ,因为它记录了所有者的SID,而不是sys.databases(或者甚至是master..sysdatabases)。在检查数据库所有者的值时,您需要在sys.database_principals中查找dbo用户,如下所示:

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

第3步

如果您使用的是SQL Server 2005,则需要使用sp_changedbowner,但从SQL Server 2008开始,不推荐使用存储过程而使用较新的ALTER AUTHORIZATION(尽管它仍然有效)。但是,是的,这是使它们相同的方式,因为它将两个位置同步到您指定的任何一个登录。

但是,您需要确保BATZ\boink是SQL Server实例所属域的有效Windows登录,并且此特定Windows登录的SID为0x010500000000000515000000C4B7E63D99D15C20332A47A24B100000。如果登录不存在,希望您能够通过CREATE LOGIN创建。

答案 1 :(得分:1)

由于数据库中的所有者是SA,并且您想要将Master中记录的所有者更改为SA,只需运行

alter authorization on database::[foo_prod] to sa