Use Lucent Sky AVM with Azure Pipelines

2024/8/22 |

This article describes how to integrate Lucent Sky AVM with Azure Pipelines. By integrating Lucent Sky AVM with an application's continuous integration pipelines, developers can ensure that only code changes meeting the security standards are committed or deployed.

The Lucent Sky AVM CLI commands used in this article favor simplicity over scalability. For example, asynchronous methods such as BeginAnalyze might be more suitable than their synchronous counterparts when working with a large application. To learn about more advanced functionalities of the CLI, view the following article in the Lucent Sky Knowledge Base:
Lucent Sky AVM CLI reference

In this article, you will learn how to:

  • Prepare Lucent Sky AVM CLI for use in Azure Pipelines.
  • Start a scan in Azure Pipelines.
  • Download and evaluate a scan report in Azure Pipelines.
  • Download the remediated source code and create a pull request in Azure Pipelines.

At the end, you will be use Lucent Sky AVM in Azure Pipelines to start a scan, download and evaluate reports, and work with remediated source code in Azure Pipelines.

Prepare Lucent Sky AVM CLI for use in Azure Pipelines

Lucent Sky AVM CLI needs to be downloaded to the Azure Pipeline agent before it can be used. How the CLI is downloaded varies and depends on each organization's needs and requirements, and the CLI might already be present if using a self-hosted agent.

For macOS or Ubuntu agents, the scripts in this article may need to be modified to prepend mono before calls of Lucent Sky AVM CLI executable. For example, mono ./SkyAnalyzer.Interface.Console.exe.

To learn more about how to install Lucent Sky AVM CLI on different operating systems, view the following article in the Lucent Sky Knowledge Base: Administration guide to Lucent Sky AVM CLI

  1. Navigate to the Pipelines > Pipelines section of the Azure DevOps project and edit the pipeline with Azure Pipeline designer. Create a secret variable named ApiKey with the value of an API key to the Lucent Sky AVM server.

  2. Open the .yml file of the Azure Pipeline. Locate the variables section and add the following variables:

     variables:
     - name: InstanceFqdn
       # Replace <InstanceFqdn> with the FQDN or IP address of the Lucent Sky AVM instance
       value: <InstanceFqdn>
     - name: ApplicationId
       # Replace <ApplicationId> with the value of the project's application ID on the Lucent Sky AVM instance
       value: <ApplicationId>
    
  3. In the .yml file, locate an appropriate location to download the CLI, such as after the application build is completed.

  4. Insert the following code to the .yml file, which downloads the CLI setup file to $(Agent.ToolsDirectory)/clear-cli.zip and extracts its content to $(Agent.ToolsDirectory)/clear-cli.

     - task: PowerShell@2
       displayName: Download CLI
       inputs:
         targetType: 'inline'
         script: |
           Invoke-WebRequest -Uri 'https://lsky.co/clearcli' -OutFile '$(Agent.ToolsDirectory)/clear-cli.zip'
           Expand-Archive -Path '$(Agent.ToolsDirectory)/clear-cli.zip' -DestinationPath '$(Agent.ToolsDirectory)/clear-cli'
           Remove-Item '$(Agent.ToolsDirectory)/clear-cli.zip'
    

    The URL https://lsky.co/clearcli points to the latest Lucent Sky AVM CLI. To pin the CLI to a specific version, append -version after the URL. For example, https://lsky.co/clearcli-2406.

  5. Insert the following code to the .yml file, which configures the CLI to use a remote Lucent Sky AVM instance.

     - task: PowerShell@2
       displayName: Configure CLI
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Agent.ToolsDirectory)/clear-cli'
         script: |
           # Replace <InstanceFqdn> with the FQDN or IP address of the Lucent Sky AVM instance
           $InstanceFqdn = "<InstanceFqdn>"
           ./SkyAnalyzer.Interface.Console.exe --Interface config --Method set --Value "endpoint = $(InstanceFqdn):5759"
    

