DevOpsBeveilig je YAML pipelines

Beveilig je YAML Pipelines met checks en templates

Security als onderdeel van je CI/CD pipeline zou voor iedereen vanzelfsprekend moeten zijn, maar in de praktijk zien we dat dit nog lang niet altijd het geval is. Bij het gebruik van CI/CD pipelines gaan we steeds meer onderdelen automatiseren en handmatige stappen willen we zo veel mogelijk wegnemen. Automatische controles op de kwaliteit van je code zou daar wat mij betreft zeker onderdeel van moeten zijn. Er zijn veel tools beschikbaar om je code te controleren, denk aan SonarCloud (of SonarQube), WhiteSource en veel andere linters. Om teams te helpen bij het gebruik van deze “security” tools, kun je gebruik maken van YAML templates.

Templates in YAML Pipelines

Waar je in de classic pipelines gebruik kunt maken van task groups om onderdelen in je pipeline te hergebruiken, kun je in YAML pipelines werken met templates. Deze templates kun je op twee manieren gebruiken: via include en via extends. Met name de 'extends' optie vind ik één van de sterkste onderdelen van de YAML Pipelines in Azure DevOps .

Een template “includen”

Bij de include optie neem je eigenlijk het template op in jouw pipeline. Dit is te vergelijken met het gebruik van task groups in Azure DevOps. Je kunt bijvoorbeeld templates maken voor onderdelen die je vaak gebruikt in je pipelines. Dit kunnen onderdelen in je build zijn (aanroep van SonarQube of SonarCloud, het starten van unit tests, …) of onderdelen van je deployment. Bij deployments kun je er op deze manier voor zorgen dat de deployment naar iedere omgeving op dezelfde manier wordt uitgevoerd.

Een template “extenden”

De andere optie is via extends, waarmee je eigenlijk de structuur van de pipeline kunt bepalen. In de template bepaal je dan welke stappen altijd uitgevoerd worden en waar de gebruikers van je template zelf onderdelen toe kunnen voegen. Je kunt er bijvoorbeeld voor kiezen om iedere build te starten met Credential Scanner (CredScan) en een Static Code Analysis, waarna de gebruikers zelf de benodigde buildtaken kunnen uitvoeren. Voor deployments zou je er voor kunnen kiezen om voor de deployment naar productie eerst een change aan te maken in ServiceNow of TopDesk.

Checks op protected resources

Met templates voor Azure Pipelines maak je het de gebruikers al een stuk eenvoudiger om onderdelen in een pipeline te gebruiken. Dit alleen kan al helpen bij de adoptie van security onderdelen in je pipeline. Het wordt namelijk al een stuk eenvoudiger gemaakt om deze security onderdelen te gebruiken.

Met behulp van checks op “protected resources” kan je ook aangeven dat gebruikers jouw template moeten gebruiken om gebruik te kunnen maken van zo’n resource. Protected resources kunnen zijn: agent pools, variable groups, secure files, service connections, environments en repositories.

Op al deze protected resources kun je checks toevoegen. Eén van die checks is “Required template”. Hiermee geef je aan dat gebruikers een template moeten extenden. Je kunt hier meerdere templates invullen, in dat geval moeten gebruikers een van de templates gebruiken om gebruik te kunnen maken van zo’n protected resource. Op deze manier kun je bijvoorbeeld verschillende templates maken voor verschillende ontwikkeltalen.

Voorbeeld template

In dit blog gaan we een required template check toevoegen aan een Agent Pool. Hiermee gaan we ervoor zorgen dat iedereen gebruik maakt van de GitHub Super Linter. De GitHub Super Linter is een verzameling van linters (tools die je code analyseren op potentiële fouten, bugs en styling errors) voor veel verschillende ontwikkeltalen, verpakt als Docker container. Deze GitHub Super Linter wordt ook aangeboden als GitHub Action, maar gaan we in dit geval aanroepen vanuit een Azure DevOps pipeline. In het voorbeeld heb ik gebruik gemaakt van de slim-v4 versie. Dit is een wat kleinere image, waardoor het builden wat sneller gaat. Je mist hiermee echter wel weer enkele linters als ‘pwsh’ en ‘C#’. Je kunt ook de volledige image gebruiken, in dat geval vervang je de docker pull regel met: docker pull github/super-linter:latest

Eerst maken we een template die de GitHub Super Linter aanroept en vervolgens de overige build stappen doorloopt.

Azure Pipeline template

