Skip to content

Commit

Permalink
feat: Add ssc-scan action, supporting both SC-SAST & Debricked
Browse files Browse the repository at this point in the history
  • Loading branch information
rsenden committed Jun 3, 2024
1 parent 3f17de0 commit df7a992
Show file tree
Hide file tree
Showing 20 changed files with 140 additions and 57 deletions.
4 changes: 2 additions & 2 deletions internal/fod-login/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ runs:
if: ${{ !env._FOD_LOGGED_IN }}
with:
dir: ${{ github.action_path }}
script: ./fod-login.sh
post: ./fod-logout.sh
script: fod-login.sh
post: fod-logout.sh

branding:
icon: 'shield'
Expand Down
24 changes: 0 additions & 24 deletions internal/run-script-js/main.js

This file was deleted.

34 changes: 34 additions & 0 deletions internal/run-script/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# fortify/github-action/internal/run-script

This action can run any of the scripts located in the `scripts` directory of this action, including the ability to run post-job scripts, for example to handle session logout.

```yaml
- uses: fortify/github-action/internal/run-script@v1
with:
script: <script name>
post: <post-job script name>
```
Originally, the idea was to have these scripts located in each individual action directory, for example having `ssc-login.sh` and `ssc-logout.sh` scripts located in the `internal/ssc-login` directory. However, this proved to be difficult/impossible:

- As scripts need to be run using `bash` (also on Windows), we need to convert `${{github.action_path}}` (which may include drive letter and backslashes on Windows) to `bash` format; an example of how this can be done is shown in `action.yml`.
- GitHub lazily evaluates action inputs when running the post-job actions, but doesn't re-run any steps used to generate those inputs.

So, suppose we'd generate a `BASH_ACTION_PATH` environment variable that contains `${{github.action_path}}` in `bash` format, we'd expect to be able to use something like:

```yaml
- uses: fortify/github-action/internal/run-script/[email protected]
with:
script: ${{ env.BASH_ACTION_PATH }}/ssc-login.sh
post: ${{ env.BASH_ACTION_PATH }}/ssc-logout.sh
```

This works fine for `script:`, but the `post:` script would use whatever the value of `BASH_ACTION_PATH` is during post-job execution. So, if we'd run both `ssc-login` and `sc-sast-login` actions, the post-job action would try to run `../internal/sc-sast-login/ssc-logout.sh`, which would fail because of the incorrect directory name.

Several work-arounds were tried, but failed. Only way that this would likely work is to have the calling action pass something like a static action id, which would then be used by this action to set a `POST_<id>_SCRIPT=${{inputs.POST}}` environment variable. During post-job execution, we wouldn't look at any actual inputs, but instead just execute the script identified in the `POST_<id>_SCRIPT` environment variable.

Apart from hosting the scripts together with the action that executes them, another advantage of such an id is that we can also provide out-of-the-box support for run-once actions, like the various `login` actions; this is currently handled by setting an environment variable in the `*-login.sh` and `*-logout.sh` scripts. As we may also have scripts that may need to be run multiple times, we should control this through a `run-once: true|false` input.

Disadvantage, apart from slightly more complex implementation, is that each caller of this `run-script` action would also need to provide the value of `${{ github.action_path }}` as an input to this action, in order to have this action determine appropriate script location.


15 changes: 4 additions & 11 deletions internal/run-script/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,14 @@ inputs:
runs:
using: composite
steps:
# github.action_path uses platform-specific path format, like D:\... for Windows.
# The run-script-js action requires the path to be in bash format, so we convert
# the paths to bash format before invoking the run-script-js action.
- run: echo "BASH_SCRIPT_DIR=$(pwd)" >> $GITHUB_ENV
shell: bash
working-directory: ${{ inputs.dir }}
- run: echo "BASH_UTIL_DIR=$(pwd)/util" >> $GITHUB_ENV
- run: echo "_RUN_SCRIPTS_DIR=$(pwd)/scripts" >> $GITHUB_ENV
shell: bash
working-directory: ${{ github.action_path }}
- uses: fortify/github-action/internal/run-script-[email protected]
- uses: fortify/github-action/internal/run-script/[email protected]
with:
util: ${{ env.BASH_UTIL_DIR }}
dir: ${{ env.BASH_SCRIPT_DIR }}
dir: ${{ env._RUN_SCRIPTS_DIR }}
script: ${{ inputs.script }}
post: ${{ inputs.post }}
post: ${{ inputs.post }}