Start a scan in Azure Pipelines

  1. Open the .yml file of the Azure Pipeline, and locate an appropriate location to start the scan, such as after the build artifacts are available.

  2. Insert the following code to the .yml file, which generates a random scan ID.

     - task: PowerShell@2
       displayName: Generate scan ID
       inputs:
         targetType: 'inline'
         script: |
           $scanId = New-Guid
           Write-Host "##vso[task.setvariable variable=ScanId]$scanId"
    
  3. Insert the following code to the .yml file, which creates a scan under the application on Lucent Sky AVM server, and uploads the build artifact for analysis.

     - task: PowerShell@2
       displayName: Create and start scan
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Agent.ToolsDirectory)/clear-cli'
         script: |
           ./SkyAnalyzer.Interface.Console.exe --Key $(ApiKey) --Interface Scan --Method Create --ApplicationId $(ApplicationId) --ScanId $(ScanId)
           ./SkyAnalyzer.Interface.Console.exe --Key $(ApiKey) --Interface Scan --Method Analyze --ScanId $(ScanId) --SourceCodePath '$(Build.SourcesDirectory)/target/ContosoWeb.war'
    
  4. Insert the following code to the .yml file, which checks the scan result code to determine if the scan was completed successfully.

     - task: PowerShell@2
       displayName: Get scan result
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Agent.ToolsDirectory)/clear-cli'
         script: |
           $scanResult = ./SkyAnalyzer.Interface.Console.exe --Key $(ApiKey) --Interface Scan --Method GetResult --ScanId $(ScanId)
           if ($scanResult -lt 0) { [Console]::Error.WriteLine("Scan failed ($scanResult)") }
    

Download and evaluate a scan report in Azure Pipelines

  1. Open the .yml file of the Azure Pipeline, and locate an appropriate location to evaluate the scan report, such as after the scan is completed.

  2. Insert the following code to the .yml file, which generates and downloads the XML report of the scan.

     - task: PowerShell@2
       displayName: Download XML report
       inputs:
         targetType: 'inline'
         workingDirectory: '$(System.DefaultWorkingDirectory)/tools/clear-cli'
         script: |
           ./SkyAnalyzer.Interface.Console.exe --Key $(ApiKey) --Interface Scan --Method Report --ScanId $(ScanId) --ReportPath "$(System.DefaultWorkingDirectory)/ScanResults/Xml-Report.zip" --ReportFormat xml
    
  3. Insert the following code to the .yml file, which extracts the XML report.

     - task: ExtractFiles@1
       displayName: Extract XML report
       inputs:
         archiveFilePatterns: '$(System.DefaultWorkingDirectory)/ScanResults/Xml-Report.zip'
         destinationFolder: '$(System.DefaultWorkingDirectory)/ScanResults'
         cleanDestinationFolder: false
    
  4. Insert the following code to the .yml file, which queries the XML report to evaluate if the scan has found any vulnerability with a priority score of 2 or higher.

     - task: PowerShell@2
       displayName: Query XML report
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Agent.ToolsDirectory)/clear-cli'
         script: |
           $resultCount = ./SkyAnalyzer.Interface.Console.exe --Interface Query --Method Execute --QueryDataSource "$(System.DefaultWorkingDirectory)/ScanResults/Report.xml" --QueryStatement "SELECT COUNT(ID) FROM Results WHERE PRIORITY <= 2"
           echo "##vso[task.setvariable variable=ResultCount]$resultCount"
    
  5. Insert the following code to the .yml file, which publishes the build artifact as a pipeline artifact named war if no vulnerability with a priority score of 2 or higher was found.

     - task: PublishPipelineArtifact@1
       displayName: Publish build artifact pipeline artifact
       condition: eq(variables['ResultCount'], '0')
       inputs:
         targetPath: '$(Build.SourcesDirectory)/target/ContosoWeb.war'
         artifact: 'war'
         publishLocation: 'pipeline'
    
  6. Insert the following code to the .yml file, which generates and downloads the HTML report when at least one vulnerability with a priority score of 2 or higher was found.

     - task: PowerShell@2
       displayName: Download HTML report
       condition: ne(variables['ResultCount'], '0')
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Agent.ToolsDirectory)/clear-cli'
         script: |
           ./SkyAnalyzer.Interface.Console.exe --Key $(ApiKey) --Interface Scan --Method Report --ScanId $(ScanId) --ReportPath "$(System.DefaultWorkingDirectory)/ScanResults/Html-Report.zip" --ReportFormat html
    
  7. Insert the following code to the .yml file, which extracts the HTML report when at least one vulnerability with a priority score of 2 or higher was found.

     - task: ExtractFiles@1
       displayName: Extract HTML report
       condition: ne(variables['ResultCount'], '0')
       inputs:
         archiveFilePatterns: '$(System.DefaultWorkingDirectory)/ScanResults/Html-Report.zip'
         destinationFolder: '$(System.DefaultWorkingDirectory)/ScanResults'
         cleanDestinationFolder: false
    
  8. Insert the following code to the .yml file, which publishes the HTML report as a pipeline artifact named report when at least one vulnerability with a priority score of 2 or higher was found.

     - task: PublishPipelineArtifact@1
       displayName: Publish HTML report as pipeline artifact
       condition: ne(variables['ResultCount'], '0')
       inputs:
         targetPath: '$(System.DefaultWorkingDirectory)/ScanResults/Report.html'
         artifact: 'report'
         publishLocation: 'pipeline'
    

