Skip to content

DevSecOps with Fortify on Demand #18

DevSecOps with Fortify on Demand

DevSecOps with Fortify on Demand #18

Workflow file for this run

# Create GitHub Action Repository Variables for your version of the application:
# FOD_BASE_URL should be FoD BASE URL for your tenant (e.g. https://ams.fortify.com)
# FOD_API_URL should be FoD API URL for your tenant (e.g. https://api.ams,fortify.com)
# FOD_PARENT_RELEASE_NAME is the FoD release name corresponding to the parent branch of any newly created branch, this is typically "main" or "develop"
# Create GitHub Action Secrets for your version of the application:
# FOD_CLIENT_ID should be an API Key obtained from your FoD tenant.
# FOD_CLIENT_SECRET should be the secret for the API Key obtained for your FoD tenant.
# Helpful hints:
# API Key credentials can be obtained from your FoD tenant, under Administration -> Settings -> API
# It is recommended to create credentials with 'Security Lead' Role selected.
# "Automated Audit preference" should be configured for the release's Static Scan Settings.
name: DevSecOps with Fortify on Demand
on:
# Triggers the workflow on push or pull request events but only for the main or develop branches
push:
paths-ignore:
- '.github/**/**'
- 'bin/**'
- 'data/**'
- 'etc/**'
- 'tests/**'
- 'README.md'
- 'LICENSE'
branches:
- '**' # matches every branch
pull_request:
branches: [ main, develop ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
inputs:
runFoDSASTScan:
description: 'Carry out SAST scan using Fortify on Demand'
required: false
default: 'true'
# Global environment variables
env:
BUILD_TYPE: "Release"
CMAKE_PRESET: "conan-release"
DEFAULT_APP_NAME: "EightBallCpp"
PYTHON_VERSION: "3.12.4"
jobs:
Build-And-Unit-Test:
# The type of runner that the job will run on
#runs-on: ubuntu-latest
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Fetch at least the immediate parents so that if this is a pull request then we can checkout the head.
fetch-depth: 2
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install CMake and Ninja
uses: lukka/get-cmake@latest
- name: Activate virtualenv
run: |
python -m venv venv
source ./venv/bin/activate
echo PATH=$PATH >> $GITHUB_ENV
- name: Install Conan
run: |
pip install conan
conan profile detect --force
conan install . --output-folder=build --build=missing --settings=build_type=${{env.BUILD_TYPE}} -c tools.cmake.cmaketoolchain:generator=Ninja
- name: Configure CMake
run: cmake --preset ${{env.CMAKE_PRESET}}
- name: Build
run: |
cd build
source conanbuild.sh
cmake --build . --clean-first --config ${{env.BUILD_TYPE}} --verbose
Quality-Gate:
#runs-on: ubuntu-latest
runs-on: self-hosted
if: ${{ always() }}
needs: [ Build-And-Unit-Test ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Fetch at least the immediate parents so that if this is a pull request then we can checkout the head.
fetch-depth: 2
# TBD
FoD-SAST-Scan:
#runs-on: ubuntu-latest
runs-on: self-hosted
if: ${{ (github.event_name == 'push') || (github.event_name == 'pull_request') || (github.event.inputs.runFoDSASTScan == 'true') }}
needs: [ Quality-Gate ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Fetch at least the immediate parents so that if this is a pull request then we can checkout the head.
fetch-depth: 2
- name: Fortify App and Release Name
id: fortify-app-and-rel-name
uses: fortify-presales/github-actions/fortify-app-and-release-name@main
with:
default_fortify_app_name: ${{ env.DEFAULT_APP_NAME }}
default_fortify_release_name: ${{ github.ref_name }}
app_name_postfix: ${{ vars.FORTIFY_APP_NAME_POSTFIX }}
# Uncomment below to debug FoD App/Release names
#- name: Print App and Release Name
# shell: bash
# run: |
# echo "FoD App Name: ${FOD_APP_NAME}"
# echo "FoD Release Name: ${FOD_RELEASE_NAME}"
# env:
# FOD_APP_NAME: ${{ steps.fortify-app-and-rel-name.outputs.app_name }}
# FOD_RELEASE_NAME: ${{ steps.fortify-app-and-rel-name.outputs.release_name }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install CMake and Ninja
uses: lukka/get-cmake@latest
- name: Activate virtualenv
run: |
python -m venv venv
source ./venv/bin/activate
echo PATH=$PATH >> $GITHUB_ENV
- name: Install Conan
run: |
pip install conan
conan profile detect --force
conan install . --output-folder=build --build=missing --settings=build_type=${{env.BUILD_TYPE}} -c tools.cmake.cmaketoolchain:generator=Ninja
- name: Configure CMake
run: cmake --preset ${{env.CMAKE_PRESET}}
# Login to Fortify on Demand fcli session
- name: Login fcli
shell: bash
run: |
fcli fod session login --url $FOD_API_URI --client-id $FOD_CLIENT_ID --client-secret $FOD_CLIENT_SECRET --session github-actions
env:
FOD_API_URI: ${{ vars.FOD_API_URL }}
FOD_CLIENT_ID: ${{ secrets.FOD_CLIENT_ID }}
FOD_CLIENT_SECRET: ${{ secrets.FOD_CLIENT_SECRET }}
- name: Fortify Translation
working-directory: "build"
run: |
source conanbuild.sh
cmake --build . --clean-first --config ${{env.BUILD_TYPE}} --verbose
sourceanalyzer -Dcom.fortify.sca.ProjectRoot=.fortify ${JVM_ARGS} -b "${FOD_APP_NAME}" -debug -verbose compile_commands.json
sourceanalyzer -Dcom.fortify.sca.ProjectRoot=.fortify -Dcom.fortify.sca.MobileBuildSessions=true ${JVM_ARGS} -b "${FOD_APP_NAME}" -debug -verbose -export-build-session "${FOD_APP_NAME}.mbs"
rm -f ${PACKAGE_FILE}
zip ${PACKAGE_FILE} "${FOD_APP_NAME}.mbs"
env:
PACKAGE_FILE: "package.zip"
FOD_APP_NAME: ${{ steps.fortify-app-and-rel-name.outputs.app_name }}
- name: Fortify Scan
working-directory: "build"
run: |
fcli fod sast-scan start --release "${FOD_RELEASE_NAME}" --notes "${FOD_SCAN_NOTES}" -f $PACKAGE_FILE --store curScan --session github-actions
sleep 10
echo "fod_scan_id=$(fcli util var get ::curScan::)" >> $GITHUB_OUTPUT
fcli fod sast-scan wait-for ::curScan:: --session github-actions
env:
PACKAGE_FILE: "package.zip"
FOD_RELEASE_NAME: ${{ format('{0}:{1}', steps.fortify-app-and-rel-name.outputs.app_name, steps.fortify-app-and-rel-name.outputs.release_name) }}
FOD_SCAN_NOTES: "Triggered by GitHub Actions (${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
# Logout/Close Fortify on Demand fcli session
- name: Logout fcli
shell: bash
run: |
fcli fod session logout --session github-actions
Security-Gate:
#runs-on: ubuntu-latest
runs-on: self-hosted
if: ${{ always() }}
needs: [ FoD-SAST-Scan ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Fetch at least the immediate parents so that if this is a pull request then we can checkout the head.
fetch-depth: 2
- name: Fortify App and Release Name
id: fortify-app-and-rel-name
uses: fortify-presales/github-actions/fortify-app-and-release-name@main
with:
default_fortify_app_name: ${{ env.DEFAULT_APP_NAME }}
default_fortify_release_name: ${{ github.ref_name }}
app_name_postfix: ${{ vars.FORTIFY_APP_NAME_POSTFIX }}
- name: Verify FoD Security Policy
uses: fortify-presales/github-actions/verify-fod-security-policy@main
with:
fod_api_url: ${{ vars.FOD_API_URL }}
fod_client_id: ${{ secrets.FOD_CLIENT_ID }}
fod_client_secret: ${{ secrets.FOD_CLIENT_SECRET }}
fod_app_name: ${{ steps.fortify-app-and-rel-name.outputs.app_name }}
fod_release_name: ${{ steps.fortify-app-and-rel-name.outputs.release_name }}
Release-To-Prod:
#runs-on: ubuntu-latest
runs-on: self-hosted
needs: [ Quality-Gate, Security-Gate ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# Fetch at least the immediate parents so that if this is a pull request then we can checkout the head.
fetch-depth: 2
# TBD