diff --git a/.azure-pipelines/templates/debricked-oss-scan.yml b/.azure-pipelines/templates/debricked-oss-scan.yml new file mode 100644 index 0000000..41b6e8c --- /dev/null +++ b/.azure-pipelines/templates/debricked-oss-scan.yml @@ -0,0 +1,59 @@ +# File: templates/debricked-oss-scan.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: workingDirectory + default: '' +- name: jdkVersion + default: '17' +- name: jdkArch + default: 'x64' +- name: debrickedToken + +jobs: +- job: DebrickedSCAScan + pool: ${{ parameters.pool }} + steps: + - task: Bash@3 + displayName: 'Linux: Set environment variables manually' + condition: eq( variables['Agent.OS'], 'Linux' ) + inputs: + targetType: 'inline' + script: | + cd ~ + echo "##vso[task.setvariable variable=HOME]$(pwd)" + echo "##vso[task.setvariable variable=USER]$(whoami)" + echo "##vso[task.setvariable variable=JAVA_HOME_17_X64]/usr/lib/jvm/java-17-openjdk-amd64" + echo "##vso[task.setvariable variable=JAVA_HOME]/usr/lib/jvm/java-17-openjdk-amd64" + - task: JavaToolInstaller@0 + inputs: + versionSpec: ${{ parameters.jdkVersion }} + jdkArchitectureOption: ${{ parameters.jdkArch }} + jdkSourceOption: PreInstalled + - task: Gradle@3 + inputs: + gradleWrapperFile: 'gradlew' + workingDirectory: '.' + tasks: 'build' + publishJUnitResults: true + testResultsFiles: '**/TEST-*.xml' + testRunTitle: 'Unit Tests' + javaHomeOption: 'JDKVersion' + jdkVersionOption: '1.17' + sonarQubeRunAnalysis: false + spotBugsAnalysis: false + - task: DebrickedInstaller@0 + inputs: + version: 'latest' + - task: PowerShell@2 + displayName: 'Debricked SCA Scan' + inputs: + targetType: 'inline' + script: | + debricked scan --callgraph -r "OctaneDemoApp" --access-token="${env:DEBRICKED_TOKEN}" -e "build.gradle" -e "*/**.lock" -e "**/build/classes/test/**" -e "**/target/classes/test-classes/**" . + workingDirectory: ${{ parameters.workingDirectory }} + env: + DEBRICKED_TOKEN: ${{ parameters.debrickedToken }} diff --git a/.azure-pipelines/templates/deploy-to-azure.yml b/.azure-pipelines/templates/deploy-to-azure.yml new file mode 100644 index 0000000..e69531b --- /dev/null +++ b/.azure-pipelines/templates/deploy-to-azure.yml @@ -0,0 +1,59 @@ +# File: templates/deploy-to-azure.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: projectName +- name: srcProject + default: '**/*.csproj' +- name: dotnetVersion + default: '6.x' +- name: buildConfiguration + default: 'Debug' +- name: azureSubscription +- name: azureDbServer +- name: azureDbPort + default: 1433 +- name: azureDbUser +- name: azureDbPassword + +jobs: +- job: Build + pool: ${{ parameters.pool }} + steps: + - task: UseDotNet@2 + inputs: + version: ${{ parameters.dotnetVersion }} + - task: DotNetCoreCLI@2 + displayName: 'dotnet build' + inputs: + command: 'build' + configuration: ${{ parameters.buildConfiguration }} + projects: ${{ parameters.srcProject }} + - task: DotNetCoreCLI@2 + displayName: 'Create migration' + inputs: + command: custom + custom: ef + #arguments: 'migrations script -i -p InsecureWebApp -o $(Build.ArtifactStagingDirectory)/Migrations/migration.sql' + arguments: format('migrations script -i -p {0} -o {1}', parameters.projectName, $(Build.ArtifactStagingDirectory)/Migrations/migration.sql) + - task: SqlAzureDacpacDeployment@1 + inputs: + azureSubscription: ${{ parameters.azureSubscription }} + AuthenticationType: 'connectionString' + #ConnectionString: 'Data Source=tcp:$(AzureDBServer),1433;Initial Catalog=$(AzureDBName);User Id=$(AzureDBUser);Password=$(AzureDBPassword)' + ConnectionString: format('Data Source=tcp:{0},{1};Initial Catalog={2};User Id={3};Password={4}', parameters.azureDbServer, parameters.azureDbPort, parameters.azureDbUser, parameters.azureDbPassword) + deployType: 'SqlTask' + SqlFile: '$(Build.ArtifactStagingDirectory)/Migrations/migration.sql' + IpDetectionMethod: 'AutoDetect' + - task: AzureRmWebAppDeployment@4 + inputs: + ConnectionType: 'AzureRM' + azureSubscription: ${{ parameters.azureSubscription }} + appType: 'webApp' + WebAppName: 'iwanet' + #packageForLinux: '$(Pipeline.Workspace)/InsecureWebApp.zip' + packageForWindows: format('{0}/{1}.zip', $(Pipeline.Workspace), parameters.projectName) + #JSONFiles: 'appsettings.json' \ No newline at end of file diff --git a/.azure-pipelines/templates/dotnet-build-and-test.yml b/.azure-pipelines/templates/dotnet-build-and-test.yml new file mode 100644 index 0000000..6230e0f --- /dev/null +++ b/.azure-pipelines/templates/dotnet-build-and-test.yml @@ -0,0 +1,47 @@ +# File: templates/dotnet-build-and-test.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: srcProject + default: '**/*.csproj' +- name: testProject + default: '' +- name: dotnetVersion + default: '6.x' +- name: buildConfiguration + default: 'Debug' +- name: runTests + type: boolean + default: true + +jobs: +- job: Build + pool: ${{ parameters.pool }} + steps: + - task: UseDotNet@2 + inputs: + version: ${{ parameters.dotnetVersion }} + - task: DotNetCoreCLI@2 + displayName: 'dotnet build' + inputs: + command: 'build' + configuration: ${{ parameters.buildConfiguration }} + projects: ${{ parameters.srcProject }} + +- job: UnitTest + dependsOn: Build + condition: eq('${{ parameters.runTests }}', true) + pool: ${{ parameters.pool }} + steps: + - task: UseDotNet@2 + inputs: + version: ${{ parameters.dotnetVersion }} + - task: DotNetCoreCLI@2 + displayName: 'dotnet test' + inputs: + command: 'test' + configuration: ${{ parameters.buildConfiguration }} + projects: ${{ parameters.testProject }} \ No newline at end of file diff --git a/.azure-pipelines/templates/fod-dast-scan.yml b/.azure-pipelines/templates/fod-dast-scan.yml new file mode 100644 index 0000000..b01ee9c --- /dev/null +++ b/.azure-pipelines/templates/fod-dast-scan.yml @@ -0,0 +1,135 @@ +# File: templates/fod-dast-scan.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: workingDirectory + default: '' +- name: jdkVersion + default: '17' +- name: jdkArch + default: 'x64' +- name: fodApiUrl + default: 'https://api.ams.fortify.com' +- name: fodClientId +- name: fodClientSecret +- name: fodAppName +- name: fodReleaseName +- name: fodParentReleaseName + default: 'main' +- name: fodServiceConnection + default: 'FortifyOnDemandServiceConnection-OctaneDemoApp' + +jobs: +- job: FoDDynamicScan + pool: ${{ parameters.pool }} + steps: + - task: Bash@3 + displayName: 'Linux: Set environment variables manually' + condition: eq( variables['Agent.OS'], 'Linux' ) + inputs: + targetType: 'inline' + script: | + cd ~ + echo "##vso[task.setvariable variable=HOME]$(pwd)" + echo "##vso[task.setvariable variable=USER]$(whoami)" + echo "##vso[task.setvariable variable=JAVA_HOME_17_X64]/usr/lib/jvm/java-17-openjdk-amd64" + echo "##vso[task.setvariable variable=JAVA_HOME]/usr/lib/jvm/java-17-openjdk-amd64" + - task: JavaToolInstaller@0 + inputs: + versionSpec: ${{ parameters.jdkVersion }} + jdkArchitectureOption: ${{ parameters.jdkArch }} + jdkSourceOption: PreInstalled + - task: FcliInstaller@0 + inputs: + version: 'latest' + - task: PowerShell@2 + displayName: 'FoD Check Release' + inputs: + targetType: 'inline' + script: | + $App="${env:FOD_APP_NAME}" + $Rel="${env:FOD_RELEASE_NAME}" + if (${env:FORTIFY_APP_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_APP_NAME to ${env:FORTIFY_APP_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${env:FORTIFY_APP_NAME_OVERRIDE}" + $App="${env:FORTIFY_APP_NAME_OVERRIDE}" + } else { + Write-Host "##[command]Using FORTIFY_APP_NAME ${App}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${App}" + } + if (${env:FORTIFY_RELEASE_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_RELEASE_NAME to ${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + $Rel=${env:FORTIFY_RELEASE_NAME_OVERRIDE} + } else { + Write-Host "##[debug]Using FORTIFY_RELEASE_NAME ${Rel}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${Rel}" + } + Write-Host "##[command]fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines" + fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines + Write-Host "##[command]fcli fod release list --app="${App}" --session=azure-pipelines" + fcli fod release list --app="${App}" --session=azure-pipelines + Write-Host "##[command]fcli fod release create ""${App}:${Rel}"" --description=""Created automatically from Azure DevOps"" --copy-from=""${App}:${env:FOD_PARENT_RELEASE_NAME}"" --status=Development --skip-if-exists -o expr=""{releaseId}"" --session=azure-pipelines" + $RelId=(fcli fod release create "${App}:${Rel}" --description="Created automatically from Azure DevOps" --copy-from="${App}:${env:FOD_PARENT_RELEASE_NAME}" --status=Development --skip-if-exists -o expr="{releaseId}" --session=azure-pipelines) + Write-Host "##[debug]Setting fodReleaseId to $RelId" + Write-Host "##vso[task.setvariable variable=fodReleaseId]$RelId" + + Write-Host "##[command]`$AssessmentTypeId=(fcli fod release lsat --release=""${App}:${Rel}"" --query='name=="DAST Automated"' -o expr=""{assessmentTypeId}"" --session=azure-pipelines" + $AssessmentTypeId=(fcli fod release lsat --release="${App}:${Rel}" --query='name=="DAST Automated"' -o expr="{assessmentTypeId}" --session=azure-pipelines) + Write-Host "##[debug]Setting fodAssessmentTypeId to $AssessmentTypeId" + Write-Host "##vso[task.setvariable variable=fodAssessmentTypeId]$AssessmentTypeId" + Write-Host "##[command]`$IsPassed=(fcli fod release lsat --release=""${App}:${Rel}"" --query='name=="DAST Automated"' -o expr=""{entitlementId}"" --session=azure-pipelines" + $EntitlementId=(fcli fod release lsat --release="${App}:${Rel}" --query='name=="DAST Automated"' -o expr="{entitlementId}" --session=azure-pipelines) + Write-Host "##[debug]Setting fodEntitlementId to $EntitlementId" + Write-Host "##vso[task.setvariable variable=fodEntitlementId]$EntitlementId" + showWarnings: true + env: + FOD_API_URL: ${{ parameters.fodApiUrl }} + FOD_CLIENT_ID: ${{ parameters.fodClientId }} + FOD_CLIENT_SECRET: ${{ parameters.fodClientSecret }} + FOD_APP_NAME: ${{ parameters.fodAppName }} + FOD_RELEASE_NAME: ${{ parameters.fodReleaseName }} + FOD_PARENT_RELEASE_NAME: ${{ parameters.fodParentReleaseName }} + # Uncomment to use Fortify Azure DevOps extension for DAST scan + - task: FortifyDASTAutomated@2 + displayName: 'FoD DAST Scan' + condition: eq(variables['Build.SourceBranch'], 'refs/heads/main') + timeoutInMinutes: 120 + inputs: + FodConnection: 'FortifyOnDemandServiceConnection-OctaneDemoApp' + ReleaseOptions: '0' + ReleaseId: $(fodReleaseId) + AssessmentTypeId: $(fodAssessmentTypeId) + EntitlementId: $(fodEntitlementId) + EntitlementFrequencyType: $(fodReleaseId) + OverrideScanSettings: '2' + PolicyFailAction: '0' + # Uncomment to use fcli for SAST scan +# - task: PowerShell@2 +# displayName: 'FoD DAST Scan' +# condition: eq(variables['Build.SourceBranch'], 'refs/heads/main') +# timeoutInMinutes: 120 +# inputs: +# targetType: 'inline' +# script: | +# Write-Host "##[command]fcli fod dast-scan start --release=$(fodReleaseId) --store=curScan --session=azure-pipelines" +# fcli fod dast-scan start --release=$(fodReleaseId) --store=curScan --session=azure-pipelines +# Start-Sleep -Seconds 5 +# $ScanId=(fcli util var get ::curScan::) +# Write-Host "##[debug]Scan Id is: $ScanId" +# Write-Host "##vso[task.setvariable variable=fodScanId]$ScanId" +# Write-Host "##[command]fcli fod dast-scan wait-for ::curScan:: --session=azure-pipelines" +# fcli fod dast-scan wait-for ::curScan:: --session=azure-pipelines +# workingDirectory: ${{ parameters.workingDirectory }} +# env: +# FOD_RELEASE_ID: $(fodReleaseId) + - task: PowerShell@2 + displayName: 'FoD Logout' + inputs: + targetType: 'inline' + script: | + Write-Host "##[command]fcli fod session logout --session=azure-pipelines" + fcli fod session logout --session=azure-pipelines \ No newline at end of file diff --git a/.azure-pipelines/templates/fod-oss-scan.yml b/.azure-pipelines/templates/fod-oss-scan.yml new file mode 100644 index 0000000..82fad9b --- /dev/null +++ b/.azure-pipelines/templates/fod-oss-scan.yml @@ -0,0 +1,120 @@ +# File: templates/fod-oss-scan.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: workingDirectory + default: '' +- name: jdkVersion + default: '17' +- name: jdkArch + default: 'x64' +- name: fodApiUrl + default: 'https://api.ams.fortify.com' +- name: fodClientId +- name: fodClientSecret +- name: fodAppName +- name: fodReleaseName +- name: fodParentReleaseName + default: 'main' + +jobs: +- job: FoDOSSScan + pool: ${{ parameters.pool }} + steps: + - task: Bash@3 + displayName: 'Linux: Set environment variables manually' + condition: eq( variables['Agent.OS'], 'Linux' ) + inputs: + targetType: 'inline' + script: | + cd ~ + echo "##vso[task.setvariable variable=HOME]$(pwd)" + echo "##vso[task.setvariable variable=USER]$(whoami)" + echo "##vso[task.setvariable variable=JAVA_HOME_17_X64]/usr/lib/jvm/java-17-openjdk-amd64" + echo "##vso[task.setvariable variable=JAVA_HOME]/usr/lib/jvm/java-17-openjdk-amd64" + - task: JavaToolInstaller@0 + inputs: + versionSpec: ${{ parameters.jdkVersion }} + jdkArchitectureOption: ${{ parameters.jdkArch }} + jdkSourceOption: PreInstalled + - task: FcliInstaller@0 + inputs: + version: 'latest' + - task: DebrickedInstaller@0 + inputs: + version: 'latest' + - task: PowerShell@2 + displayName: 'FoD Check Release' + inputs: + targetType: 'inline' + script: | + $App="${env:FOD_APP_NAME}" + $Rel="${env:FOD_RELEASE_NAME}" + if (${env:FORTIFY_APP_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_APP_NAME to ${env:FORTIFY_APP_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${env:FORTIFY_APP_NAME_OVERRIDE}" + $App="${env:FORTIFY_APP_NAME_OVERRIDE}" + } else { + Write-Host "##[command]Using FORTIFY_APP_NAME ${App}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${App}" + } + if (${env:FORTIFY_RELEASE_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_RELEASE_NAME to ${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + $Rel=${env:FORTIFY_RELEASE_NAME_OVERRIDE} + } else { + Write-Host "##[debug]Using FORTIFY_RELEASE_NAME ${Rel}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${Rel}" + } + Write-Host "##[command]fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines" + fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines + Write-Host "##[command]fcli fod release list --app="${App}" --session=azure-pipelines" + fcli fod release list --app="${App}" --session=azure-pipelines + Write-Host "##[command]fcli fod release create ""${App}:${Rel}"" --description=""Created automatically from Azure DevOps"" --copy-from=""${App}:${env:FOD_PARENT_RELEASE_NAME}"" --status=Development --skip-if-exists -o expr=""{releaseId}"" --session=azure-pipelines" + $RelId=(fcli fod release create "${App}:${Rel}" --description="Created automatically from Azure DevOps" --copy-from="${App}:${env:FOD_PARENT_RELEASE_NAME}" --status=Development --skip-if-exists -o expr="{releaseId}" --session=azure-pipelines) + Write-Host "##[debug]Setting fodReleaseId to $RelId" + Write-Host "##vso[task.setvariable variable=fodReleaseId]$RelId" + showWarnings: true + env: + FOD_API_URL: ${{ parameters.fodApiUrl }} + FOD_CLIENT_ID: ${{ parameters.fodClientId }} + FOD_CLIENT_SECRET: ${{ parameters.fodClientSecret }} + FOD_APP_NAME: ${{ parameters.fodAppName }} + FOD_RELEASE_NAME: ${{ parameters.fodReleaseName }} + FOD_PARENT_RELEASE_NAME: ${{ parameters.fodParentReleaseName }} + - task: PowerShell@2 + displayName: 'FoD OSS Scan' + inputs: + targetType: 'inline' + script: | + if (Test-Path ${env:PACKAGE_FILE}) { + Remove-Item ${env:PACKAGE_FILE} -Verbose + } + Write-Host "##[command]debricked resolve $(Build.SourcesDirectory)" + debricked resolve --regenerate 2 $(Build.SourcesDirectory) + Get-Child-Item -Path $(Build.SourcesDirectory) + Write-Host "##[command]Compress-Archive -Path $(Build.SourcesDirectory)/gradle.debricked.lock -DestinationPath ${env:PACKAGE_FILE}" + Compress-Archive -Path $(Build.SourcesDirectory)/gradle.debricked.lock -DestinationPath ${env:PACKAGE_FILE} + Write-Host "##[command]fcli fod oss-scan start --release=$(fodReleaseId) --file=${env:PACKAGE_FILE} --store=curScan --session=azure-pipelines" + fcli fod oss-scan start --release=$(fodReleaseId) --file=${env:PACKAGE_FILE} --store=curScan --session=azure-pipelines + Start-Sleep -Seconds 5 + $ScanId=(fcli util var get ::curScan::) + Write-Host "##[debug]Scan Id is: $ScanId" + Write-Host "##vso[task.setvariable variable=fodScanId]$ScanId" + Write-Host "##[command]fcli fod oss-scan wait-for ::curScan:: --session=azure-pipelines" + fcli fod oss-scan wait-for ::curScan:: --session=azure-pipelines + workingDirectory: ${{ parameters.workingDirectory }} + env: + PACKAGE_FILE: "$(Build.SourcesDirectory)/package.zip" + FOD_RELEASE_ID: $(fodReleaseId) + FOD_SCAN_NOTES: "Triggered by Azure DevOps Pipelines" + - task: PowerShell@2 + displayName: 'FoD Logout' + inputs: + targetType: 'inline' + script: | + Write-Host "##[command]fcli fod session logout --session=azure-pipelines" + fcli fod session logout --session=azure-pipelines diff --git a/.azure-pipelines/templates/fod-sast-scan.yml b/.azure-pipelines/templates/fod-sast-scan.yml new file mode 100644 index 0000000..9193199 --- /dev/null +++ b/.azure-pipelines/templates/fod-sast-scan.yml @@ -0,0 +1,136 @@ +# File: templates/fod-sast-scan.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: workingDirectory + default: '' +- name: projectFile + default: 'build.gradle' +- name: jdkVersion + default: '17' +- name: jdkArch + default: 'x64' +- name: fodApiUrl + default: 'https://api.ams.fortify.com' +- name: fodClientId +- name: fodClientSecret +- name: fodAppName +- name: fodReleaseName +- name: fodParentReleaseName + default: 'main' +- name: fodServiceConnection + default: 'FortifyOnDemandServiceConnection-OctaneDemoApp' + +jobs: +- job: FoDStaticScan + pool: ${{ parameters.pool }} + steps: + - task: Bash@3 + displayName: 'Linux: Set environment variables manually' + condition: eq( variables['Agent.OS'], 'Linux' ) + inputs: + targetType: 'inline' + script: | + cd ~ + echo "##vso[task.setvariable variable=HOME]$(pwd)" + echo "##vso[task.setvariable variable=USER]$(whoami)" + echo "##vso[task.setvariable variable=JAVA_HOME_17_X64]/usr/lib/jvm/java-17-openjdk-amd64" + echo "##vso[task.setvariable variable=JAVA_HOME]/usr/lib/jvm/java-17-openjdk-amd64" + - task: JavaToolInstaller@0 + inputs: + versionSpec: ${{ parameters.jdkVersion }} + jdkArchitectureOption: ${{ parameters.jdkArch }} + jdkSourceOption: PreInstalled + - task: FcliInstaller@0 + inputs: + version: 'latest' + - task: PowerShell@2 + displayName: 'FoD Check Release' + inputs: + targetType: 'inline' + script: | + $App="${env:FOD_APP_NAME}" + $Rel="${env:FOD_RELEASE_NAME}" + if (${env:FORTIFY_APP_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_APP_NAME to ${env:FORTIFY_APP_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${env:FORTIFY_APP_NAME_OVERRIDE}" + $App="${env:FORTIFY_APP_NAME_OVERRIDE}" + } else { + Write-Host "##[command]Using FORTIFY_APP_NAME ${App}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${App}" + } + if (${env:FORTIFY_RELEASE_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_RELEASE_NAME to ${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + $Rel=${env:FORTIFY_RELEASE_NAME_OVERRIDE} + } else { + Write-Host "##[debug]Using FORTIFY_RELEASE_NAME ${Rel}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${Rel}" + } + Write-Host "##[command]fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines" + fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines + Write-Host "##[command]fcli fod release list --app="${App}" --session=azure-pipelines" + fcli fod release list --app="${App}" --session=azure-pipelines + Write-Host "##[command]fcli fod release create ""${App}:${Rel}"" --description=""Created automatically from Azure DevOps"" --copy-from=""${App}:${env:FOD_PARENT_RELEASE_NAME}"" --status=Development --skip-if-exists -o expr=""{releaseId}"" --session=azure-pipelines" + $RelId=(fcli fod release create "${App}:${Rel}" --description="Created automatically from Azure DevOps" --copy-from="${App}:${env:FOD_PARENT_RELEASE_NAME}" --status=Development --skip-if-exists -o expr="{releaseId}" --session=azure-pipelines) + Write-Host "##[debug]Setting fodReleaseId to $RelId" + Write-Host "##vso[task.setvariable variable=fodReleaseId]$RelId" + fcli tool sc-client install -y -d $(Build.SourcesDirectory)/sc-client + Write-Host "##vso[task.prependpath]$(Build.SourcesDirectory)/sc-client/bin" + showWarnings: true + env: + FOD_API_URL: ${{ parameters.fodApiUrl }} + FOD_CLIENT_ID: ${{ parameters.fodClientId }} + FOD_CLIENT_SECRET: ${{ parameters.fodClientSecret }} + FOD_APP_NAME: ${{ parameters.fodAppName }} + FOD_RELEASE_NAME: ${{ parameters.fodReleaseName }} + FOD_PARENT_RELEASE_NAME: ${{ parameters.fodParentReleaseName }} + # Uncomment to use Fortify Azure DevOps extension for SAST scan + - task: FortifyOnDemandStatic@9 + displayName: 'FoD SAST Scan' + inputs: + FortifyProjects: '.' + FodConnection: 'FortifyOnDemandServiceConnection-OctaneDemoApp' + ReleaseOptions: '0' + ReleaseId: $(fodReleaseId) + EntitlementSelection: '1' + EntitlementPreference: '1' + OverrideScanSettings: '2' + InProgressScanActionType: '2' + RemediationScanPreference: '2' + BuildType: 'gradle' + BuildCommand: 'clean build' + BuildFile: ${{ parameters.projectFile }} + PolicyFailAction: '0' + # Uncomment to use fcli for SAST scan +# - task: PowerShell@2 +# displayName: 'FoD SAST Scan' +# inputs: +# targetType: 'inline' +# script: | +# Write-Host "##[command]scancentral package -bt gradle -bf ${env:PROJ_FILE} -o ${env:PACKAGE_FILE} -oss" +# scancentral package -bt gradle -bf ${env:PROJ_FILE} -o ${env:PACKAGE_FILE} -oss +# Write-Host "##[command]fcli fod sast-scan start --release=$(fodReleaseId) --notes=""${env:FOD_SCAN_NOTES}"" --file=${env:PACKAGE_FILE} --store=curScan --session=azure-pipelines" +# fcli fod sast-scan start --release=$(fodReleaseId) --notes="${env:FOD_SCAN_NOTES}" -f=${env:PACKAGE_FILE} --store=curScan --session=azure-pipelines +# Start-Sleep -Seconds 5 +# $ScanId=(fcli util var get ::curScan::) +# Write-Host "##[debug]Scan Id is: $ScanId" +# Write-Host "##vso[task.setvariable variable=fodScanId]$ScanId" +# Write-Host "##[command]fcli fod sast-scan wait-for ::curScan:: --session=azure-pipelines" +# fcli fod sast-scan wait-for ::curScan:: --session=azure-pipelines +# workingDirectory: ${{ parameters.workingDirectory }} +# env: +# PROJ_FILE: ${{ parameters.projectFile }} +# FOD_RELEASE_ID: $(fodReleaseId) +# PACKAGE_FILE: "package.zip" +# FOD_SCAN_NOTES: "Triggered by Azure DevOps Pipelines" + - task: PowerShell@2 + displayName: 'FoD Logout' + inputs: + targetType: 'inline' + script: | + Write-Host "##[command]fcli fod session logout --session=azure-pipelines" + fcli fod session logout --session=azure-pipelines diff --git a/.azure-pipelines/templates/fod-security-gate.yml b/.azure-pipelines/templates/fod-security-gate.yml new file mode 100644 index 0000000..f379983 --- /dev/null +++ b/.azure-pipelines/templates/fod-security-gate.yml @@ -0,0 +1,124 @@ +# File: templates/fod-security-gate.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: workingDirectory + default: '' +- name: jdkVersion + default: '17' +- name: jdkArch + default: 'x64' +- name: fodApiUrl + default: 'https://api.ams.fortify.com' +- name: fodClientId +- name: fodClientSecret +- name: fodAppName +- name: fodReleaseName +- name: fodParentReleaseName + default: 'main' +- name: fodReportTemplate + default: 'HybridIssueDetail' +- name: reportDir + default: '$(Build.SourcesDirectory)/reports' +- name: reportFile + default: '$(Build.SourcesDirectory)/reports/main.html' + +jobs: +- job: FoDSecurityGate + pool: ${{ parameters.pool }} + steps: + - task: Bash@3 + displayName: 'Linux: Set environment variables manually' + condition: eq( variables['Agent.OS'], 'Linux' ) + inputs: + targetType: 'inline' + script: | + cd ~ + echo "##vso[task.setvariable variable=HOME]$(pwd)" + echo "##vso[task.setvariable variable=USER]$(whoami)" + echo "##vso[task.setvariable variable=JAVA_HOME_17_X64]/usr/lib/jvm/java-17-openjdk-amd64" + echo "##vso[task.setvariable variable=JAVA_HOME]/usr/lib/jvm/java-17-openjdk-amd64" + - task: JavaToolInstaller@0 + inputs: + versionSpec: ${{ parameters.jdkVersion }} + jdkArchitectureOption: ${{ parameters.jdkArch }} + jdkSourceOption: PreInstalled + - task: FcliInstaller@0 + inputs: + version: 'latest' + - task: PowerShell@2 + displayName: 'Validate Security Policy' + inputs: + targetType: 'inline' + script: | + $App="${env:FOD_APP_NAME}" + $Rel="${env:FOD_RELEASE_NAME}" + if (${env:FORTIFY_APP_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_APP_NAME to ${env:FORTIFY_APP_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${env:FORTIFY_APP_NAME_OVERRIDE}" + $App="${env:FORTIFY_APP_NAME_OVERRIDE}" + } else { + Write-Host "##[command]Using FORTIFY_APP_NAME ${App}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${App}" + } + if (${env:FORTIFY_RELEASE_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_RELEASE_NAME to ${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + $Rel=${env:FORTIFY_RELEASE_NAME_OVERRIDE} + } else { + Write-Host "##[debug]Using FORTIFY_RELEASE_NAME ${Rel}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${Rel}" + } + Write-Host "##[command]fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines" + fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines + + Write-Host "##[command]`$SecurityRating=(fcli fod release get ""${App}:${Rel}"" -o expr=""{rating}"" --session=azure-pipelines" + $SecurityRating=(fcli fod release get "${App}:${Rel}" -o expr="{rating}" --session=azure-pipelines) + Write-Host "##[command]`$IsPassed=(fcli fod release get ""${App}:${Rel}"" -o expr=""{isPassed}"" --session=azure-pipelines" + $IsPassed=(fcli fod release get "${App}:${Rel}" -o expr="{isPassed}" --session=azure-pipelines) + + Write-Host "##[debug]Release ""${App}:${Rel}"" Security Rating: ${SecurityRating}/5" + + if ($IsPassed) { + Write-Host "##[debug]Release ""${App}:${Rel}"" has passed security policy" + } else { + Write-Host "##[error]Release ""${App}:${Rel}"" failed security policy" + #exit 1 + } + + Write-Host "##[command]Creating FoD Report for Release" + fcli fod report create "${env:FOD_REPORT_NAME}" --format=html --release="${App}:${Rel}" --template="${env:FOD_REPORT_TEMPLATE}" --store=curReport --session=azure-pipelines + Start-Sleep -Seconds 10 + fcli fod report wait-for ::curReport:: --on-unknown-state=wait --session=azure-pipelines + New-Item -ItemType Directory -Force -Path ${env:FOD_REPORT_DIR} | Out-Null + fcli fod report download ::curReport:: --file=${env:FOD_REPORT_DIR}/${env:FOD_REPORT_NAME}.zip --session=azure-pipelines + Expand-Archive -Path ${env:FOD_REPORT_DIR}/${env:FOD_REPORT_NAME}.zip -DestinationPath ${env:FOD_REPORT_DIR} + Get-ChildItem -Path ${env:FOD_REPORT_DIR} -Filter '*.html' | Rename-Item -NewName { $_.Name -replace '_\d+' } + Remove-Item -Force ${env:FOD_REPORT_DIR}/${env:FOD_REPORT_NAME}.zip | Out-Null + fcli fod report delete ::curReport:: --session=azure-pipelines + + Write-Host "##[command]fcli fod session logout --session=azure-pipelines" + fcli fod session logout --session=azure-pipelines + showWarnings: true + env: + FOD_API_URL: ${{ parameters.fodApiUrl }} + FOD_CLIENT_ID: ${{ parameters.fodClientId }} + FOD_CLIENT_SECRET: ${{ parameters.fodClientSecret }} + FOD_APP_NAME: ${{ parameters.fodAppName }} + FOD_RELEASE_NAME: ${{ parameters.fodReleaseName }} + FOD_REPORT_TEMPLATE: ${{ parameters.fodReportTemplate }} + FOD_REPORT_DIR: ${{ parameters.reportDir }} + FOD_REPORT_NAME: "Report-$(Build.BuildId)" + - task: PublishBuildArtifacts@1 + condition: succeededOrFailed() + inputs: + pathToPublish: ${{ parameters.reportDir }} + artifactName: FortifyReports + - task: PublishHtmlReport@1 + condition: succeededOrFailed() + inputs: + tabName: 'Fortify Security Report' + reportDir: ${{ parameters.reportFile }} diff --git a/.azure-pipelines/templates/fod-to-octane.yml b/.azure-pipelines/templates/fod-to-octane.yml new file mode 100644 index 0000000..7db37d9 --- /dev/null +++ b/.azure-pipelines/templates/fod-to-octane.yml @@ -0,0 +1,125 @@ +# File: templates/fod-to-octane.yml + +# defaults for any parameters that aren't specified +parameters: + - name: 'pool' + type: object + default: {} + - name: workingDirectory + default: '' + - name: jdkVersion + default: '17' + - name: jdkArch + default: 'x64' + - name: fodBaseUrl + default: 'https://ams.fortify.com' + - name: fodApiUrl + default: 'https://api.ams.fortify.com' + - name: fodTenant + - name: fodClientId + - name: fodClientSecret + - name: fodAppName + - name: fodReleaseName + - name: octaneBaseUrl + default: 'https://almoctane-ams.saas.microfocus.com/' + - name: octaneSharedSpaceId + - name: octaneWorkspaceId + - name: octaneClientId + - name: octaneClientSecret + - name: configDir + default: 'etc' + - name: configFile + default: 'FoDToOctane.xml' + +jobs: + - job: FoDIssuesToOctaneDefects + pool: ${{ parameters.pool }} + steps: + - task: Bash@3 + displayName: 'Linux: Set environment variables manually' + condition: eq( variables['Agent.OS'], 'Linux' ) + inputs: + targetType: 'inline' + script: | + cd ~ + echo "##vso[task.setvariable variable=HOME]$(pwd)" + echo "##vso[task.setvariable variable=USER]$(whoami)" + echo "##vso[task.setvariable variable=JAVA_HOME_17_X64]/usr/lib/jvm/java-17-openjdk-amd64" + echo "##vso[task.setvariable variable=JAVA_HOME]/usr/lib/jvm/java-17-openjdk-amd64" + - task: JavaToolInstaller@0 + inputs: + versionSpec: ${{ parameters.jdkVersion }} + jdkArchitectureOption: ${{ parameters.jdkArch }} + jdkSourceOption: PreInstalled + - task: FcliInstaller@0 + inputs: + version: 'latest' + - task: PowerShell@2 + displayName: 'Install FortifyBugTrackerUtility' + inputs: + targetType: 'inline' + script: | + fcli tool definitions update + $ftbuDir = Join-Path -Path $(Build.BinariesDirectory) -ChildPath "ftbu" + fcli tool fbtu install -y -d $ftbuDir + $ftbuBinDir = Join-Path -Path "$ftbuDir" -ChildPath "bin" + Write-Host "##vso[task.prependpath]$ftbuBinDir" + - task: PowerShell@2 + displayName: 'FoD Check Release' + inputs: + targetType: 'inline' + script: | + $App="${env:FOD_APP_NAME}" + $Rel="${env:FOD_RELEASE_NAME}" + if (${env:FORTIFY_APP_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_APP_NAME to ${env:FORTIFY_APP_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${env:FORTIFY_APP_NAME_OVERRIDE}" + $App="${env:FORTIFY_APP_NAME_OVERRIDE}" + } else { + Write-Host "##[command]Using FORTIFY_APP_NAME ${App}" + Write-Host "##vso[task.setvariable variable=FORTIFY_APP_NAME]${App}" + } + if (${env:FORTIFY_RELEASE_NAME_OVERRIDE}) { + Write-Host "##[debug]Overriding FORTIFY_RELEASE_NAME to ${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${env:FORTIFY_RELEASE_NAME_OVERRIDE}" + $Rel=${env:FORTIFY_RELEASE_NAME_OVERRIDE} + } else { + Write-Host "##[debug]Using FORTIFY_RELEASE_NAME ${Rel}" + Write-Host "##vso[task.setvariable variable=FORTIFY_RELEASE_NAME]${Rel}" + } + Write-Host "##[command]fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines" + fcli fod session login --url=""${env:FOD_API_URL}"" --client-id=""${env:FOD_CLIENT_ID}"" --client-secret=""${env:FOD_CLIENT_SECRET}"" --session=azure-pipelines + Write-Host "##[command]fcli fod release get ""${App}:${Rel}"" -o expr=""{releaseId}"" --session=azure-pipelines" + $RelId=(fcli fod release get "${App}:${Rel}" -o expr="{releaseId}" --session=azure-pipelines) + Write-Host "##[debug]Setting fodReleaseId to $RelId" + Write-Host "##vso[task.setvariable variable=fodReleaseId]$RelId" + showWarnings: true + env: + FOD_API_URL: ${{ parameters.fodApiUrl }} + FOD_CLIENT_ID: ${{ parameters.fodClientId }} + FOD_CLIENT_SECRET: ${{ parameters.fodClientSecret }} + FOD_APP_NAME: ${{ parameters.fodAppName }} + FOD_RELEASE_NAME: ${{ parameters.fodReleaseName }} + - task: PowerShell@2 + displayName: 'Run FortifyBugTrackerUtility' + inputs: + targetType: 'inline' + script: | + $ftbuJar = Join-Path -Path $(Build.BinariesDirectory) -ChildPath "ftbu" | Join-Path -ChildPath "FortifyBugTrackerUtility.jar" + $ftbuConfig = Join-Path -Path $(Build.SourcesDirectory) -ChildPath "${env:CONFIG_DIR}" | Join-Path -ChildPath "${env:CONFIG_FILE}" + Write-Host "##[command]java -jar $ftbuJar -configFile $ftbuConfig -FoDBaseUrl ""${env:FOD_BASE_URL}"" -FoDTenant ""${env:FOD_TENANT}"" -FoDClientId ""${env:FOD_CLIENT_ID}"" -FoDClientSecret ""${env:FOD_CLIENT_SECRET}"" -FoDReleaseId ""${env:FOD_RELEASE_ID}"" -OctaneBaseUrl ""${env:OCTANE_BASE_URL}"" -OctaneSharedSpaceUid ""${env:OCTANE_SHARED_SPACE_ID}"" -OctaneWorkspaceId ""${env:OCTANE_WORKSPACE_ID}"" -OctaneClientId ""${env:OCTANE_CLIENT_ID}"" -OctaneClientSecret ""${env:OCTANE_CLIENT_SECRET}"" " + java -jar $ftbuJar -configFile $ftbuConfig -FoDBaseUrl "${env:FOD_BASE_URL}" -FoDTenant "${env:FOD_TENANT}" -FoDClientId "${env:FOD_CLIENT_ID}" -FoDClientSecret "${env:FOD_CLIENT_SECRET}" -FoDReleaseId "${env:FOD_RELEASE_ID}" -OctaneBaseUrl "${env:OCTANE_BASE_URL}" -OctaneSharedSpaceUid "${env:OCTANE_SHARED_SPACE_ID}" -OctaneWorkspaceId "${env:OCTANE_WORKSPACE_ID}" -OctaneClientId "${env:OCTANE_CLIENT_ID}" -OctaneClientSecret "${env:OCTANE_CLIENT_SECRET}" + workingDirectory: ${{ parameters.workingDirectory }} + env: + FOD_BASE_URL: ${{ parameters.fodBaseUrl }} + FOD_TENANT: ${{ parameters.fodTenant }} + FOD_CLIENT_ID: ${{ parameters.fodClientId }} + FOD_CLIENT_SECRET: ${{ parameters.fodClientSecret }} + FOD_RELEASE_ID: $(fodReleaseId) + OCTANE_BASE_URL: ${{ parameters.octaneBaseUrl }} + OCTANE_SHARED_SPACE_ID: ${{ parameters.octaneSharedSpaceId }} + OCTANE_WORKSPACE_ID: ${{ parameters.octaneWorkspaceId }} + OCTANE_CLIENT_ID: ${{ parameters.octaneClientId }} + OCTANE_CLIENT_SECRET: ${{ parameters.octaneClientSecret }} + CONFIG_DIR: ${{ parameters.configDir }} + CONFIG_FILE: ${{ parameters.configFile }} diff --git a/.azure-pipelines/templates/gradle-build-and-test.yml b/.azure-pipelines/templates/gradle-build-and-test.yml new file mode 100644 index 0000000..84d0ee8 --- /dev/null +++ b/.azure-pipelines/templates/gradle-build-and-test.yml @@ -0,0 +1,44 @@ +# File: templates/gradle-dotnet-build-and-test.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: jdkVersion + default: '17' +- name: jdkArch + default: 'x64' + +jobs: +- job: Build + pool: ${{ parameters.pool }} + steps: + - task: Bash@3 + displayName: 'Linux: Set environment variables manually' + condition: eq( variables['Agent.OS'], 'Linux' ) + inputs: + targetType: 'inline' + script: | + cd ~ + echo "##vso[task.setvariable variable=HOME]$(pwd)" + echo "##vso[task.setvariable variable=USER]$(whoami)" + echo "##vso[task.setvariable variable=JAVA_HOME_17_X64]/usr/lib/jvm/java-17-openjdk-amd64" + echo "##vso[task.setvariable variable=JAVA_HOME]/usr/lib/jvm/java-17-openjdk-amd64" + - task: JavaToolInstaller@0 + inputs: + versionSpec: ${{ parameters.jdkVersion }} + jdkArchitectureOption: ${{ parameters.jdkArch }} + jdkSourceOption: PreInstalled + - task: Gradle@3 + inputs: + gradleWrapperFile: 'gradlew' + workingDirectory: '.' + tasks: 'build' + publishJUnitResults: true + testResultsFiles: '**/TEST-*.xml' + testRunTitle: 'Unit Tests' + javaHomeOption: 'JDKVersion' + jdkVersionOption: '1.17' + sonarQubeRunAnalysis: false + spotBugsAnalysis: false \ No newline at end of file diff --git a/.azure-pipelines/templates/simulate-deployment.yml b/.azure-pipelines/templates/simulate-deployment.yml new file mode 100644 index 0000000..a707581 --- /dev/null +++ b/.azure-pipelines/templates/simulate-deployment.yml @@ -0,0 +1,20 @@ +# File: templates/simulate-deployment.yml + +# defaults for any parameters that aren't specified +parameters: +- name: 'pool' + type: object + default: {} +- name: workingDirectory + default: $(Build.SourcesDirectory). + +jobs: +- job: Build + pool: ${{ parameters.pool }} + steps: + - task: CmdLine@2 + inputs: + script: | + echo "Deploying application..." + dir + workingDirectory: ${{ parameters.workingDirectory }} \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..47e9c4b --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,301 @@ +# Example Continuous Delivery Pipeline with Fortify on Demand (FoD) + +name: IWA-CD + +trigger: + batch: true + branches: + include: + - main + - develop + - feature/* + - release/* + exclude: + - experimental/* + paths: + exclude: + - README.md + - bin/* + - lib/* + - etc/* + - media/* + +pr: + branches: + include: + - main + - develop + paths: + exclude: + - README.md + - bin/* + - lib/* + - etc/* + - media/* + +variables: + # + # In order for the pipeline to execute successfully you should create and set the following variables in the Pipeline UI. + # + # For FoD: + # FOD_BASE_URL - FoD Base Url, e.g. "https://ams.fortify.com" + # FOD_API_URL - FoD API URL, e.g. "https://api.ams.fortify.com" + # FOD_TENANT - FoD Tenant Name + # FOD_CLIENT_ID - FoD API Client Id + # FOD_CLIENT_SECRET - FoD API Client Secret + # + # For Octane/ValueEdge if integration is used + # OCTANE_WORKSPACES - List of target ALM Octane/ValueEdge workspaces + # and the below if FortifyBugTrackerUtility is used: + # OCTANE_BASE_URL - ALM Octane/ValueEdge Base Url, e.g. "https://almoctane-ams.saas.microfocus.com/" + # OCTANE_CLIENT_ID - ALM Octane/ValueEdge API Client Id + # OCTANE_CLIENT_SECRET - ALM Octane/ValueEdge API Client Secret + # OCTANE_SHARED_SPACE_ID - ALM Octane/ValueEdge Shared Space Id + # OCTANE_WORKSPACE_ID - ALM Octane/ValueEdge Shared SpaceWorkspace Id + # + # For Debricked: + # DEBRICKED_TOKEN - Debricked Access Token + # + # + # The pipeline job templates make use of the Fortify CLI tool (https://github.com/fortify/fcli) and Debricked CLI tool (https://github.com/debricked/cli) + # There are tasks which make use of preview extensions (not published to the Azure DevOps marketplace) to install these tools included, e.g.: + # - FcliInstaller - https://github.com/fortify-presales/azure-pipelines-fcli-tasks + # - DebrickedInstaller - https://github.com/fortify-presales/azure-pipelines-debricked-tasks + # Follow the instructions on the GitHub repos to install these extensions. + # If you are using a self-hosted agent you can install the fcli and debricked tools yourselves, add to the path and comment out the these extension tasks. + # + # IMPORTANT: if using a self-hosted agent, please ensure a Java 17x64 SDK is installed and the environment variable JAVA_HOME_17_X64 is set to its location + + # Change these variables depending on which parts of the pipeline to execute: + - name: USE_FOD_SAST + value: true + - name: USE_FOD_OSS + value: false + - name: USE_DEBRICKED + value: true + - name: USE_FOD_DAST + value: true + - name: SYNC_ISSUES + value: true + + # + # By default the FoD/SSC application name is set to the name of the Git repository + # If you wish to override any of these please set the following variables from the pipelines UI: + # + # FORTIFY_APP_NAME_OVERRIDE + # FORTIFY_RELEASE_NAME_OVERRIDE + # + - name: FORTIFY_APP_NAME + value: $(Build.Repository.Name) + - name: FORTIFY_RELEASE_NAME + value: $[replace(variables['Build.SourceBranch'], 'refs/heads/', '')] + +stages: + + #- stage: ALMOctanePre + # displayName: 'ALM Octane Pre' + # jobs: + # - job: + # condition: always() + # pool: + # name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + # steps: + # - task: octane-start-task@2 + # inputs: + # OctaneServiceConnection: 'AzureExtensionPipelineServiceConnection-IWA' + # WorkspaceList: "$(OCTANE_WORKSPACES)" + # GithubRepositoryConnection: 'GitHubServiceConnection-IWA' + # CreatePipelineCheckbox: true + + # + # Build and Unit Test the application components + # + - stage: BuildAndUnitTest + displayName: 'Build and Unit Test' + jobs: + # Build IWA and run its tests + - template: '.azure-pipelines/templates/gradle-build-and-test.yml' + parameters: + # workingDirectory: '.' + # projectFile: 'build.gradle' + pool: + name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + # + # Software Composition Analysis - OSS Scan with Debricked + # + - stage: Debricked_SCA + displayName: 'Debricked SCA' + condition: eq(variables['USE_DEBRICKED'], 'true') + dependsOn: + - BuildAndUnitTest + jobs: + # Run Debricked OSS Scan on Project + - template: '.azure-pipelines/templates/debricked-oss-scan.yml' + parameters: + workingDirectory: '.' + debrickedToken: $(DEBRICKED_TOKEN) + pool: + name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + # + # Software Composition Analysis - OSS Scan with Fortify on Demand + # + - stage: FoD_OSS + displayName: 'FoD OSS' + condition: eq(variables['USE_FOD_OSS'], 'true') + dependsOn: + - BuildAndUnitTest + jobs: + # Run FoD OSS Scan on Project + - template: '.azure-pipelines/templates/fod-oss-scan.yml' + parameters: + workingDirectory: '.' + fodApiUrl: $(FOD_API_URL) + fodClientId: $(FOD_CLIENT_ID) + fodClientSecret: $(FOD_CLIENT_SECRET) + fodAppName: "$(FORTIFY_APP_NAME)" + fodReleaseName: "$(FORTIFY_RELEASE_NAME)" + pool: + name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + # + # Static Application Security Testing with Fortify on Demand + # + - stage: FoD_SAST + displayName: 'FoD SAST' + condition: eq(variables['USE_FOD_SAST'], 'true') + dependsOn: + - BuildAndUnitTest + jobs: + # Run FoD SAST Scan on Project + - template: '.azure-pipelines/templates/fod-sast-scan.yml' + parameters: + workingDirectory: '.' + projectFile: 'build.gradle' + fodApiUrl: $(FOD_API_URL) + fodClientId: $(FOD_CLIENT_ID) + fodClientSecret: $(FOD_CLIENT_SECRET) + fodAppName: "$(FORTIFY_APP_NAME)" + fodReleaseName: "$(FORTIFY_RELEASE_NAME)" + pool: + name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + # + # Deploy the application - use an appropriate set of tasks for your application/environment here + # + - stage: DeployApp + displayName: 'Deploy Application' + dependsOn: + - FoD_SAST + #- FoD_OSS + #- Debricked_SCA + jobs: + # This is a simulated deployment and does nothing + - template: '.azure-pipelines/templates/simulate-deployment.yml' + parameters: + workingDirectory: '.' + pool: + name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + # + # Dynamic Application Security Testing with Fortify on Demand + # + - stage: FoD_DAST + displayName: 'FoD DAST' + condition: and(eq(variables['USE_FOD_DAST'], 'true'), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + dependsOn: DeployApp + jobs: + # Run FoD DAST Scan on Project + - template: '.azure-pipelines/templates/fod-dast-scan.yml' + parameters: + fodApiUrl: $(FOD_API_URL) + fodClientId: $(FOD_CLIENT_ID) + fodClientSecret: $(FOD_CLIENT_SECRET) + fodAppName: "$(FORTIFY_APP_NAME)" + fodReleaseName: "$(FORTIFY_RELEASE_NAME)" + pool: + name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + # + # Verify FoD Security Policy + # + - stage: FoD_SecurityGate + displayName: 'FoD Security Gate' + condition: always() + dependsOn: + - FoD_SAST + #- FoD_OSS + - FoD_DAST + jobs: + # Verify Security Policy for the Release + - template: '.azure-pipelines/templates/fod-security-gate.yml' + parameters: + workingDirectory: '.' + fodApiUrl: $(FOD_API_URL) + fodClientId: $(FOD_CLIENT_ID) + fodClientSecret: $(FOD_CLIENT_SECRET) + fodAppName: "$(FORTIFY_APP_NAME)" + fodReleaseName: "$(FORTIFY_RELEASE_NAME)" + reportFile: "$(Build.SourcesDirectory)/reports/$(FORTIFY_RELEASE_NAME).html" + pool: + name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + # + # Create and synchronize "NEW" FoD Issues to ALM Octane/ValueEdge + # + #- stage: FoD_Issues_To_Octane + # displayName: 'FoD Issues to Octane' + # condition: eq(variables['SYNC_ISSUES'], 'true') + # dependsOn: + # - FOD_SAST + # - FOD_DAST + # jobs: + # - template: '.azure-pipelines/templates/fod-to-octane.yml' + # parameters: + # workingDirectory: '.' # could be project directory with specific config file + # fodBaseUrl: $(FOD_BASE_URL) + # fodTenant: $(FOD_TENANT) + # fodClientId: $(FOD_CLIENT_ID) + # fodClientSecret: $(FOD_CLIENT_SECRET) + # fodAppName: "$(FORTIFY_APP_NAME)" + # fodReleaseName: "$(FORTIFY_RELEASE_NAME)" + # octaneBaseUrl: $(OCTANE_BASE_URL) + # octaneSharedSpaceId: $(OCTANE_SHARED_SPACE_ID) + # octaneWorkspaceId: $(OCTANE_WORKSPACE_ID) + # octaneClientId: $(OCTANE_CLIENT_ID) + # octaneClientSecret: $(OCTANE_CLIENT_SECRET) + # configFile: 'FoDToOctane-NEW.xml' + # pool: + # name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + + #- stage: ALMOctanePost + # displayName: 'ALM Octane Post' + # condition: always() + # dependsOn: + # - ALMOctanePre + # - FoD_SAST + # - FoD_DAST + # - FoD_SecurityGate + # - FoD_Issues_To_Octane + # jobs: + # - job: + # condition: always() + # pool: + # name: 'FortifyPreSales' # use named self-hosted pool + #vmImage: 'windows-2022' # or uncomment to use Azure Devops cloud-hosted pool + # steps: + # - task: octane-end-task@2 + # inputs: + # OctaneServiceConnection: 'AzureExtensionPipelineServiceConnection-IWA' + # WorkspaceList: "$(OCTANE_WORKSPACES)" + # GithubRepositoryConnection: 'GitHubServiceConnection-IWA' diff --git a/build.gradle b/build.gradle index bd34b5e..e13911e 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,7 @@ plugins { ext { springBootVersion = '2.7.17' springSecurityVersion = '3.0.4.RELEASE' + springLog4jVersion = '2.3.12.RELEAS' jacksonVersion = '2.13.0' tymeleafLayoutDialectVersion = '3.2.1' itextVersion = '7.2.5' @@ -16,7 +17,6 @@ ext { junitPlatformVersion = '1.7.1' seleniumVersion = '4.21.0' mockitoVersion = '4.11.0' - log4jVersion = '2.6.0' } repositories { @@ -36,6 +36,7 @@ dependencies { implementation "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:${tymeleafLayoutDialectVersion}" implementation "org.springframework.boot:spring-boot-starter-tomcat:${springBootVersion}" implementation "org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}" + implementation "org.springframework.boot:spring-boot-starter-log4j2:${springLog4jVersion}" implementation "org.apache.commons:commons-email:1.4" implementation "com.google.guava:guava:30.1.1-jre" implementation "com.h2database:h2:1.4.197" @@ -62,7 +63,11 @@ dependencies { implementation "org.springframework.boot:spring-boot-devtools:${springBootVersion}" implementation "org.apache.tika:tika-core:1.18" implementation "org.json:json:20201115" - implementation "org.springframework.boot:spring-boot-starter-log4j2:2.4.13" + //modules { + // module("org.springframework.boot:spring-boot-starter-logging") { + // replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback") + // } + //} implementation "org.mockito:mockito-bom:${mockitoVersion}" implementation "org.hibernate.validator:hibernate-validator:6.1.0.Final" implementation "com.warrenstrange:googleauth:1.5.0" @@ -92,7 +97,8 @@ configurations.implementation { } configurations.all { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' - exclude module: 'spring-boot-starter-logging' + exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging' + //exclude module: 'spring-boot-starter-logging' } dependencyLocking { lockAllConfigurations() }