it-swarm.com.de

Ausführungsberechtigung für Objekt sp_start_job verweigert

Ich muss einem Benutzer erlauben, einen bestimmten Agentenjob zu kündigen, ohne andere starten zu können. Um dies zu erreichen, habe ich das folgende Verfahren (vereinfacht) erstellt:

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

Wenn ich diese Prozedur aufrufe (nachdem ich überprüft habe, dass sie über "sysadminaccount" ausgeführt wird), wird die folgende Fehlermeldung angezeigt:

Nachricht 229, Ebene 14, Status 5, Prozedur sp_start_job, Zeile 1 Die EXECUTE-Berechtigung wurde für das Objekt 'sp_start_job', Datenbank 'msdb', Schema 'dbo' verweigert.

Der Account ist ein Mitglied der Sysadmin-Rolle, daher sollte es meines Wissens keine Probleme geben, Jobs zu starten. Ich habe überprüft, dass es ein Mitglied der drei sqlagent-Rollen in msdb ist, und diese Rollen haben alle die Ausführungsberechtigung für sp_start_job.

Wie kann ich diesem Konto die entsprechenden Berechtigungen erteilen? Gibt es noch etwas, das wegen des Identitätswechsels getan werden muss?

8
Mansfield

Ich mag die Option TRUSTWORTHY nicht, weil sie Ihre Exposition gegenüber einer Vielzahl von Dingen erheblich erhöht. Wie Remus in diese Antwort erklärt, erhöht es im Wesentlichen jedes db_owner bis sysadmin. Einige andere lesenswerte Dinge sind eine Reihe über TRUSTWORTHY von Sebastian Meine , das BOL-Thema und einen KB-Artikel (auch wenn die Teile der Versammlung in diesem Szenario für Sie möglicherweise nicht relevant sind). ::

(Und es gibt Unmengen anderer Posts, die vor der blinden Nutzung dieser Eigenschaft warnen - nur weil sie funktioniert und einfach ist, heißt das nicht, dass es das Richtige ist - in der Tat sollten Sie sie noch mehr in Frage stellen.) Daher würde ich einen anderen Ansatz vorschlagen (und es gibt noch andere, z. B. das Signieren mit einem Zertifikat, aber das hat bei mir immer funktioniert):

  1. Erstellen Sie die Prozedur in msdb.
  2. Erstellen Sie einen Benutzer für die Anmeldung dieses Benutzers in msdb:

    USE msdb;
    GO
    CREATE USER floobarama FROM LOGIN floobarama;
    
  3. Gewähren Sie dem Benutzer Ausführungsberechtigungen für die gespeicherte Prozedur:

    GRANT EXECUTE ON [dbo].[RunJob] TO floobarama;
    
  4. Testen Sie es - entweder indem Sie die Prozedur aus einer anderen Datenbank aufrufen:

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

    Oder ein einfacher Test, falls Sie jetzt keinen Job ausführen und nicht warten möchten, bis dieser Benutzer ihn ausführt, um herauszufinden, ob er über ausreichenden Zugriff auf msdb verfügt:

    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;
    

    Ergebnis sollte sein:

    I am really...
    ---------------
    sysadminaccount
    
  5. Stellen Sie sicher, dass diesem Benutzer nichts anderes in msdb angezeigt wird:

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

    Ergebnis sollte sein ...

    Nachricht 229, Ebene 14, Status 5, Zeile 21
    Die SELECT-Berechtigung wurde für das Objekt 'sysjobs', Datenbank 'msdb', Schema 'dbo' verweigert.

    ... da das Erstellen eines Benutzers in einer Datenbank ihm keine automatischen Rechte für irgendetwas in dieser Datenbank gewährt; Sie müssen dies explizit entweder für diesen Benutzer oder für eine Rolle oder Gruppe tun, in der er sich befindet (einschließlich public).

12
Aaron Bertrand

Kann nicht kommentieren, da ich nicht genug Punkte habe, also schreibe ich eine Antwort. Dies scheint ein datenbankübergreifendes Problem bei der Verkettung von Eigentumsrechten zu sein. Wenn diese Prozedur außerhalb von msdb erstellt wird, hat sie keinen Zugriff auf Objekte in der Datenbank, auf die verwiesen wird, selbst wenn "EXECUTE AS" den Benutzer als Mitglied der Sysadmin-Rolle ausgibt.

Die wahrscheinliche Lösung lautet also:

  1. Machen Sie Ihre Datenbank TRUSWORTHY:

    ALTER DATABASE dbname SET TRUSTWORTHY ON;
    
  2. Aktivieren Sie die datenbankübergreifende Besitzverkettung für die Datenbank (möglicherweise nicht erforderlich).

    ALTER DATABASE dbname SET DB_CHAINING ON;
    
2
yahor

Ich stimme voll und ganz zu, dass TRUSTWORTHY einem Ansatz nicht allzu vertrauenswürdig ist. Sie sollten einen anderen Weg wählen, um das gewünschte Ergebnis zu erzielen.

Ich habe kürzlich eine Möglichkeit veröffentlicht, einem anderen Benutzer oder einer Gruppe von Benutzern den Start eines SQL Agent-Jobs zu gewähren. Sie können es sehen bei:

Nicht-Sysadmin, Nicht-Eigentümer eines SQL Server-Agent-Jobs darf ausführen

Die dritte Option, eine Sicherheitstabelle und eine gespeicherte Prozedur, bietet Ihnen die größte Flexibilität und die geringste Gefährdung.

0
RLF