Azure Fortify Integration and Breaking Pipelines
Introduction
Hello everyone, we will talk about “Azure Devops Fortify integration process and secure pipeline configuration” this article. First we will perform the installation. azure agent, ssc connection etc. Afterwards, we will scan a project in the Azure Devops environment with Fortify SCA and upload the result to SSC. This is a pipeline diagram in normal flow. To spice up the work, we will break the pipeline if the number of vulnerabilities at a certain level is high in the project.
Stage 1: Azure Devops Agent Installation and Setup Proccess
Stage 2: Service Connection (SSC) and Fortify Addon Install
Stage 3: Create first pipeline
Stage 4: How to break pipeline from the number of vulnerabilities in the project.
Requirements
Fortify SSC/SCA
Azure Devops Account
Lab Information
Windows Server 2019, Fortify SSC/SCA 23.2.* version.
Azure Devops Configuration and Agent Installation
In the first stage, we create an account by going to dev.azure.com and create a project by clicking “new project” as seen in figure 1.0. My project name is “Test”
With this video you can see how the agent can be created and downloaded.
Project Settings > Agent Pools > Agent Pool Name > New Agent
If you downloaded agent, you continue next step.
mkdir agent ; cd agent
Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\vsts-agent-win-x64-3.232.1.zip", "$PWD")
You can then configure the agent and start the service by following the steps in the image using PowerShell. Even though it is not the same as in the example image, it is recommended that you set the startup type of the agent to automatic from the services.
Stage 1 completed. Let’s we do now configuration service connection.
Service Connection and Fortify Addon Installation
In this section, we will connect the ssc service to the azure devops environment. Finally, we will add the Fortify plugin to our Azure environment.
Step by Step
Projects Settings > Service Connections > New Service Connection > Generic
What you need to pay attention to when creating the service is the token you specify. You can create the token via fortify ssc. You can review the official Fortify document for the token you should use at the minimum level.
This section finally, You must download Fortify Addon on Microsoft marketplace.
Create First Pipeline
In this section, we will create firs pipeline. We will pull a project that we forked from the Github repo. We will create a simple azure.yml file and start a sca scan and upload the result to ssc.
Step by Step
Projects > Pipelines > New Pipelines
At this stage we will select the github option. It will ask us to connect our own github account. (Your company may also have a joint enterprise github account. When you make this connection, it will ask us to select a repository. At this stage, you can fork a public github project you want to scan and add it to your own repository.
I used the https://github.com/ferhatcil/hackigniter repository. Thanks to the person who shared the project publicly.
You can select the startup pipeline on the configuration screen. Afterwards, you can delete all the default lines in the azure-yml file.
You can then search for the “fortify” plugin we added before from the “show assistant” panel. There will be more than one result. The “Fortify Static Code Analyzer Assessment” option you need to select. When you click Add, it will give you a sample scanning option. The information you need to fill in before adding is indicated with photographs. Additionally, you need to create an application via ssc.
Footnote: The application name and application version information shown in Figure 1.9 must be entered.
Finally, all that remains is to edit our file in .yml format. You may need to edit the draft a bit. You can take the code blog as an example.
trigger:
- master
pool: Medium-Article
steps:
- task: FortifySCA@7
inputs:
applicationType: 'other'
fortifyBuildId: 'php'
fortifyScanType: 'LocalScan'
runFortifyUpload: true
fortifyServerName: 'ssc test'
fortifyApplicationName: 'hackigniter'
fortifyApplicationVersion: '1'
pool: change.
fortifyserverName: change
fortifyApplicationName: change
FortifyApplicationVersion: change
run pipeline! 🚀
Congratulations. You have successfully created your first pipeline. When you check the SSC, you will see that the project has been scanned successfully and its report has been uploaded.
How to Break Pipeline by Potential Security Issues
In the final stage of the work, we will organize the pipeline we created from a security perspective. The pipeline structure we use here and our goal is, at the end of the day, as follows:
1- Create a pipeline where integrations are carried out in the Azure Devops environment.
2- Pull the project from Github, scan it with SCA, upload it to SSC.
3- Finish Pipeline.
In addition to this, we will add an extra step in the last stage.
4- If you see a vulnerability in x (variable) number and y (variable) level during the scanning, break the pipeline.
If we need to interpret this code script;
I adapt the curl request to the powershell script for the Fortify API connection. Python vs. you can use It’s completely habit. Then, I print the json file with the get request I send. Here you can use azure variables for file path and similar structures. In this article, I specified the file path directly to make it more visible.
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$fortify_ssc_api_url = "$(url)"
$token = "FortifyToken $(FortiToken)"
$headers = @{
"Authorization" = $token
"Content-Type" = "application/json"
"Accept" = "application/json"
}
try {
# Api request get
$response = Invoke-WebRequest -Uri $fortify_ssc_api_url -Method Get -Headers $headers
# Reponse status
if ($response.StatusCode -eq 200) {
# JSON data parse
$project_versions_data = $response.Content | ConvertFrom-Json
# Json data write
$file_path = "C:\Users\Administrator\Desktop\test.json"
$project_versions_data | ConvertTo-Json -Depth 4 | Out-File -FilePath $file_path
$jsonData = Get-Content "C:\Users\Administrator\Desktop\test.json"
$priorityLines = $jsonData | Where-Object { $_ -like "*friority*" }
$txtFile = "C:\Users\Administrator\Desktop\output.txt"
$priorityLines | Out-File -FilePath "C:\Users\Administrator\Desktop\output.txt"
Write-Host "Project vulnerability info export succes."
} else {
throw "HTTP Error: $($response.StatusCode) $($response.StatusDescription)"
}
} catch [System.Net.WebException] {
Write-Host "HTTP Error: $($_.Exception.Message)"
} catch {
Write-Host "An error occurred: $($_.Exception.Message)"
}
I used this endpoint.
Azure Define Variables
Now we parse the json file with the where-object structure and extract the lines containing the expression “friority”. To make this more understandable, I shared the sample json output visually. It gives multiple outputs as api response. Our goal, as I explained in the pipeline process structure, is to actually obtain the number of vulnerabilities at the end of the day and terminate the pipeline accordingly.
$jsonData = Get-Content "C:\Users\Administrator\Desktop\test.json"
$priorityLines = $jsonData | Where-Object { $_ -like "*friority*" }
$txtFile = "C:\Users\Administrator\Desktop\output.txt"
$priorityLines | Out-File -FilePath "C:\Users\Administrator\Desktop\output.txt"
As the last stage, we will read our txt file and if the “*friority*” statement is used more than x variable (exit1), we will throw an error code and break the pipeline.
Why Exit 1
A pipeline is a command-line structure in which a series of commands are executed sequentially. The output of each command is used as the input for the next command. Breaking a pipeline means stopping the execution of one or more commands.
The exit 1 expression indicates that the execution of a command has failed. Therefore, using the exit 1 expression to break a pipeline will stop the execution of the rest of the pipeline.
Final
trigger:
- master
pool: Default
steps:
- task: FortifySCA@7
inputs:
applicationType: 'other'
fortifyBuildId: 'php'
fortifyScanType: 'LocalScan'
runFortifyUpload: true
fortifyServerName: 'ssc test'
fortifyApplicationName: 'hackigniter'
fortifyApplicationVersion: '1'
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$fortify_ssc_api_url = "$(url)"
$token = "FortifyToken $(FortiToken)"
$headers = @{
"Authorization" = $token
"Content-Type" = "application/json"
"Accept" = "application/json"
}
try {
# Api request get
$response = Invoke-WebRequest -Uri $fortify_ssc_api_url -Method Get -Headers $headers
# Reponse status
if ($response.StatusCode -eq 200) {
# JSON data parse
$project_versions_data = $response.Content | ConvertFrom-Json
# Json data write
$file_path = "C:\Users\Administrator\Desktop\test.json"
$project_versions_data | ConvertTo-Json -Depth 4 | Out-File -FilePath $file_path
$jsonData = Get-Content "C:\Users\Administrator\Desktop\test.json"
$priorityLines = $jsonData | Where-Object { $_ -like "*friority*" }
$txtFile = "C:\Users\Administrator\Desktop\output.txt"
$priorityLines | Out-File -FilePath "C:\Users\Administrator\Desktop\output.txt"
Write-Host "Project vulnerability info export succes."
} else {
throw "HTTP Error: $($response.StatusCode) $($response.StatusDescription)"
}
} catch [System.Net.WebException] {
Write-Host "HTTP Error: $($_.Exception.Message)"
} catch {
Write-Host "An error occurred: $($_.Exception.Message)"
}
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$content = Get-Content -Path "C:\Users\Administrator\Desktop\output.txt"
$x = 2
$lines = $content | Where-Object { $_ -like "*friority*" }
if ($lines.Length -ge $x) {
Write-Host "Pipeline Broken. Error Status: Exit Code 1"
Exit 1
}
Broke Pipeline ❌
Conclusion
Sometimes a pipeline’s failure to work may be as important as its operation. In today’s DevSecops concept, this is just one of the processes that can be improved. There are many processes like this.
https://www.linkedin.com/in/0x3d/