SSIS vs. SQL: Identitätswechsel — wie ein Agent-Job an die Ressourcen kommt, die er braucht

Ein SQL-Server-Agent-Job, der auf einem File Share lesen soll, scheitert mit Login failed — der Service-Account des Agents hat dort keine Berechtigung. Die Lösung ist ein Identitätswechsel (englisch impersonation) zur Laufzeit, im SQL Server Agent über einen Proxy-User. Eine Sackgasse bleibt: reine Transact-SQL Script-Steps unterstützen keinen Identitätswechsel — der Workaround ist, das T-SQL in ein SSIS-Paket als Wrapper zu packen.

Was dich erwartet:

  • Warum jeder Job-Step standardmäßig im Security-Kontext des Agent-Service-Accounts läuft — und warum das selten passt.
  • Schritt-für-Schritt-Anlage Credential → Proxy → Job-Step, parallel in SSMS-GUI und T-SQL.
  • Warum reine Transact-SQL Script-Steps die Run As-Property nicht unterstützen, welche Step-Typen es können — und wie sich die Lücke entweder über einen SSIS-Wrapper oder über CmdExec mit sqlcmd.exe schließen lässt.
  • 2026er-Brücke: Group Managed Service Accounts (gMSA), Azure SQL Managed Instance, Azure Data Factory mit Managed Identity, SQL Server on Linux, Container/Pod-Identity.

Voraussetzung: SQL Server 2017+ on Windows, SSMS für die GUI-Konfiguration, ein Login mit Berechtigung zum Anlegen von Credentials (sysadmin oder explizite Permission ALTER ANY CREDENTIAL) und Proxies (msdb-Rolle SQLAgentOperatorRole plus Owner-Rolle).

Inhalt

Überblick

SQL Server Integration Services (SSIS) ist ein mächtiges Tool Set für die Entwicklung von ETL-Strecken. Es gibt viele gute Gründe, die für einen Einsatz von SSIS sprechen — und genauso viele, die dagegen sprechen. Beschränken wir uns auf den Microsoft-Stack, dann kommt als Alternative für die Entwicklung von komplexen ETL-Strecken (im Wesentlichen) nur noch Transact-SQL (T-SQL) in Frage.

Dieser Artikel gehört zu einer Serie von Artikeln, die wichtige Entscheidungskriterien für die Wahl der richtigen Technologie(n) — SSIS und/oder T-SQL — beleuchten.


Wird ein SQL-Server-Agent-Job gestartet, läuft jeder Step standardmäßig im Security-Kontext des Service-Accounts des SQL Server Agent. Dieser Service-Account wird beim Setup festgelegt — entweder als explizites Domänen-/Maschinen-Konto oder als lokales Systemkonto NT AUTHORITY\System.

Mit dieser Auswahl hat der Service-Account einen festen Satz an Berechtigungen, die selten zu allen Jobs passen. Das lokale Systemkonto NT AUTHORITY\System hat umfassende Rechte an lokalen Ressourcen und ist Mitglied der Windows-Gruppe Administratoren — gleichzeitig fehlen ihm typischerweise Berechtigungen für File Shares, Datenquellen anderer Maschinen oder Cross-Domain-Ressourcen.

Nach dem Need-to-Know-Prinzip (jeder Account bekommt genau die Rechte, die er für seine Aufgabe braucht — nicht mehr, nicht weniger) sollte ein Job-Step unter einem dedizierten Account laufen, dessen Rechte zur konkreten Aufgabe passen. Da in einem typischen SQL Server Agent dutzende Jobs mit sehr unterschiedlichen Anforderungen konfiguriert sind, lässt sich das nicht über einen einzigen Service-Account abbilden.

Microsofts Antwort darauf ist der Identitätswechsel (englisch impersonation) zur Laufzeit. Konkret: ein einzelner Job-Step kann unter einem anderen Login als dem Service-Account ausgeführt werden, indem ein Proxy-User zugewiesen wird.

