Thực thi quyền bị từ chối trên đối tượng sp_start_job


8

Tôi cần cho phép người dùng khởi động một công việc đại lý cụ thể mà không có bất kỳ khả năng nào để bắt đầu những công việc khác. Để thực hiện điều này, tôi đã tạo quy trình sau (đơn giản hóa):

ALTER PROCEDURE [dbo].[RunJob]
    @job_name nvarchar(200)
WITH EXECUTE AS 'sysadminaccount'
AS
BEGIN
    --SET NOCOUNT ON;
    BEGIN TRY
        EXEC msdb.dbo.sp_start_job @job_name = @job_name 

        -- Wait for job to finish
        DECLARE @job_history_id AS INT = NULL
        DECLARE @job_result AS INT = NULL

        WHILE 1=1
        BEGIN
            SELECT TOP 1 @job_history_id = activity.job_history_id
            FROM msdb.dbo.sysjobs jobs
            INNER JOIN msdb.dbo.sysjobactivity activity ON activity.job_id = jobs.job_id
            WHERE jobs.name = @job_name
            ORDER BY activity.start_execution_date DESC

            IF @job_history_id IS NULL
            BEGIN
                WAITFOR DELAY '00:00:01'
                CONTINUE
            END
            ELSE
                BREAK
        END

        -- Check exit code
        SET @job_result = (SELECT history.run_status
        FROM msdb.dbo.sysjobhistory history
        WHERE history.instance_id = @job_history_id)

        RETURN @job_result;

    END TRY
    BEGIN CATCH
        THROW;
        RETURN;
    END CATCH
END

Tuy nhiên, khi tôi gọi thủ tục này (đã xác minh nó đang chạy qua "sysadminaccount"), tôi nhận được thông báo lỗi sau:

Msg 229, Cấp 14, Trạng thái 5, Quy trình sp_start_job, Dòng 1 Quyền EXECUTE đã bị từ chối trên đối tượng 'sp_start_job', cơ sở dữ liệu 'msdb', lược đồ 'dbo'.

Tài khoản là một thành viên của vai trò sysadmin, vì vậy tôi hiểu rằng không nên có bất kỳ vấn đề nào khi bắt đầu công việc. Tôi đã xác minh rằng nó là thành viên của ba vai trò sqlagent trong msdb và tất cả các vai trò đó đều có quyền thực thi sp_start_job.

Làm cách nào tôi có thể cấp cho tài khoản này các quyền phù hợp? Có điều gì khác cần phải được thực hiện vì sự mạo danh?

Câu trả lời:


12

Tôi không thích TRUSTWORTHYtùy chọn này vì nó làm tăng đáng kể khả năng bạn tiếp xúc với nhiều thứ khác nhau. Như Remus giải thích trong câu trả lời này , nó về cơ bản nâng cao bất kỳ db_ownerđể sysadmin. Một số điều khác đáng đọc là một loạt bài về TRUSTWORTHYbởi Sebastian Meine , chủ đề BOL, và một bài viết KB (mặc dù các phần lắp ráp có thể không liên quan đến mình trong kịch bản này):

(Và có rất nhiều bài đăng khác trên mạng cảnh báo về việc sử dụng tài sản này một cách mù quáng - chỉ vì nó hoạt động và thật dễ dàng không có nghĩa đó là điều đúng đắn - thực tế sẽ khiến bạn nghi ngờ nhiều hơn nữa.) Vì vậy, tôi sẽ đề xuất một cách tiếp cận khác (và vẫn còn những cách khác, chẳng hạn như ký bằng chứng chỉ, nhưng điều này luôn hiệu quả với tôi):

  1. Tạo thủ tục trong msdb.
  2. Tạo người dùng cho người dùng này đăng nhập msdb:

    USE msdb;
    GO
    CREATE USER floobarama FROM LOGIN floobarama;
  3. Cấp cho người dùng thực thi đặc quyền trên thủ tục được lưu trữ:

    GRANT EXECUTE ON [dbo].[RunJob] TO floobarama;
  4. Kiểm tra nó - bằng cách gọi thủ tục từ cơ sở dữ liệu khác:

    USE tempdb;
    GO
    EXECUTE AS LOGIN = N'floobarama';
    GO
    EXEC msdb.dbo.RunJob @job_name = N'whatever';
    GO
    REVERT;

    Hoặc một thử nghiệm dễ dàng hơn, trong trường hợp bạn không muốn chạy bất kỳ công việc nào bây giờ và không muốn đợi cho đến khi người dùng này thực thi nó để tìm hiểu xem họ có đủ quyền truy cập vào msdb:

    USE msdb;
    GO
    CREATE PROCEDURE dbo.whatever
    WITH EXECUTE AS N'sysadminaccount'
    AS
    BEGIN
      SET NOCOUNT ON;
      SELECT [I am really...] = SUSER_SNAME();
    END
    GO
    GRANT EXECUTE ON dbo.whatever TO floobarama;
    
    USE tempdb;
    GO
    EXECUTE AS LOGIN = N'floobarama';
    GO
    EXEC msdb.dbo.whatever;
    GO
    REVERT;

    Kết quả sẽ là:

    I am really...
    ---------------
    sysadminaccount
  5. Xác thực rằng điều này không tiết lộ bất cứ điều gì khác msdbcho người dùng này:

    USE tempdb;
    GO
    EXECUTE AS LOGIN = N'floobarama';
    GO
    SELECT job_id FROM msdb.dbo.sysjobs;
    GO
    REVERT;

    Kết quả sẽ là ...

    Msg 229, Cấp 14, Trạng thái 5, Dòng 21
    Quyền CHỌN đã bị từ chối trên đối tượng 'sysjobs', cơ sở dữ liệu 'msdb', lược đồ 'dbo'.

    ... kể từ khi tạo người dùng trong cơ sở dữ liệu không cung cấp cho họ quyền tự động đối với mọi thứ trong cơ sở dữ liệu đó; bạn cần phải làm rõ ràng cho người dùng đó hoặc cho một vai trò hoặc nhóm mà họ tham gia (bao gồm public).