Download the remediated source code and create a pull request in Azure Pipelines

  1. Open the .yml file of the Azure Pipeline, and locate an appropriate location to work with the remediated source code, such as after the pipeline failed security policy evaluation.

  2. Insert the following code to the .yml file, which configures Git on the Azure Pipelines agent and creates a branch for the remediated source code when at least one vulnerability with a priority score of 2 or higher was found..

     - task: PowerShell@2
       displayName: Configure Git
       condition: ne(variables['ResultCount'], '0')
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Build.SourcesDirectory)'
         script: |
           # Replace <UserEmail> with the user email to use for Git
           $UserEmail = "<UserEmail>"
           # Replace <UserName> with the user name to use for Git
           $UserName = "<UserName>"
           git config --global user.email "$UserEmail"
           git config --global user.name "$UserName"
           git checkout -b scan-$(ScanId)
    
  3. Insert the following code to the .yml file, which generates and downloads the remediated source code when at least one vulnerability with a priority score of 2 or higher was found.

     - task: PowerShell@2
       displayName: Download remediated source code
       condition: ne(variables['ResultCount'], '0')
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Agent.ToolsDirectory)/clear-cli'
         script: |
           ./SkyAnalyzer.Interface.Console.exe --Key $(ApiKey) --Interface Scan --Method Remediate --ScanId $(ScanId) --RemediatedSourceCodePath "$(System.DefaultWorkingDirectory)/ScanResults/RemediatedSource.zip" --RemediationOption 0
    
  4. Insert the following code to the .yml file, which extracts the remediated source code over the original source code when at least one vulnerability with a priority score of 2 or higher was found.

     - task: ExtractFiles@1
       displayName: Extract remediated source code
       condition: ne(variables['ResultCount'], '0')
       inputs:
         archiveFilePatterns: '$(System.DefaultWorkingDirectory)/ScanResults/RemediatedSource.zip'
         destinationFolder: '$(Build.SourcesDirectory)'
         cleanDestinationFolder: false
    
  5. Insert the following code to the .yml file, which commits the remediated source code to a branch when at least one vulnerability with a priority score of 2 or higher was found.

     - task: PowerShell@2
       displayName: Commit and push remediated source code
       condition: ne(variables['ResultCount'], '0')
       inputs:
         targetType: 'inline'
         workingDirectory: '$(Build.SourcesDirectory)'
         script: |
           # Replace <AplPath> with Application Protection Library files suitable for the framework of the project
           AplPath="<AplPath>"
           git add **/$AplPath
           git commit -m "Instant Fixes from scan $(ScanId)"
           git push -u origin scan-$(ScanId)
    
  6. Insert the following code to the .yml file, which fails the pipeline when at least one vulnerability with a priority score of 2 or higher was found.

     - task: PowerShell@2
       displayName: Fail pipeline
       condition: ne(variables['ResultCount'], '0')
       inputs:
         targetType: 'inline'
         script: |
           [Console]::Error.WriteLine('This build did not pass the scan criteria.')
         failOnStderr: true
    
  7. Navigate to the Repos > Pull requests section of the Azure DevOps project, and create a pull request from the branch containing the remediated source code.