Das Service-Account-Problem

Spürbar wird die Reibung, sobald ein Job-Step auf Ressourcen außerhalb der SQL-Server-Instanz zugreifen muss:

  • File Share für CSV-/Excel-Quelldateien, auf den der Service-Account keine Berechtigung hat.
  • Datenquellen anderer SQL-Server-Instanzen, an denen der Service-Account kein Login besitzt.
  • Domain-Ressourcen (LDAP-Abfragen, Active-Directory-Lookups), für die nur ein dediziertes Service-Konto berechtigt ist.
  • Cloud-Endpoints (Storage Accounts, externe APIs), die ein anderes Auth-Token verlangen als das, was der Service-Account beistellt.

Die naive Lösung wäre, dem Service-Account einfach mehr Rechte zu geben. Das skaliert aber nicht: jede zusätzliche Berechtigung vergrößert die Angriffsfläche und vermischt die Rechte unterschiedlicher Job-Welten. Spätestens wenn ein Job nur lesen darf und ein anderer auch schreiben und löschen soll, kollidieren die Anforderungen.

Die Lösung: Credential + Proxy-User

Microsoft trennt die Identitäts-Konfiguration in zwei Objekte:

  • Credential — ein Instance-level Objekt (im SSMS-Pfad Security → Credentials), das einen externen Login (Domain-Konto, gMSA, lokales Konto) plus zugehörigem Secret kapselt. Das Credential lebt im Server, nicht im Agent.
  • Proxy — ein Agent-level Objekt (im SSMS-Pfad SQL Server Agent → Proxies → <Subsystem>, z. B. SSIS Package Execution), das einen Credential einem bestimmten Subsystem zuordnet und an Job-Steps freigibt.

Im Run As-Feld des Job-Steps wird statt des Service-Accounts der Proxy eingetragen. Sobald der Step startet, wechselt der Agent intern auf die im Credential hinterlegte Identity und führt den Step in deren Sicherheits-Kontext aus.

Schritt für Schritt: Konfiguration

Die Konfiguration besteht aus drei Schritten und ist im Folgenden in beiden Varianten gezeigt — über die SSMS-GUI und über T-SQL. Beide Wege führen zum selben Endzustand; welche Variante besser passt, hängt davon ab, ob das Setup einmalig manuell erfolgt oder reproduzierbar im Skript stehen soll.

Schritt 1 — Credential anlegen

Im SSMS-Object-Explorer geht der Weg über Security → Credentials und dort per Rechtsklick auf New Credential…. Der Dialog verlangt einen Credential-Namen, die Identity (typischerweise ein Domain-Konto im Format DOMAIN\konto) und das zugehörige Passwort.

SSMS Object Explorer mit Pfad Security → Credentials, neu angelegtes Credential cred_etl_proxy als Listen-Eintrag sichtbar.

Programmatisch:

  1: USE [master];
  2: GO
  3: 
  4: CREATE CREDENTIAL [cred_etl_proxy]
  5: WITH
  6:    IDENTITY = N'DOMAIN\svc_etl_proxy',
  7:    SECRET   = N'<password>';
  8: GO

Das <password> ist nur ein Platzhalter — ein hartkodierter Klartext im Skript ist im Production-Setup ein klares Anti-Pattern. Im Produktivbetrieb wird das Secret stattdessen aus einer sicheren Quelle nachgeladen, etwa aus Azure Key Vault, aus einer gMSA-Identity ganz ohne statisches Passwort oder aus einer verschlüsselten Konfigurationsdatei. Die Datei mit dem Klartext landet damit nie im Repository.

Schritt 2 — Proxy-User anlegen

Der entsprechende Weg in SSMS führt über SQL Server Agent → Proxies → SSIS Package Execution und einen Rechtsklick auf New Proxy…. Im Dialog werden Proxy-Name, zugeordnetes Credential und das Subsystem (SSIS Package Execution) gesetzt. Unter „Principals“ wird zusätzlich festgelegt, welche Logins den Proxy bei der Job-Step-Konfiguration überhaupt auswählen dürfen.

