Beheerdershandleiding Airflow: connecties beheren

Airflow-connecties die authenticeren met een client_id/client_secret (Databricks, Fabric, Power BI, Synapse, Data Factory, een private git-repo, of elke generieke OAuth-beveiligde API) moeten dat secret laten roteren voordat het verloopt. De Airflow Connections Pipeline is een self-contained Azure DevOps pipelinepakket dat dit automatisch, volgens een schema, doet voor elke connectie die je opgeeft, zonder ooit het eigen applicatiesecret van Airflow prijs te geven.

Overzicht

Eén pipeline, één schema, een lijst met connecties. Bij elke geplande run doorloopt de pipeline de lijst en, per item:

  1. Roteert het client secret van de target-appregistratie: de app die eigenaar is van waar Airflow verbinding mee maakt (een Databricks service principal, een Fabric service principal, een appregistratie van een generieke API, enzovoort). Benoem de target via targetAppName om de pipeline de appregistratie en service principal te laten aanmaken wanneer die ontbreekt (de aanbevolen manier om elke connectie zijn eigen dedicated SP te geven), of via targetAppId om een bestaande te roteren. Een vers aangemaakte SP heeft nog eenmalig, handmatig, resource-toegang nodig (workspace-rollen, ARM RBAC).

  2. Zorgt ervoor dat de SP van de service connection de “Admin”-approl van de Airflow-app heeft, en kent deze zelf toe via Microsoft Graph wanneer deze ontbreekt.

  3. Genereert een access token voor de Airflow-applicatie zelf, zonder ooit het eigen client secret van de Airflow-app te gebruiken (zie “Eén service connection” hieronder).

  4. Zet de nieuwe client_id/client_secret in de opgegeven Airflow-connectie via de Airflow REST API.

Omdat elk item op hetzelfde schema roteert, kies een cron-cadans die korter is dan de kleinste validityDays van al je connecties.

De pipeline verkrijgen

Dit is een op zichzelf staand Azure DevOps pipeline-pakket, zonder afhankelijkheid van de rest van de platform-repo. Verkrijg op een van twee manieren een werkende kopie:

In beide gevallen: pak het pakket uit in een eigen Azure DevOps repo (of een map van een bestaande) en wijs een nieuwe pipeline ernaar — zie “Je pipeline instellen” hieronder.

Eén service connection

Elk item benoemt één Azure DevOps service connection (serviceConnectionName, doorgaans dezelfde voor elk item) waarvan de service principal alles doet:

Taak

Wat de SP nodig heeft

Vindt/maakt target-apps aan en roteert hun secrets

Eigenaar van die appregistraties. Om de pipeline apps per connectie te laten aanmaken (targetAppName), de Graph-applicatiepermissie Application.ReadWrite.OwnedBy — apps die het aanmaakt zijn automatisch in eigendom.

Authenticeert bij de Airflow REST API

De “Admin”-approl op de Airflow-applicatie — zelf toegekend door de pipeline wanneer de SP AppRoleAssignment.ReadWrite.All heeft, anders eenmalig handmatig toegekend.

Je hebt het eigen client secret van de Airflow-applicatie nooit nodig, en zou dit ook nooit moeten krijgen. In plaats daarvan krijgt de SP van de service connection de “Admin”-approl van de Airflow-app. Wanneer de pipeline een token aanvraagt voor de Airflow-app als resource/audience, neemt Microsoft Entra ID die rol op in een roles-claim, ongeacht welke client het token aanvroeg. De auth-laag van Airflow controleert alleen de claim, niet wie het secret van de app in bezit heeft.

Als de SP de rol niet zelf kan toekennen (AppRoleAssignment.ReadWrite.All ontbreekt), mislukt de pipeline met een duidelijke foutmelding en twee oplossingspaden: iemand met rechten over de Airflow-appregistratie draait eenmalig Grant-AirflowAdminRole.ps1, of de SP van de service connection krijgt die Graph-permissie (admin consent vereist) zodat de pipeline bij elke volgende run zelfvoorzienend wordt. Hoe dan ook kan een vers toegekende rol even nodig hebben om door te dringen — draai opnieuw als de eerstvolgende stap nog steeds een 403 geeft.

Je pipeline instellen in Azure DevOps

Alles hieronder gebeurt in je eigen Azure DevOps-organisatie, niet die van de leverancier. Voorkennis van Azure DevOps is niet nodig: elke stap noemt het exacte menu om te klikken.

