允许 Windows 个 AD 组拥有 SQL 个作业
Allow Windows AD group to own a SQL job
SQL 代理作业位于用户级别之上,需要将登录名分配给所有者。但它不将组登录作为可接受的参数。我需要使用 Windows 广告组作为所有者,因为我有不同的 SQL 用户,其中一些用户应该只能看到特定的工作。就像现在一样,我使用 SQLAgentUserRole 为每个用户创建了单独的作业,这肯定不好,并且数据库中充满了 1:1 个作业,每个作业都有不同的所有者以避免看到其他作业。
全貌:
假设我在数据库中有 10 个不同的工作。其中一个作业名为 UserJob。我希望特定用户在连接到数据库时展开作业部分以仅查看名为“UserJob”的作业并能够启动它。我不需要通过存储过程等。我只需要通过 SSMS 启动作业(右键单击,启动作业,如果需要,输入参数)。谢谢
根据 the docs SSMS 检查以下数据库角色中的用户成员身份以显示 SQL 服务器代理树节点:
- SQL代理用户角色
- SQLAgentReaderRole
- SQL代理操作员角色
我使用 SQL Server Profiler 来查找当您第一次在对象浏览器中连接到数据库并展开各种节点时执行的查询。
对于 SQL 服务器代理,它使用 SELECT * FROM msdb.dbo.sysjobs_view
视图列出作业。此视图可以修改。
变化
- 在 msdb 数据库中创建一个新的数据库角色。我称之为“CustomJobRole”。
- 然后我创建了一个名为“TestJob”的新工作(我假设您已经有一个工作)
- 创建一个应该能够看到并且运行 只能看到“TestJob”的低权限用户。
- 将此用户添加到“CustomJobRole”和“SQLAgentReaderRole”and/or“SQLAgentOperatorRole”(有关详细信息,请参阅上面的链接文档)
- 修改
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
为原代码,与解决方案无关
总结
这个方法是“hacky”,因为它只修改特定用户的工作列表,实际上并没有阻止他们通过代码 运行ing 其他工作,换句话说,这不提供任何安全性,只是清洁方便 UI。实现很简单,但显然不可扩展:作业名称是硬编码的,并且使用了负成员资格(即 AND ISNULL( IS_MEMBER(N'CustomJobRole'), 0 ) = 0
)。 IMO,尽管它是最简单和最可靠(副作用最小)的方法。
测试于
SSMS v18.9.2 + SQL 服务器 2014 SP3
编辑作业步骤解决方法
除非您是作业所有者或系统管理员,否则无法修改作业步骤。
一种更“hacky”的解决此问题的方法是创建一个 table 来保存所有输入参数并为用户提供 insert/update 访问此 table 的权限。然后您的 SP 可以从这个 table 中读取参数。用户应该很容易右键单击 -> 在 table 上编辑并修改数据。
对于 table 结构,我建议如下:
- 假设您的参数相对较少,我建议您为每个参数创建一列。这样你就有了正确的数据类型
参数.
- 向 table 添加插入/删除后触发器以确保
table 总是只有一行数据。
SQL 代理作业位于用户级别之上,需要将登录名分配给所有者。但它不将组登录作为可接受的参数。我需要使用 Windows 广告组作为所有者,因为我有不同的 SQL 用户,其中一些用户应该只能看到特定的工作。就像现在一样,我使用 SQLAgentUserRole 为每个用户创建了单独的作业,这肯定不好,并且数据库中充满了 1:1 个作业,每个作业都有不同的所有者以避免看到其他作业。
全貌: 假设我在数据库中有 10 个不同的工作。其中一个作业名为 UserJob。我希望特定用户在连接到数据库时展开作业部分以仅查看名为“UserJob”的作业并能够启动它。我不需要通过存储过程等。我只需要通过 SSMS 启动作业(右键单击,启动作业,如果需要,输入参数)。谢谢
根据 the docs SSMS 检查以下数据库角色中的用户成员身份以显示 SQL 服务器代理树节点:
- SQL代理用户角色
- SQLAgentReaderRole
- SQL代理操作员角色
我使用 SQL Server Profiler 来查找当您第一次在对象浏览器中连接到数据库并展开各种节点时执行的查询。
对于 SQL 服务器代理,它使用 SELECT * FROM msdb.dbo.sysjobs_view
视图列出作业。此视图可以修改。
变化
- 在 msdb 数据库中创建一个新的数据库角色。我称之为“CustomJobRole”。
- 然后我创建了一个名为“TestJob”的新工作(我假设您已经有一个工作)
- 创建一个应该能够看到并且运行 只能看到“TestJob”的低权限用户。
- 将此用户添加到“CustomJobRole”和“SQLAgentReaderRole”and/or“SQLAgentOperatorRole”(有关详细信息,请参阅上面的链接文档)
- 修改
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
为原代码,与解决方案无关
总结
这个方法是“hacky”,因为它只修改特定用户的工作列表,实际上并没有阻止他们通过代码 运行ing 其他工作,换句话说,这不提供任何安全性,只是清洁方便 UI。实现很简单,但显然不可扩展:作业名称是硬编码的,并且使用了负成员资格(即 AND ISNULL( IS_MEMBER(N'CustomJobRole'), 0 ) = 0
)。 IMO,尽管它是最简单和最可靠(副作用最小)的方法。
测试于
SSMS v18.9.2 + SQL 服务器 2014 SP3
编辑作业步骤解决方法
除非您是作业所有者或系统管理员,否则无法修改作业步骤。 一种更“hacky”的解决此问题的方法是创建一个 table 来保存所有输入参数并为用户提供 insert/update 访问此 table 的权限。然后您的 SP 可以从这个 table 中读取参数。用户应该很容易右键单击 -> 在 table 上编辑并修改数据。
对于 table 结构,我建议如下:
- 假设您的参数相对较少,我建议您为每个参数创建一列。这样你就有了正确的数据类型 参数.
- 向 table 添加插入/删除后触发器以确保 table 总是只有一行数据。