SSMS Object Explorer mit Pfad SQL Server Agent → Proxies → SSIS Package Execution, neu angelegter Proxy proxy_etl_fileshare als Listen-Eintrag sichtbar.

Programmatisch:

  1: USE [msdb];
  2: GO
  3: 
  4: <em>-- Proxy anlegen</em>
  5: EXEC dbo.sp_add_proxy
  6:    @proxy_name      = N'proxy_etl_fileshare',
  7:    @credential_name = N'cred_etl_proxy',
  8:    @enabled         = 1;
  9: GO
 10: 
 11: <em>-- Proxy auf das SSIS-Subsystem (ID 11) berechtigen</em>
 12: EXEC dbo.sp_grant_proxy_to_subsystem
 13:    @proxy_name   = N'proxy_etl_fileshare',
 14:    @subsystem_id = 11;
 15: GO
 16: 
 17: <em>-- Login berechtigen, den Proxy bei Job-Step-Konfiguration zu verwenden</em>
 18: EXEC dbo.sp_grant_login_to_proxy
 19:    @proxy_name = N'proxy_etl_fileshare',
 20:    @login_name = N'DOMAIN\bi_developer';
 21: GO

Ein Proxy sollte dabei immer nur auf die tatsächlich benötigten Subsysteme berechtigt werden. Eine Blanket-Berechtigung über alle Subsysteme vergrößert die Angriffsfläche unnötig und steht im Widerspruch zum Need-to-Know-Prinzip.

Schritt 3 — Job-Step auf Proxy umstellen

Im Job-Step-Editor (erreichbar über SQL Server Agent → Jobs → <job_name> → Steps → <step_name> → Edit…) wird im Run As-Dropdown der Default-Eintrag SQL Server Agent Service Account durch den neu angelegten Proxy ersetzt.

Job-Step-Eigenschaften-Dialog mit aktiviertem Run-As-Dropdown, Auswahl proxy_etl_fileshare, Step-Typ SQL Server Integration Services Package

Programmatisch:

  1: USE [msdb];
  2: GO
  3: 
  4: EXEC dbo.sp_update_jobstep
  5:    @job_name   = N'job_etl_load_daily',
  6:    @step_id    = 1,
  7:    @proxy_name = N'proxy_etl_fileshare';
  8: GO

Beim nächsten Job-Lauf führt der Agent diesen Step nicht mehr unter dem Service-Account aus, sondern im Sicherheits-Kontext der im Credential hinterlegten Identity domain\marcu.

Sackgasse: T-SQL-Script-Step hat kein Run As

Die Run As-Property ist allerdings nicht für jeden Step-Typ verfügbar. Welche Subsysteme die Konfiguration zulassen und welche nicht, fasst die folgende Tabelle zusammen:

Step-Typ (Subsystem-Name)Run As (Proxy) unterstützt?
SQL Server Integration Services Package (SSIS)
PowerShell (PowerShell)
Operating System / CmdExec (CmdExec)
Analysis Services Command/Query (ANALYSISCOMMAND / ANALYSISQUERY)
Replication-Subsysteme (DistributionMergeQueueReaderSnapshotLogReader)
Transact-SQL Script (TSQL)

Die String-Namen sind der robuste API-Anker — die numerischen subsystem_id-Werte in msdb.dbo.syssubsystems sind nicht Teil der öffentlichen MS-Doku-Garantie und können zwischen Versionen variieren. Die lokalen Werte lassen sich direkt aus der Instanz lesen: SELECT subsystem_id, subsystem FROM msdb.dbo.syssubsystems;.

Für Transact-SQL Script-Steps läuft das SQL damit immer im Security-Kontext des Service-Accounts — unabhängig davon, welcher Proxy am Step konfiguriert ist. Eine reine T-SQL-Strecke aus Stored Procedures und Skripten lässt sich über diesen Weg also nicht impersonieren.

