我正在尝试寻找或设计一种方法,让开发人员团队能够修改 SQL 代理作业步骤和计划,但这不涉及开发人员的系统管理员权限。由于我无法将代理作业的所有权分配给组,因此我需要某种解决方法。
到目前为止,我想到了以下想法
- 创建服务器登录名和 MSDB 和 Master 中的匹配用户。使用此帐户拥有代理作业。要允许修改,请向包含开发人员的组授予对 [msdb].[dbo].sp_update_job、sp_update_jobstep 和 sp_update_jobschedule 的 EXECUTE 权限。
这使得他们能够使用 MSDB 存储过程提交对任何代理作业的修改
- 按照上述步骤创建一个登录名/用户,并使其成为所有代理作业的所有者。然后与开发人员分享密码。
由于不同的原因,这两种情况都不是特别安全,但我试图在安全团队的需求与开发人员执行其工作的能力之间取得平衡 - 因此我认为需要涉及一点实用主义。
有没有更好的方法来实现这一点?
答案1
我今天一直在研究这个问题,我解决这个问题的方法是使用 EXECUTE AS OWNER 在可信任的数据库中创建一个存储过程,其中所有者是 sa。我通过创建一个新的作业类别并将任何可编辑作业的类别设置为该类别来限制它的范围。然后我向开发人员授予此新存储过程的 EXECUTE 权限。
此存储过程会更改作业的所有者(例如,指定自己的姓名),然后他们可以编辑它。完成后,他们可以将所有者改回“sa”或之前的任何名称。
当然,它仍有被滥用的可能,因为开发人员可能会以某种恶意的方式编辑作业,然后将其设置为以 sa 身份运行。但这种情况或许可以通过审核谁在更改作业所有者以及新作业的定义是什么来缓解,这样就可以追究一些责任。
CREATE PROCEDURE dbo.UpdateJobOwner
@JobName NVARCHAR(128),
@NewOwner NVARCHAR(128)
WITH EXECUTE AS OWNER
AS
BEGIN
DECLARE @JobId UNIQUEIDENTIFIER;
DECLARE @result int;
-- Get the Job ID based on the provided Job Name
SELECT @JobId = job_id
FROM msdb.dbo.sysjobs sj
JOIN msdb.dbo.syscategories sc
ON sc.category_id = sj.category_id
WHERE sj.[name] = @JobName
AND sc.[name] = N'Editable Agent Jobs'
-- Check if the job exists
IF @JobId IS NOT NULL
BEGIN
-- Update the job owner
EXEC @result = msdb.dbo.sp_update_job
@job_id = @JobId,
@owner_login_name = @NewOwner;
IF (@result = 0) PRINT 'Job owner updated successfully.';
END
ELSE
BEGIN
PRINT 'Job not found. Please check the provided Job Name.';
END
END
GO
当然,“正确”的程序是不允许开发人员随时更换代理工作,并且任何更改都要经过变更控制流程。但这个世界并不完美,目前这对我来说已经足够了。