Auto Penetration test on Az Functions
Background
DevSecOps is becoming increasingly more popular. Idea is to shift left security related components so that vulnerability can be caught earlier during the development phase. This post is an attempt to experiment and explain how to add automatic penetration test for Azure Functions in Azure DevOps.
Conclusion
If you don’t have much time reading through entire post, you can just check out yaml below for the end result. Since this is created based on my use-case, you probably want to read “technical decision” section to understand why I did what.
/azure-pipelines.yml
<initial setup on downloading node and setting up vm>- script: |
npm install -g azure-cli
npm install -g azure-functions-core-tools
displayName: ‘Download azure-cli’- script: |
npm install
displayName: ‘npm install’- task: DownloadSecureFile@1
name: secureJSON
inputs:
secureFile: ‘openapi.json’- task: DownloadSecureFile@1
name: secureProp
inputs:
secureFile: ‘options.prop’- script: |
mkdir /tmp/owaspzap && chmod 777 /tmp/owaspzap
mv $(secureJSON.secureFilePath) /tmp/owaspzap
displayName: Create required directories for owaspzap test- bash: |
curl https://packages.microsoft.com/keys/microsoft.asc | gpg — dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sudo sh -c ‘echo “deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main” > /etc/apt/sources.list.d/dotnetdev.list’
npm run start &
docker run -v /tmp/owaspzap:/zap/wrk/:rw -t owasp/zap2docker-weekly zap-api-scan.py -t openapi.json -f openapi -z “-configfile options.prop” -r report.html -J report.json || true
displayName: ‘Penetration test’- task: CopyFiles@2
condition: always()
inputs:
SourceFolder: ‘/tmp/owaspzap/’
TargetFolder: ‘$(Build.ArtifactStagingDirectory)’- task: PublishBuildArtifacts@1
condition: always()
inputs:
ArtifactName: ‘owasp_zap_reports’
<Copy from https://marketplace.visualstudio.com/items?itemName=CSE-DevOps.zap-scanner "Reporting" > "Install handlebars" Section><Copy from https://marketplace.visualstudio.com/items?itemName=CSE-DevOps.zap-scanner > "Reporting" > "Report Generation" Section><Copy from https://marketplace.visualstudio.com/items?itemName=CSE-DevOps.zap-scanner > "Reporting" > "Publish Report (Nunit Style)" Section>
Technical Decision
Programming Languages: Typescript
Since pen test tests against API end point, programming language should not effect how you construct.
Penetration security tool : OWASP ZAP
My team decided to use OWASP ZAP because
- Open source
- UI tool to test on your local (post on how to use it is here)
- ZAP’s docker images are provided and easy to integrated into CI/CD pipeline
AuthLevel for Azure Functions: Functions
- More secure compared to anonymous
- Works well with API Management (I am not covering API management in this post)
Docker vs non-docker
My team decided not to containerize Azure Functions code because
- Containerize applications requires function key due to authLevel=Functions
- Did not want to manage function key
- Wanted to test before deploying
Baseline Scan vs API Scan
My team decided on using API scan. Since I wanted test how each API endpoint is doing with pen test, our decision was naturally API scan. This has small gotcha. Extension only supports baseline pen test. I can still use cli to execute the scan.
Steps
Create azure function and create basic CI pipeline
I guess don’t need much explanation here
Get required API definitions and values for testing
- Set API management with azure functions and you can get API definition
- Create API definition json and values prop file. More instruction here (I got stuck a bit because I was adding “-config” in the file)
- I decided to put these json and prop files under pipeliens> library>secure files but technical anywhere where pipeline can access should be fine
4. Add task to access these files in CI pipeline. Now you can access openapi.json (In addition, create owaspzap tmp directory)
- task: DownloadSecureFile@1
name: secureJSON
inputs:
secureFile: ‘openapi.json’- script: |
mkdir /tmp/owaspzap && chmod 777 /tmp/owaspzap
mv $(secureJSON.secureFilePath) /tmp/owaspzap
displayName: Create required directories for owaspzap test
Install OWASP ZAP and Run pen test
- Install az cli and related libraries
curl https://packages.microsoft.com/keys/microsoft.asc | gpg — dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sudo sh -c ‘echo “deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main” > /etc/apt/sources.list.d/dotnetdev.list’
2. Run src code in the background
npm run start &
3. Finally run pen test and create report
docker run -v /tmp/owaspzap:/zap/wrk/:rw -t owasp/zap2docker-weekly zap-api-scan.py -t openapi.json -f openapi -z “-configfile options.prop” -r report.html -J report.json || true
Now publish the test result
For this, I just copied from instruction under here. Copied code for Install handlebars, Report Generation, and Publish Report (Nunit Style)