In der Praxis haben sich zwei Workarounds etabliert:

Workaround 1: SSIS-Paket als Wrapper. Das eigentliche T-SQL bleibt in Stored Procedures, und das SSIS-Paket enthält nur einen oder wenige Execute SQL Task-Container, die diese SPs aufrufen. Der Job-Step ist damit wieder vom Typ SSIS Package Execution und unterstützt Run As. Argumentation und Diff-Pragmatik dieses Ansatzes vertieft der Folge-Artikel SSIS vs. SQL: Lesbarkeit und Wartbarkeit.

Workaround 2: CmdExec-Step mit sqlcmd.exe. Der Step ist hier vom Typ Operating System (CmdExec) (Subsystem 3) und unterstützt damit ebenfalls Run As. Ausgeführt wird sqlcmd.exe mit dem T-SQL-Skript als Parameter:

sqlcmd.exe -E -S server\instance -d database -i path\to\script.sql

Caveats:

  • -E setzt Windows-Authentifizierung gegen den SQL Server voraus, mit der Identity des Proxy-Credentials. Funktioniert, wenn das Credential ein Windows-Konto kapselt.
  • -U <login> -P <password> ist die SQL-Authentication-Variante — das Passwort als Klartext im Step-Kommando ist Production-Anti-Pattern.
  • Logging reduziert sich auf den Step-Output (stdout/stderr); die SSIS-typischen ETL-Logging-Strecken (Execution-Log-Tabellen, SSISDB-Reports) entfallen.

Wer den Komfort der SSIS-Logging-Welt nicht aufgeben möchte, fährt mit Workaround 1 deutlich besser; sqlcmd ist die richtige Wahl, wenn das Setup ohnehin ohne SSIS-Stack auskommen soll.cmd ist die richtige Wahl, wenn das Setup ohnehin ohne SSIS-Stack auskommen soll.

Identitätswechsel jenseits On-Prem-Agent

Das Proxy-Konzept stammt aus der Welt von SQL Server 2008 und passt zum klassischen On-Prem-Stack mit Windows-Domäne. In einem 2026er-Setup trifft man dagegen auf eine deutlich veränderte Auth-Landschaft:

  • Group Managed Service Accounts (gMSA). Microsoft empfiehlt seit Windows Server 2012 gMSAs als modernen Ersatz für statisch verkonfigurierte Service-Accounts: automatische Passwort-Rotation, kein Klartext-Storage, an Computer-/Service-Konten gebunden. Das Credential kann auf eine gMSA-Identity zeigen, und damit fällt die Klartext-Passwort-Problematik aus Schritt 1 weg. Windows Server 2025 ergänzt das Bild zusätzlich um delegated Managed Service Accounts (dMSA) — eine gehärtete Variante für einzelne, an eine konkrete Maschine gebundene Services, die zusätzlich gegen Pass-the-Hash- und Pass-the-Ticket-Angriffe absichert. dMSA ist kein gMSA-Ersatz, sondern ein zweites Werkzeug im selben Werkzeugkasten.
  • Azure SQL Managed Instance. Hat einen SQL Server Agent mit eingeschränktem Funktions-Umfang — Proxies werden in MI nicht unterstützt. Identitäts-Brücken für SSIS-Pakete oder externe Ressourcen-Zugriffe laufen stattdessen über die Managed Identity der MI selbst oder über eine Azure-Data-Factory-Integration mit eigener Managed Identity. PowerShell- und CmdExec-Steps sind weiterhin verfügbar; Analysis Services, Merge Replication und Queue Reader fehlen.
  • Azure Data Factory. Ersetzt klassische Agent-Jobs durch Triggers + Activities. Statt eines Proxy-Users mit Credential wird der Factory eine System-/User-assigned Managed Identity zugewiesen, die in Zielsystemen (Storage, SQL, Key Vault) als Identity gestattet wird. Kein statisches Secret mehr, keine separate Proxy-Konfiguration nötig. Microsoft positioniert Data Factory in Microsoft Fabric als Nachfolge-Plattform; Azure Synapse Pipelines bleiben technisch verfügbar, werden strategisch aber in Fabric überführt.
  • SQL Server on Linux. Unterstützt SQL Server Agent, aber das Proxy-Konzept für Windows-Authentifizierung greift nicht 1:1 — Linux-Auth gegen File Shares läuft über das OS-Mount (CIFS, NFS), nicht über den Agent-Proxy.
  • Containerized SQL Server (Docker, Kubernetes). Das Service-Account-Modell verschiebt sich auf Pod-Identity / Workload Identity. Der klassische Proxy-Stack verliert dort an Bedeutung.

