GitHub Advanced Security now supports the ability to analyze your code for vulnerabilities from third-party CI pipelines, while previously, instead, this capability was available exclusively with GitHub Actions.
In this post (and video) I will show you how to use Code Scanning to scan a GitHub Repository from an Azure DevOps pipeline using the YAML editor.
Intro
Alright, as I've mentioned before, rather than leveraging the native GitHub Actions workflow with the standard “Set Up Workflow” experience, today we are going to use an Azure DevOps Pipeline to scan the Code we have in our GitHub repo.
Let's take a look at the steps we would need to perform to integrate GitHub Advanced Security for Code Scanning with Azure DevOps:
Since the Azure Pipelines Agent I am using is ephemeral, because I'm using the Hosted Agents, I'll have to install the CodeQL package on each pipeline execution. If you are using a self-hosted agent instead consider pre-installing the package to save time and compute resources.
Video
As usual, if you are a visual learner, or simply prefer to watch and listen instead of reading, here you have the video with the whole explanation and demo, which to be fair is much more complete than this post.
(Link to the video: https://youtu.be/ZgR90vWpBQw)
If you rather prefer reading, well... let's just continue :)
Download CodeQL
First thing we have to do, as we have seen in the list of steps, is to Download the latest CodeQL dependencies on my agent.
- script: |
wget https://github.com/github/codeql-action/releases/latest/download/codeql-runner-linux
chmod +x codeql-runner-linux
displayName: 'Get latest CodeQL package. Install on Agent.'
Since this Pipeline runs on Linux, using wget and targeting the latest Linux release I can download all necessary files to my directory. I also change permissions for the downloaded file before I run it.
Authorizing CodeQL
Next, we need to give that pipeline full access to our repo. To do so, we need to create a GitHub Personal Access Token. (see how).
For private repositories the token must have the whole
repo
scope. For public repos, instead, the token needs only thepublic_repo
andrepo:security_events
scopes.
Then we need to save the PAT as a variable in the Pipeline. Remember to set it as a secret. For security sake, I'd recommend you using Azure KeyVault, save the PAT there and reference it into Azure Pipelines.
Now that we have the GitHub Personal Access Token saved in Azure Pipelines, we can initialize CodeQL.
Initialize CodeQL
Let's initialize the CodeQL Executable and create a CodeQL database for the language detected.
Once again we need to add a script step to our workflow:
- script: |
./codeql-runner-linux init \
--repository YOUR_REPO_NAME \
--github-url https://github.com \
--github-auth $GITHUB_PAT \
--config-file .github/codeql/codeql-config.yml
displayName: 'Initialize CodeQL Executable and create a CodeQL database'
Replace the YOUR_REPO_NAME
placeholder with the whole name of the repo you want to scan, for example "n3wt0n/myrepo"
Also, the $GITHUB_PAT
is the name of the variable where I've saved the PAT.
If you want to analyze a compiled language like .Net, Java and so on, remember to execute the build AFTER the CodeQL Init step but BEFORE the Analyze step.
In fact the init step will create a script for you that you have to execute before building your code in order for CodeQL to be able to monitor the build as well.
Analyze the repo
Finally, I want to populate the CodeQL runner databases, analyze them, and upload the results to GitHub.
Let's add the final script
- script: |
./codeql-runner-linux analyze \
--repository YOUR_REPO_NAME \
--github-url https://github.com \
--github-auth $GITHUB_PAT \
--commit $(Build.SourceVersion) \
--ref $(Build.SourceBranch)
displayName: 'Populate the CodeQL runner databases, analyze them, and upload the results to GitHub.'
Once again, replace the YOUR_REPO_NAME
placeholder with the whole name of the repo you want to scan.
Here we also have 2 more parameters:
- --commit: this is the SHA of the commit you want to scan
- --ref: this is the fully qualified ref name of the branch you want to scan (i.e. refs/heads/master)
In my case I retrieve both parameters from variables, which is an approach I would recommend.
Conclusion
And that is basically it.
You can now run the Pipelines and, if successful, you should be able to navigate back to your GitHub repository security tab under code scanning to view the results of your scan.
Check the video for the full explanation and demo
Let me know in the comment section below what you think about this experience. For me, it would of course be even better if we could have native Azure Pipelines tasks instead of having to write shell scripts, but for the time being this work pretty well as well.