branding:
icon: 'shield'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,10 @@ inputs:
description: 'Script to run on job completion'
required: false
dir:
description: 'Directory where scripts are located, should usually be set to github.action_path'
description: 'Directory where scripts are located, set automatically by internal/run-script action'
required: true
util:
description: 'Directory where utility scripts are located, set automatically by internal/run-script action'
required: true
key:
description: 'Name of the state variable used to detect the post step.'
required: false
default: POST

runs:
using: 'node20'
main: 'main.js'
post: 'main.js'
post: 'post.js'
3 changes: 3 additions & 0 deletions internal/run-script/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const util = require("./util");

util.run(process.env.INPUT_SCRIPT);
File renamed without changes.
3 changes: 3 additions & 0 deletions internal/run-script/js/post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const util = require("./util");

util.run(process.env.INPUT_POST);
12 changes: 12 additions & 0 deletions internal/run-script/js/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { spawn } = require("child_process");

exports.run = function(script) {
if ( script ) {
const scriptDir = process.env.INPUT_DIR;
const subprocess = spawn(`bash -c -o pipefail -v 'export UTIL_DIR=${scriptDir}; ${scriptDir}/${script}'`,
{ stdio: "inherit", shell: true });
subprocess.on("exit", (exitCode) => {
process.exitCode = exitCode;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ fi
if [ -z "$FCLI_CMD" ]; then
echo "ERROR: fortify/github-action/setup must be run to set up fcli before running this action"
exit 1;
fi
fi

function run {
echo RUN: "$@"
"$@"
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ else
echo "ERROR: Either FOD_CLIENT_ID and FOD_CLIENT_SECRET, or FOD_TENANT, FOD_USER and FOD_PASSWORD environment variables must be set"
exit 1;
fi
${FCLI_CMD} fod session login --url "${FOD_URL}" "${_FOD_AUTH_OPTS[@]}" ${EXTRA_FOD_LOGIN_OPTS} || exit 1
run ${FCLI_CMD} fod session login --url "${FOD_URL}" "${_FOD_AUTH_OPTS[@]}" ${EXTRA_FOD_LOGIN_OPTS} \
|| exit 1
echo '_FOD_LOGGED_IN=true' >> $GITHUB_ENV
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@

if [[ "${_FOD_LOGGED_IN}" == "true" ]]; then
echo '_FOD_LOGGED_IN=false' >> $GITHUB_ENV
${FCLI_CMD} fod session logout || exit 1
run ${FCLI_CMD} fod session logout \
|| exit 1
fi
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ fi
if [ -z "SSC_TOKEN" ]; then
echo "ERROR: SSC_TOKEN environment variable must be set"; exit 1;
fi
${FCLI_CMD} sc-sast session login --ssc-url "${SSC_URL}" -t "${SSC_TOKEN}" -c "${SC_SAST_TOKEN}" ${EXTRA_SC_SAST_LOGIN_OPTS}
run ${FCLI_CMD} sc-sast session login --ssc-url "${SSC_URL}" -t "${SSC_TOKEN}" -c "${SC_SAST_TOKEN}" ${EXTRA_SC_SAST_LOGIN_OPTS} \
|| exit 1
echo '_SC_SAST_LOGGED_IN=true' >> $GITHUB_ENV
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@

if [[ "${_SC_SAST_LOGGED_IN}" == "true" ]]; then
echo '_SC_SAST_LOGGED_IN=false' >> $GITHUB_ENV
${FCLI_CMD} sc-sast session logout --no-revoke-token || exit 1
run ${FCLI_CMD} sc-sast session logout --no-revoke-token \
|| exit 1
fi
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ elif [ -n "${SSC_USER}" -a -n "${SSC_PASSWORD}" ]; then
else
echo "ERROR: Either SSC_TOKEN, or SSC_USER and SSC_PASSWORD environment variables must be set"; exit 1;
fi
${FCLI_CMD} ssc session login --url "${SSC_URL}" "${_SSC_AUTH_OPTS[@]}" ${EXTRA_SSC_LOGIN_OPTS}
run ${FCLI_CMD} ssc session login --url "${SSC_URL}" "${_SSC_AUTH_OPTS[@]}" ${EXTRA_SSC_LOGIN_OPTS} \
|| exit 1
echo '_SSC_LOGGED_IN=true' >> $GITHUB_ENV
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ if [[ "${_SSC_LOGGED_IN}" == "true" ]]; then
else
echo "ERROR: Either SSC_TOKEN, or SSC_USER and SSC_PASSWORD environment variables must be set"; exit 1;
fi
${FCLI_CMD} ssc session logout "${_SSC_LOGOUT_OPTS[@]}" || exit 1
run ${FCLI_CMD} ssc session logout "${_SSC_LOGOUT_OPTS[@]}" \
|| exit 1
fi
33 changes: 33 additions & 0 deletions internal/run-script/scripts/ssc-scan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash
. ${UTIL_DIR}/common.sh

# This script assumes that fcli and Debricked CLI have already been installed,
# and that any necessary fcli sessions have been created.
# TODO Check prerequisites like SSC_APPVERSION, DEBRICKED_TOKEN, ...

if [ "${DO_SC_SAST_SCAN}" == "true" ]; then
run ${FCLI_CMD} sc-sast scan start --publish-to "${SSC_APPVERSION}" -p package.zip -v "${SC_SAST_SENSOR_VERSION}" --store sc_sast_scan ${EXTRA_SC_SAST_SCAN_OPTS} \
|| exit 1
fi
if [ "${DO_DEBRICKED_SCAN}" == "true" ]; then
# Debricked may return non-zero exit code on automation rule failures, in which case
# we still want to run subsequent steps, hence we temporarily ignore the exit code,
run ${DEBRICKED_CLI_CMD} scan -t "${DEBRICKED_TOKEN}" -i "Fortify GitHub Action" \
|| FAIL_ON_EXIT=true
run ${FCLI_CMD} ssc artifact import-debricked --av "${SSC_APPVERSION}" --repository "${GITHUB_REPOSITORY}" --branch "${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" -t "${DEBRICKED_TOKEN}" --store debricked_scan \
|| exit 1
fi
if [ "${DO_WAIT}" == "true" ] || [ "${DO_EXPORT}" == "true" ]; then
if [ "${DO_SC_SAST_SCAN}" == "true" ]; then
run ${FCLI_CMD} sc-sast scan wait-for ::sc_sast_scan:: \
|| exit 1
fi
if [ "${DO_DEBRICKED_SCAN}" == "true" ]; then
run ${FCLI_CMD} ssc artifact wait-for ::debricked_scan:: \
|| exit 1
fi
fi
if [ "${FAIL_ON_EXIT}" == "true" ]; then
echo "Earlier failures detected"
exit 1
fi
4 changes: 2 additions & 2 deletions internal/sc-sast-login/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ runs:
if: ${{ !env._SC_SAST_LOGGED_IN }}
with:
dir: ${{ github.action_path }}
script: ./sc-sast-login.sh
post: ./sc-sast-logout.sh
script: sc-sast-login.sh
post: sc-sast-logout.sh

branding:
icon: 'shield'
Expand Down
4 changes: 2 additions & 2 deletions internal/ssc-login/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ runs:
if: ${{ !env._SSC_LOGGED_IN }}
with:
dir: ${{ github.action_path }}
script: ./ssc-login.sh
post: ./ssc-logout.sh
script: ssc-login.sh
post: ssc-logout.sh
branding:
icon: 'shield'
color: 'blue'
Expand Down
25 changes: 25 additions & 0 deletions ssc-scan/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: 'Perform SAST scan'
description: 'Perform a SAST scan on ScanCentral SAST'
author: 'Fortify'
runs:
using: composite
steps:
- uses: fortify/github-action/[email protected]
with:
export-path: false
fcli: action-default
debricked-cli: ${{ env.DO_DEBRICKED_SCAN=='true' && 'action-default' || 'skip' }}
- uses: fortify/github-action/internal/[email protected]
- uses: fortify/github-action/internal/[email protected]
- uses: fortify/github-action/[email protected]
- uses: fortify/github-action/internal/[email protected]
with:
dir: ${{ github.action_path }}
script: ssc-scan.sh
- if: env.DO_EXPORT == 'true'
uses: fortify/github-action/[email protected]

branding:
icon: 'shield'
color: 'blue'

0 comments on commit df7a992

Please sign in to comment.