Über alle Varianten zieht sich dieselbe Pointe: wer heute ein neues System aufsetzt, greift eher zu Managed Identity oder gMSA als zu einem statischen Domain-Konto mit Passwort. Bestehende On-Prem-Setups leben dagegen weiter mit Proxy und Credential — beim nächsten Refresh der Service-Accounts lohnt sich aber die Frage, ob gMSA das Setup nicht spürbar vereinfachen würde.

Take-Away

  • Identitätswechsel ist Pflicht, sobald ein Job-Step auf Ressourcen außerhalb des Service-Account-Kontexts zugreifen muss. Der Default — alles läuft unter dem Service-Account — skaliert nicht und ist zugleich ein Sicherheitsrisiko.
  • Credential + Proxy ist das klassische On-Prem-Pattern, umgesetzt in drei Schritten: zuerst das Credential im Security-Tree, dann der Proxy im SQL Server Agent-Tree pro benötigtem Subsystem, und zuletzt der Job-Step, der auf diesen Proxy umgestellt wird.
  • Transact-SQL Script-Steps bleiben die Lücke, weil sie kein Run As unterstützen. Wer dort Impersonation braucht, weicht entweder auf ein SSIS-Paket als Wrapper oder auf einen CmdExec-Step mit sqlcmd.exe aus — Ersteres für die saubere Logging-Welt, Letzteres für ein minimales Setup ganz ohne SSIS-Stack.
  • In der 2026er-Welt übernehmen Managed Identity (in Azure) und gMSA (on-prem) zunehmend die Rolle des klassischen Service-Accounts. Wer neu aufsetzt, beginnt am besten gleich dort; wer ein bestehendes System pflegt, kann den Wechsel schrittweise vorbereiten.

FAQ

Warum unterstützt ein Transact-SQL Script-Step kein Run As?

Das TSQL-Subsystem führt das Skript direkt über die interne SQL-Engine aus, nicht über einen separaten Worker-Prozess wie bei SSIS, PowerShell oder CmdExec. Microsoft hat die Run As-Property für dieses Subsystem nie nachgerüstet — vermutlich, weil der Anwendungsfall „SQL-Skript läuft als anderer SQL-Login“ auch ohne Job-Step-Impersonation gelöst werden kann, etwa über EXECUTE AS LOGIN = '…' direkt im SQL-Skript.

Kann ich ein SSIS-Paket im Agent ohne Proxy unter dem Service-Account ausführen?

Ja, das ist sogar der Default. Wenn das Run As-Feld auf SQL Server Agent Service Account steht, startet der Step ohne Identitätswechsel und läuft im Kontext des Service-Accounts. Das funktioniert problemlos, solange der Service-Account alle benötigten Berechtigungen hat. Sobald das nicht der Fall ist — typischerweise bei File-Share-Zugriffen oder Cross-Instance-Quellen — kommt der Proxy ins Spiel.

Wie viele Proxy-User braucht eine Agent-Instanz?