Deze template beschrijft de stappen die altijd genomen worden. In dit geval gaat het om de job ‘Run GitHub Super Linter’. Daaronder komen de build steps die als buildSteps parameter meegegeven moeten worden. Dit kunnen de build steps zijn die je normaal gesproken in je build YAML zult hebben, denk aan restore, build, unit test, etc.

Vervolgens stellen we de Required Template check in voor de pool. Hiervoor open je de Project Settings en kies je voor Agent Pools. Je klikt op de pool waar je de check aan toe wilt voegen en klikt rechtsboven op More Actions en kiest voor Approvals and checks:

Beveilig je pipelines met checks en templates

Hier kun je vervolgens kiezen voor de Required template check:

Beveilig je pipelines met checks en templates

Je vult de gevraagde gegevens in en slaat de check op:

pipelines3b

In onderstaand voorbeeld heb ik twee templates toegevoegd als required template, waarbij gebruikers dus minimaal 1 van deze templates moeten gebruiken:

Beveilig je pipelines met checks en templates

Als ik vervolgens een pipeline wil starten die niet voldoet aan deze check, faalt mijn pipeline en zie ik dat niet alle check geslaagd zijn:

Beveilig je pipelines met checks en templates

Je kunt klikken op de regel 0/1 check passed voor meer informatie:

Beveilig je pipelines met checks en templates
Beveilig je pipelines met checks en templates
Vervolgens pas ik mijn pipeline aan, zodat ik wel gebruik maak van het vereiste template:

Azure Pipelines

Omdat de template in een andere Git repository staat, voeg ik de betreffende repository toe als resource. In het tweede blok extend ik de pipeline vanuit die template en voeg ik de overige build steps toe aan de buildSteps parameter.

Het is ook aan te raden om goed na te denken welke branch of tag je wilt gebruiken voor de extends templates. Hiermee voorkom je problemen zodra er aanpassingen aan de template nodig zijn die ervoor zorgen dat alle bestaande pipelines falen. In het voorbeeld hierboven hebben we gebruik gemaakt van Git tags.

En vervolgens kan ik met mijn pipeline wel gebruik maken van de betreffende Agent Pool. Je ziet hier 1 check passed:

Pipelines

In het geval de linter issues vindt in je code faalt de pipeline alsnog.

Pipelines beveiligen

Valkuilen

Hoe aantrekkelijk het voor sommigen ook zal klinken, begin niet direct met het afdwingen van templates op alle resources zonder overleg met je gebruikers. Als je gebruik gaat maken van templates op een centrale plek, worden die templates uiteindelijk een essentieel onderdeel van alle pipelines. Een fout in de template, of een service die down is, zal ervoor zorgen dat veel (of alle) pipelines falen.

Probeer te voorkomen dat deze templates een bottleneck gaan vormen in het proces en zo de gebruikers gaan frustreren. Als veel pipelines gebruik moeten maken van hetzelfde template, is het extra belangrijk dat alle onderdelen die je hiermee afdwingt altijd werken. Als de taken die je in een template gebruikt regelmatig falen of de doorlooptijd van pipelines flink verlengen, zul je niet het gewenste resultaat bereiken. Doe dit ook altijd in goed overleg met je gebruikers, zodat ze begrijpen waarom ze deze template zouden moeten gebruiken en ook mee kunnen denken in de invulling.

Conclusie

Templates in YAML pipelines maken het mogelijk om onderdelen in je pipeline te hergebruiken. Hiermee kun je het voor je gebruikers eenvoudiger maken om deze onderdelen te gebruiken. Als iedereen voor elke pipeline zelf de benodigde stappen moet toevoegen en configureren, is de kans aanwezig dat bepaalde essentiële onderdelen worden overgeslagen. Door de gebruikers te voorzien van standaard bouwblokken die ze aan kunnen roepen met variabelen, worden die essentiële onderdelen meegenomen zodra ze deze templates gebruiken. Daarom is het ook aan te raden om zo snel mogelijk te beginnen met templates en extends, dit kan bijvoorbeeld met een vrijwel leeg template. Je kunt de template dan stap voor stap voorzien van security onderdelen, maar je hebt dan al snel een centrale plek die vrijwel alle pipelines raakt.

De combinatie met checks op protected resources geeft veel mogelijkheden. Je kunt hiermee bepaalde security checks afdwingen. Maar denk goed na over de invulling. En doe alles in goed overleg met je gebruikers.

Mike Beemsterboer, DevOps Consultant

Ondersteuning nodig bij het opzetten van een CI/CD Pipeline? Ga naar CI/CD Pipeline opzetten.

  • DevOps-program-banner