允许 Windows AD 组拥有 SQL 作业

Posted

技术标签:

【中文标题】允许 Windows AD 组拥有 SQL 作业【英文标题】:Allow Windows AD group to own a SQL job 【发布时间】:2022-01-22 17:27:18 【问题描述】:

SQL 代理作业位于用户级别之上,需要为所有者分配登录名。但它不会将组登录作为可接受的参数。我需要使用 Windows AD 组作为所有者,因为我有不同的 SQL 用户,其中一些用户应该只看到特定的作业。现在我已经使用 SQLAgentUserRole 为每个用户创建了单独的作业,这肯定不好,并且数据库中充满了 1:1 的作业,每个作业都有不同的所有者,以避免看到其他作业。

全图: 假设我在数据库中有 10 个不同的工作。其中一项作业名为 UserJob。我希望特定用户在连接到数据库并展开作业部分以仅查看名为“UserJob”的作业并能够启动它。我不需要通过存储过程等。我只需要通过 SSMS 启动作业(右键单击,启动作业,如果需要,输入参数)。谢谢。

【问题讨论】:

我能想到的解决你问题的唯一方法是更新 SSMS 用于在 SQL 代理中选择作业的存储过程,我认为是 [msdb]. [Dbo]. [Sp_help_job] 我现在正在尝试这样做但没有成功:(它再次只显示了我拥有的工作。 也许你可以检查RLS,我知道这并不容易,但它可能是一个线索 【参考方案1】:

根据the docs SSMS 检查以下数据库角色中的用户成员身份以显示 SQL Server 代理树节点:

SQLAgentUserRole SQLAgentReaderRole SQLAgentOperatorRole

我使用 SQL Server Profiler 来查找当您第一次在对象浏览器中连接到数据库并展开各种节点时执行了哪些查询。

对于 SQL Server 代理,它使用SELECT * FROM msdb.dbo.sysjobs_view 视图列出作业。此视图可以修改。

变化

    在 msdb 数据库中创建一个新的数据库角色。我称之为“CustomJobRole”。 然后我创建了一个名为“TestJob”的新作业(我假设您已经有一个作业) 创建一个应该只能查看和运行“TestJob”的低权限用户。 将此用户添加到“CustomJobRole”和“SQLAgentReaderRole”和/或“SQLAgentOperatorRole”(有关详细信息,请参阅上面链接的文档) 修改sysjobs_view如下:

(见代码中的 cmets)

ALTER VIEW sysjobs_view
AS
SELECT jobs.job_id,
       svr.originating_server,
       jobs.name,
       jobs.enabled,
       jobs.description,
       jobs.start_step_id,
       jobs.category_id,
       jobs.owner_sid,
       jobs.notify_level_eventlog,
       jobs.notify_level_email,
       jobs.notify_level_netsend,
       jobs.notify_level_page,
       jobs.notify_email_operator_id,
       jobs.notify_netsend_operator_id,
       jobs.notify_page_operator_id,
       jobs.delete_level,
       jobs.date_created,
       jobs.date_modified,
       jobs.version_number,
       jobs.originating_server_id,
       svr.master_server
FROM msdb.dbo.sysjobs as jobs
  JOIN msdb.dbo.sysoriginatingservers_view as svr
    ON jobs.originating_server_id = svr.originating_server_id
  --LEFT JOIN msdb.dbo.sysjobservers js ON jobs.job_id = js.job_id
WHERE 
    -- Custom: Add Condition for your Custom Role and Job Name
    ( (ISNULL(IS_MEMBER(N'CustomJobRole'), 0) = 1) AND jobs.name = 'TestJob' )
    OR (owner_sid = SUSER_SID())
   OR (ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0) = 1)
   -- Custom: In order for users to be able to see and start Jobs they have to be members of SQLAgentReaderRole/SQLAgentOperatorRole
   -- but these roles gives them ability to see all jobs so add an exclusion
   OR ( ISNULL(IS_MEMBER(N'SQLAgentReaderRole'), 0) = 1 AND ISNULL( IS_MEMBER(N'CustomJobRole'), 0 ) = 0 ) 
   OR ( (ISNULL(IS_MEMBER(N'TargetServersRole'), 0) = 1) AND
        (EXISTS(SELECT * FROM msdb.dbo.sysjobservers js 
         WHERE js.server_id <> 0 AND js.job_id = jobs.job_id))) -- filter out local jobs

注意:注释掉的LEFT JOIN是原始代码,与解决方案无关。

总结

这种方法很“hacky”,因为它只修改了某些用户的作业列表,实际上并没有阻止他们通过代码运行其他作业,换句话说,这不提供任何安全性,只是提供干净 UI 的便利。实现很简单,但显然不可扩展:作业名称是硬编码的,并且使用了否定成员身份(即AND ISNULL( IS_MEMBER(N'CustomJobRole'), 0 ) = 0)。 IMO,它是最简单、最可靠(副作用最小)的方法。

测试于

SSMS v18.9.2 + SQL Server 2014 SP3

编辑作业步骤解决方法

除非您是作业所有者或系统管理员,否则无法修改作业步骤。 解决此问题的一种甚至更“hacky”的方法是创建一个表,该表将保存所有输入参数并为用户提供对该表的插入/更新访问权限。然后您的 SP 可以从该表中读取参数。用户应该很容易右键单击 -> 在表格上编辑和修改数据。

对于表结构,我建议如下:

假设您的参数相对较少,我建议您为每个参数创建一列。这样你就可以为每个正确的数据类型 参数。 向表中添加插入/删除后触发器以确保 该表始终只有一行数据。

【讨论】:

Alex,你太棒了,这是非常好的举动。 + 真的很好的解释!!这正是我想要的。谢谢!非常感谢! 亚历克斯,最后一件事...由于作业通过这种方式在其中包含参数,我看到作业中的按钮变灰,我无法单击并设置参数;(我已阅读可以修改作业的用户必须是系统管理员的互联网。任何建议如何继续并仍然保留 SSMS 的 UI? 我看不出有什么办法。 SSMS 执行一个简单的查询select is_srvrolemember('sysadmin') * 1 +is_srvrolemember('serveradmin') * 2 ... 以获取所有服务器级别的权限,其余逻辑在 SSMS 中实现。一种更“hacky”的方法是创建一个包含所有输入参数并允许用户访问该表的表。然后您的 SP 可以从该表中读取参数。用户应该能够轻松地右键单击 -> 在表格上编辑并修改数据。

以上是关于允许 Windows AD 组拥有 SQL 作业的主要内容,如果未能解决你的问题,请参考以下文章

vCenter 6.5U1 Windows SQL Server 2012 安装

linux基础8

Azure AD B2C 是不是允许组层次结构?

linux第三课

Linux入门笔记3

linux日常笔记3