1. Zet de bestanden in een repo

  1. Klik in je Azure DevOps-project (linkerbalk) op Repos.

  2. Als het project nog geen repo heeft, biedt Azure DevOps aan om er op datzelfde scherm een aan te maken — accepteer de standaardnaam, of geef het een naam als airflow-connections. Je kunt deze pipeline ook prima in een bestaande repo zetten in plaats van een nieuwe; elke submap werkt.

  3. Voeg de bestanden van de pipeline toe aan die repo, met behoud van de mapstructuur (templates/, scripts/, en je connections.yaml):

    • Geen git-ervaring nodig: klik op het scherm Repos → Files op ⋯ (rechtsboven) → Upload file(s), en herhaal dit per map (templates/rotate-connection-template.yaml, alles onder scripts/, en je connections.yaml).

    • Gebruik je al git: clone de repo, kopieer de inhoud van het uitgepakte pakket erin, git add / git commit / git push.

2. Vul je connections.yaml in

  1. Begin vanuit examples/connections.yaml in het gedownloade pakket, of gebruik de generator om er direct een te maken.

  2. Voeg voor elke benodigde connectie een item toe aan de connections-lijst — zie de referentie van connectietypes hieronder. Gebruik targetAppName om de pipeline per connectie een dedicated appregistratie + SP te laten aanmaken, of targetAppId om een bestaande vast te leggen.

  3. connectionId is de Airflow conn_id en moet uniek zijn binnen het bestand — alleen letters, cijfers, underscores en hyphens.

  4. Kies een cron-cadans onder schedules: die korter is dan de kortste validityDays van je connecties, zodat elk secret wordt geroteerd voordat het verloopt.

3. Maak de service connection aan

Dit is de ene identiteit waaronder de pipeline draait (zie “Eén service connection” hierboven) — de naam moet exact overeenkomen met de serviceConnectionName-variabele in je YAML-bestand.

Notitie

De Airflow-applicatie zelf is eigendom van het platform en leeft in de eigen tenant van het platform, niet in de jouwe. Zelf de “Admin”-rol toekennen (hieronder) werkt pas zodra je organisatie Entra ID-onboarding heeft doorlopen — dat is wat de Airflow-applicatie van het platform consenteert in jouw tenant, wat nodig is voordat de SP van je service connection er überhaupt een rol aan kan toekennen. Wordt je Airflow-instantie in plaats daarvan beveiligd via het gedeelde Keycloak-realm van het platform, dan is de Airflow-stap van dit rotatiemechanisme niet van toepassing — neem contact op met het platform-team over het roteren van het secret van die connectie.

  1. Klik linksonder in Azure DevOps op Project Settings.

  2. Klik onder Pipelines op Service connections.

  3. Klik op New service connection.

  4. Kies Azure Resource Manager, klik daarna op Next.

  5. Kies Service principal (automatic) — Azure DevOps maakt de appregistratie voor je aan, dus voor dit deel is er geen aparte Entra ID-stap.

  6. Kies je Subscription (elk abonnement in je eigen tenant — dit is alleen van belang voor het aanmaken van de service principal zelf; welke je kiest heeft geen invloed op de rechten, aangezien alles wat deze pipeline nodig heeft wordt verleend op Microsoft Entra ID-niveau, niet op abonnementsniveau). Laat Resource group leeg (scope: Subscription).

  7. Voer onder Service connection name exact dezelfde naam in als serviceConnectionName in je YAML-bestand (bijv. customer-connections).

  8. Vink uit: Grant access permission to all pipelines. Deze service connection krijgt gevoelige rechten (eigenaarschap van je target-apps, de Graph-permissies hieronder) — laat niet elke pipeline in het project deze vrij kunnen gebruiken. Klik op Save. Bij de eerste run van de pipeline die je in de volgende sectie aanmaakt, toont Azure DevOps een banner om die specifieke pipeline te autoriseren voor deze connection — keur dat daar goed.

De service connection bestaat nu, maar heeft alleen de basis-abonnementsrol die Azure DevOps eraan heeft toegekend. Er zijn nog twee Microsoft Graph applicatiepermissies nodig voordat de pipeline zijn werk kan doen. Ken deze eenmalig toe, als Microsoft Entra ID-beheerder:

  1. Open portal.azure.com, ga dan naar Microsoft Entra ID → App registrations.

  2. Zoek de appregistratie die Azure DevOps zojuist heeft aangemaakt — terug bij de zojuist aangemaakte service connection (Project Settings → Service connections → je connection → Manage Service Principal) opent deze direct in de Entra-portal.

  3. Klik op API permissions → Add a permission → Microsoft Graph → Application permissions.

  4. Zoek beide op en vink ze aan:

    • Application.ReadWrite.OwnedBy — nodig als een connectie targetAppName gebruikt (laat de pipeline de appregistratie van die connectie aanmaken).

    • AppRoleAssignment.ReadWrite.All — nodig zodat de pipeline zichzelf de Airflow “Admin”-rol kan toekennen (zie “De Admin-rol toekennen” hierboven).

    Klik op Add permissions.

  5. Klik op Grant admin consent for <your organization>, bevestig daarna met Yes. De permissierij toont nu een groen vinkje onder Status.

Gebruik je targetAppName nergens in je bestand, dan kun je Application.ReadWrite.OwnedBy overslaan. Wil je AppRoleAssignment.ReadWrite.All liever helemaal niet toekennen, sla dan ook die over — de pipeline drukt dan bij de eerste run instructies af voor handmatige toekenning (zie “De Admin-rol toekennen” hierboven, optie (a)).

4. Maak de pipeline aan

  1. Klik in de linkerbalk op Pipelines → New pipeline.

  2. Where is your code? → Azure Repos Git → selecteer de repo waarin je de bestanden hebt gezet.

  3. Configure your pipeline → Existing Azure Pipelines YAML file.

  4. Branch: main (of de branch waarnaar je hebt gepusht). Path: kies je connections.yaml-bestand (bijv. /customer-connections.yaml).

  5. Klik op Continue, bekijk de YAML-preview, klik daarna op de vervolgkeuze naast Run en kies Save (niet Save and run — zie eerst de volgende stap).

  6. Optioneel: geef de pipeline een herkenbare naam — open hem, klik op ⋯ (rechtsboven) → Rename/move, bijv. “Rotate Airflow connections”.

5. Draai eenmaal, vertrouw daarna op het schema

  1. Open de pipeline en klik op Run pipeline → Run.

  2. Volg elke stap. Als de admin-rol-stap mislukt, drukt deze de twee exacte oplossingen af — zie “De Admin-rol toekennen” hierboven en Probleemoplossing hieronder.

  3. Zodra elke stap groen is, staan je connecties live in Airflow — controleer in de Airflow-UI op de pagina Admin → Connections de ``connectionId``(s) die je hebt geconfigureerd.

  4. Verder niets te doen: het schedules:-blok in je YAML zet herhalende runs al klaar. Controleer de eerstvolgende runtijd onder Scheduled runs van de pipeline (klokicoon, rechtsboven op de pipeline-pagina).

Referentie connectietypes

De pipelinetemplate dispatcht op connType. Types met een dedicated script nemen getypeerde velden direct over (geen handgeschreven extraJson); elk ander connType valt terug op de generieke Set-AirflowConnection.ps1-stap met hostName/extraJson. Login/password zijn altijd de geroteerde client_id/client_secret, en de tenant-ID wordt tijdens runtime afgeleid uit de Azure-context van de service connection, nooit expliciet uitgeschreven in YAML.

Type

connType

Getypeerde velden

Opmerkingen

HTTP (generieke OAuth-beveiligde API)

http

hostName, extraJson (tenant_id, scope, token_url)

De ingebouwde HttpHook van Airflow doet zelf geen client-credentials OAuth — combineer dit met een kleine custom hook in je DAGs die deze velden leest en de token-exchange uitvoert.

Databricks

databricks

hostName (workspace-URL)

Komt overeen met de gedocumenteerde Azure AD SPN-authenticatiemethode van apache-airflow-providers-databricks (extra azure_tenant_id).

Fabric (FabricOperator)

fabric

delegatedScopes (User.Read Workspace.ReadWrite.All Item.ReadWrite.All Item.Execute.All)

Extra tenantId; workspace-/item-ID’s zijn operatorargumenten, geen connectievelden. Scopes worden door de rotatiestap gedeclareerd op de API-permissies van de target-app — admin consent is een eenmalige handmatige stap.

Fabric Capacity (FabricCapacityOperator)

fabric_capacity

—

Extra tenantId; subscription/resource group/capacity-naam zijn operatorargumenten. Richt zich op het ARM-managementvlak — ken de SP de custom rol toe uit “Fabric Capacity-toegang” hieronder.

Power BI

power_bi

—

Extra tenant_id; dataset-/group-ID’s zijn operatorargumenten. Zie airflow-powerbi-provider.

Synapse (AzureSynapseHook)

azure_synapse

hostName (workspace-URL), subscriptionId

Extra’s tenantId/subscriptionId. AzureSynapsePipelineHook leest dezelfde velden, dus één connectie bedient beide.

Data Factory (AzureDataFactoryHook)

azure_data_factory

subscriptionId, resourceGroup, factoryName

Extra’s tenantId/subscriptionId plus resource_group_name/factory_name; resource group/factory zijn standaardwaarden op connectieniveau die operators kunnen overschrijven.

Git (private DAGs-repo)

git