So viele wie nötig, so wenige wie möglich — typischerweise einer pro Job-Welt mit eigenem Ressourcen-Profil. Eine häufige Aufteilung ist: ein Proxy für ETL-Loads mit File-Share-Zugriff, einer für Cross-Instance-Quellen und ein dritter für Cloud-Storage. Jeder Proxy bekommt dabei nur die Subsysteme freigeschaltet, die er tatsächlich nutzt — Sammel-Proxies mit allen Subsystemen widersprechen dem Need-to-Know-Prinzip.

Was ist der Unterschied zwischen Credential und Proxy?

Das Credential lebt auf Instance-Level und kapselt eine externe Identity (Domain-Konto, gMSA, lokales Konto) zusammen mit ihrem Secret — es ist die „Identitäts-Quelle“. Der Proxy lebt auf Agent-Level und verknüpft genau ein Credential mit einem oder mehreren Subsystemen (SSIS, PowerShell, CmdExec, …); zusätzlich legt er fest, welche SQL-Logins den Proxy bei der Job-Step-Konfiguration auswählen dürfen. Ein Credential kann in mehreren Proxies wiederverwendet werden — etwa ein Proxy für SSIS und ein weiterer für PowerShell, beide auf derselben Identität.

Funktioniert Impersonation in Azure SQL Managed Instance noch?

Anders als On-Prem: der Agent in Managed Instance unterstützt keine Proxies. Wer in MI Job-Steps unter einer anderen Identität fahren will, geht stattdessen über die Managed Identity der MI selbst oder über eine Azure-Data-Factory-Integration mit eigener Managed Identity — das jeweilige Zielsystem (Storage, SQL, Key Vault) wird auf diese Identität berechtigt. Die klassische Credential + Proxy-Konfiguration aus diesem Artikel greift dort also nicht. Für reine Azure-native Pipelines ist Azure Data Factory ohnehin die strategische Wahl, weil Managed Identity direkt am Triggers-/Activities-Modell hängt.

Warum kein CmdExec-Step mit sqlcmd.exe statt SSIS-Wrapper?

Der CmdExec-Workaround ist legitim und manchmal genau die richtige Wahl — vor allem, wenn der Stack ohnehin ohne SSIS auskommen soll. Drei Gründe sprechen aber häufig für den SSIS-Wrapper: erstens ist das Logging reichhaltiger (SSISDB-Reports und Execution-Log-Tabellen statt nur stdout/stderr); zweitens läuft die Auth-Brücke über Windows-Auth (-E) sauber gegen das Proxy-Credential, während die SQL-Auth-Variante (-U und -P) das Klartext-Passwort-Problem zurückbringt; und drittens lässt sich ein SSIS-Wrapper später durch Pre-/Post-Tasks oder Conditional Branching erweitern, ohne die Step-Konfiguration im Agent neu zu schneiden.

Was sind die Sicherheits-Caveats beim Proxy-Setup?

Drei Stellen, an denen die Konfiguration besonders sauber bleiben muss: Erstens sollte das Credential-Secret nicht als Klartext-Passwort gepflegt werden — Azure Key Vault, gMSA-Identitäten ganz ohne statisches Passwort oder eine verschlüsselte Konfigurationsdatei sind die Alternativen; das code/001.sql-Snippet im Repository hat den Klartext nur als Platzhalter. Zweitens werden Subsystem-Permissions granular vergeben — ein Proxy bekommt nur die Subsysteme freigeschaltet, die er tatsächlich braucht; eine Blanket-Berechtigung über alle Subsysteme vergrößert die Angriffsfläche unnötig. Und drittens lohnt sich ein dedizierter Audit-Trail: Änderungen an Credentials und Proxies landen zwar im SQL Server Default Trace, für regulatorische Anforderungen ist aber eine eigene SERVER AUDIT SPECIFICATION (etwa mit SERVER_PRINCIPAL_CHANGE_GROUP für Credentials und DATABASE_PERMISSION_CHANGE_GROUP für Proxy-Subsystem-Grants) die robustere Lösung.

Verwandte Artikel

SSIS-vs.-SQL-Cluster:

ETL-Kontext: