允许Windows AD组拥有SQL作业



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

整体情况:假设我在数据库中有10个不同的作业。其中一个作业名为UserJob。当连接到数据库时,我想要特定的用户,并展开作业部分以只看到名为"的作业;UserJob";我不需要通过存储过程等来启动它。我只需要通过SSMS启动作业(右键单击,启动作业,如果需要,输入参数(。谢谢

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

  • SQLAgentUserRole
  • SQLAgentReaderRole
  • SQLAgentOperator角色

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

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

更改

  1. 在msdb数据库中创建一个新的数据库角色。我称之为";CustomJobRole">
  2. 然后我创建了一个名为";TestJob">
  3. 创建一个应该只能看到并运行的低权限用户";TestJob">
  4. 将该用户添加到";CustomJobRole;以及";SQLAgentReaderRole";和/或";SQLAgentOperator角色";(有关详细信息,请参阅上面链接的文档(
  5. 修改sysjobs_view如下:

(参见代码中的注释(

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是原始代码,与解决方案无关。

摘要

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

测试日期

SSMS v18.9.2+SQL Server 2014 SP3

编辑作业步骤解决方案

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

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

  • 假设您的参数相对较少,我建议您为每个参数创建一列。通过这种方式,您可以为每个参数
  • 向表中添加After Insert/Delete触发器以确保表总是只有一行数据

最新更新