repoUrl (HTTPS clone-URL), trackingRef (branch)

Hetzelfde model van een dedicated app per connectie — gebruik targetAppName om deze connectie zijn eigen SP te geven, en zie dan Git: authorizing the DAGs repo (one-time) hieronder voordat je verwacht dat het ook echt werkt. Zie ook apache-airflow-providers-git-azure voor het workload-identity-alternatief dat helemaal geen geroteerd secret nodig heeft.

Git: de DAGs-repo autoriseren (eenmalig)

Het roteren van het secret van de git-connectie houdt alleen de inloggegevens van de service principal geldig. Het geeft die service principal niet vanzelf toestemming om de DAGs-repo te lezen. Als de DAGs-repo in Azure DevOps staat en je gebruikt targetAppName om deze connectie zijn eigen dedicated service principal te geven, doe dan het volgende eenmalig per service principal, als beheerder van de Azure DevOps-organisatie, voordat de pipeline voor het eerst tegen die connectie draait:

  1. Geef de service principal een toegangsniveau (een “licentie”). Azure DevOps vereist er een voor elke identiteit die ermee werkt, service principals inbegrepen — zonder deze stap bestaat de repo-permissie uit stap 2 wel, maar mislukken Git-bewerkingen alsnog.

    1. Organization Settings (tandwielicoon, linksonder) → Users → Add users.

    2. Plak in het gebruikersveld de Application (client) ID van de service principal (te vinden op de Overview-pagina van de appregistratie in Microsoft Entra ID).

    3. Access level: kies Basic. Stakeholder geeft geen leestoegang tot Git voor een private repo, dus dat werkt hier niet.

    4. Add to project(s): kies het project waarin de DAGs-repo staat. Klik op Add.

  2. Autoriseer het op de specifieke repo — niet organisatiebreed.

    1. Project Settings → Repositories → selecteer de DAGs-repo → tab Security.

    2. Klik op Add en plak dezelfde service-principal-identiteit.

    3. Zet de permissies op Reader (dekt Read / Code: Read — alles wat dit connectietype nodig heeft, aangezien het alleen clonet en pullt, nooit pusht).

Herhaal beide stappen voor elke git-connectie die zijn eigen dedicated service principal heeft. Delen meerdere git-connecties één target-app (via targetAppId in plaats daarvan), dan hoef je dit maar één keer te doen voor die gedeelde identiteit.

Fabric Capacity-toegang (eenmalig)

De fabric_capacity-connectie stuurt suspend/resume/scale aan via het ARM-managementvlak, dus de SP ervan heeft een rol op de capacity-resource nodig, geen Contributor. Maak eenmalig een minimale custom rol aan (Fabric Capacity (Smooth) Operator) die Microsoft.Fabric/capacities/{read,write}, capacities/suspend/action, capacities/resume/action, en capacities/skus/read / skus/read toekent, en ken deze vervolgens toe aan de door de pipeline aangemaakte SP voor die connectie (draai de pipeline eerst eenmaal zodat de SP bestaat). Laat write weg als je alleen ooit suspend/resume doet, niet scale.

Probleemoplossing

Symptoom

Waarschijnlijke oorzaak

Kan de Airflow API niet bereiken (na retries)

airflowBaseUrl klopt niet of de instantie ligt eruit — geen auth-probleem, aangezien deze stap eerst met backoff opnieuw probeert.

Admin-rolstap mislukt met handmatige oplossingsstappen

De SP van de service connection kan de Airflow “Admin”-rol niet zelf toekennen — ken deze handmatig toe of geef de SP AppRoleAssignment.ReadWrite.All, en draai opnieuw.

401/403 van de Airflow API, ook al is de admin-rolstap geslaagd

Een vers toegekende rol kan even nodig hebben om door te dringen — draai opnieuw. Blijft het aanhouden, controleer dan of de opgeloste Airflow-app de juiste is (leg deze expliciet vast met airflowAppId als airflowAppName dubbelzinnig oplost).

“does not exist” bij het roteren van het target-secret

Met targetAppId moet de target-app al bestaan — schakel over naar targetAppName als je wilt dat de pipeline een dedicated app per connectie aanmaakt.

Kan de target-app niet aanmaken

De SP van de service connection mist rechten om apps aan te maken — laat een admin de app handmatig aanmaken en leg deze vast via targetAppId, of ken de SP Application.ReadWrite.OwnedBy toe en draai opnieuw.

Pipeline geslaagd, maar het target-systeem geeft 401/403 aan DAGs

Een vers aangemaakte SP per connectie heeft credentials maar nog geen toegang — ken eenmalig de resource-kant toegang toe (workspace-rol, ARM RBAC, etc.).