2

Không thể bình luận vì tôi không đủ điểm nên viết câu trả lời. Có vẻ như đây là vấn đề chuỗi sở hữu cơ sở dữ liệu chéo. Nếu quy trình này được tạo bên ngoài msdb thì không có quyền truy cập vào các đối tượng trong cơ sở dữ liệu được tham chiếu, ngay cả khi "EXECUTE AS" mạo danh người dùng là thành viên của vai trò sysadmin.

Vì vậy, giải pháp có thể là:

  1. Tạo cơ sở dữ liệu của bạn TRUSWORTHY:

    ALTER DATABASE dbname SET TRUSTWORTHY ON;
  2. Cho phép chuỗi quyền sở hữu cơ sở dữ liệu chéo cho cơ sở dữ liệu (có thể không cần thiết)

    ALTER DATABASE dbname SET DB_CHAINING ON;

làm cho cơ sở dữ liệu đáng tin cậy đã lừa Cảm ơn nhiều!
Mansfield

2
Tại sao không đề xuất tạo thủ tục trong msdb? Điều này có vẻ như tiếp xúc ít hơn nhiều so với những gì bạn đã đề nghị.
Aaron Bertrand

@AaronBertrand Tôi không đặc biệt muốn cấp cho người dùng cuối quyền truy cập vào msdb. Tôi đang đưa ra sự tiếp xúc nào khác bằng cách làm cho cơ sở dữ liệu đáng tin cậy?
Mansfield

2
Bạn có thể khá an toàn cho họ kết nối truy cập và các quyền chỉ trong thủ tục này. Họ sẽ không thể làm gì khác nếu không có quyền rõ ràng. @SebastianMeine đã viết một loạt tuyệt vời về TRUSTWORTHY: sqlity.net/en/1653/ Khăn sqlity.net/en/1701/ nam sqlity.net/vi/1710/ . - các bộ phận lắp ráp không có khả năng liên quan nhưng cũng kiểm tra hỗ trợ KB này . microsoft.com/kb/2183687 & dba.stackexchange.com/a/25894/1186
Aaron Bertrand

@AaronBertrand Aaron, bạn nói đúng. Việc triển khai phụ thuộc rất nhiều vào việc bạn cấp quyền cho người dùng 'không đáng tin cậy' để tạo / thay đổi các đối tượng trong cơ sở dữ liệu đáng tin cậy. Trong quá trình thực hiện tôi đã làm việc cho đến nay nó không phải là trường hợp, vì vậy nhận xét của bạn là rất có giá trị.
yahor

0

Tôi hoàn toàn đồng ý với TRUSTWORTHY không phải là một cách tiếp cận đáng tin cậy. Bạn nên chọn một cách khác để có được kết quả mà bạn cần.

Gần đây tôi đã đăng một cách để cấp phép bắt đầu công việc Đại lý SQL cho một người dùng hoặc nhóm người dùng khác. Bạn có thể thấy nó tại:

Cho phép người không phải là sysadmin, không phải là chủ sở hữu của tác vụ SQL Server Agent thực thi nó

Tùy chọn thứ ba, bảng bảo mật và quy trình được lưu trữ, cung cấp cho bạn sự linh hoạt nhất và ít tiếp xúc nhất.


-1

Trong máy chủ Sql:

chỉ cần truy cập bảo mật-> lược đồ-> dbo .. Nhấp đúp chuột vào dbo ... sau đó nhấp vào tab quyền -> (phông chữ màu xanh) xem quyền cơ sở dữ liệu và thoải mái cuộn cho các trường bắt buộc như "thực thi" .... hãy tự giúp mình với việc chọn .... và cấp, với các điều khiển cấp hoặc từ chối .... hy vọng điều này sẽ giúp


3
Điều này không trả lời câu hỏi.
Colin 't Hart
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.