diff --git a/internal/fod-login/action.yml b/internal/fod-login/action.yml index 6a6a230..96282f3 100644 --- a/internal/fod-login/action.yml +++ b/internal/fod-login/action.yml @@ -1,30 +1,19 @@ name: 'Run "fcli fod session login" command' -description: 'Run "fcli fod session login" command based on environment variables' +description: 'Run "fcli fod session login" command based on environment variables, auto-logout on job termination' author: 'Fortify' runs: using: composite steps: - # Define login options - - run: | - if [ -z "$FOD_URL" ]; then - echo "ERROR: FOD_URL environment variable must be set"; exit 1; - fi - if [ -n "${FOD_CLIENT_ID}" -a -n "${FOD_CLIENT_SECRET}" ]; then - echo '_FOD_LOGIN_OPTS=--url "${FOD_URL}" --client-id "${FOD_CLIENT_ID}" --client-secret "${FOD_CLIENT_SECRET}" ${EXTRA_FOD_LOGIN_OPTS}' >> $GITHUB_ENV - elif [ -n "${FOD_USER}" -a -n "${FOD_PASSWORD}" -a -n "${FOD_TENANT}" ]; then - echo '_FOD_LOGIN_OPTS=--url "${FOD_URL}" -t "${FOD_TENANT}" -u "${FOD_USER}" -p "${FOD_PASSWORD}" ${EXTRA_FOD_LOGIN_OPTS}' >> $GITHUB_ENV - 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 - shell: bash - # Run fcli login command; note that the calling action/workflow is responsible for installing fcli - - uses: fortify/github-action/internal/run@feat-1.3.0 + # If not run before: check preconditions, run fcli login command, and run + # post-job fcli logout command. + # Note that the calling action/workflow is responsible for installing fcli + - uses: fortify/github-action/internal/run-script@feat-1.3.0 + if: ${{ !env._FOD_LOGGED_IN }} with: - cmd: '"${FCLI_CMD}" fod session login ${_FOD_LOGIN_OPTS}' - # Clean up temporary environment variables - - run: | - echo '_FOD_LOGIN_OPTS=""' >> $GITHUB_ENV - shell: bash + cwd: ${{ github.action_path }} + script: ./fod-login.sh + post: ./fod-logout.sh + branding: icon: 'shield' color: 'blue' diff --git a/internal/fod-login/fod-login.sh b/internal/fod-login/fod-login.sh new file mode 100755 index 0000000..98ee373 --- /dev/null +++ b/internal/fod-login/fod-login.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +### Start common code +if [ -n "$RUNNER_DEBUG" ]; then + set -v -x +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 +### End common code + +if [ -z "$FOD_URL" ]; then + echo "ERROR: FOD_URL environment variable must be set"; exit 1; +fi +if [ -n "${FOD_CLIENT_ID}" -a -n "${FOD_CLIENT_SECRET}" ]; then + _FOD_AUTH_OPTS=("--client-id" "${FOD_CLIENT_ID}" "--client-secret" "${FOD_CLIENT_SECRET}") +elif [ -n "${FOD_USER}" -a -n "${FOD_PASSWORD}" -a -n "${FOD_TENANT}" ]; then + _FOD_AUTH_OPTS=("-t" "${FOD_TENANT}" "-u" "${FOD_USER}" "-p" "${FOD_PASSWORD}") +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 +echo '_FOD_LOGGED_IN=true' >> $GITHUB_ENV \ No newline at end of file diff --git a/internal/fod-login/fod-logout.sh b/internal/fod-login/fod-logout.sh new file mode 100755 index 0000000..b93d33f --- /dev/null +++ b/internal/fod-login/fod-logout.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +### Start common code +if [ -n "$RUNNER_DEBUG" ]; then + set -v -x +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 +### End common code + +if [[ "${_FOD_LOGGED_IN}" == "true" ]]; then + echo '_FOD_LOGGED_IN=false' >> $GITHUB_ENV + ${FCLI_CMD} fod session logout || exit 1 +fi \ No newline at end of file diff --git a/internal/fod-logout/action.yml b/internal/fod-logout/action.yml deleted file mode 100644 index ebe4eb6..0000000 --- a/internal/fod-logout/action.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: 'Run "fcli fod session login" command' -description: 'Run "fcli fod session login" command based on environment variables' -author: 'Fortify' -runs: - using: composite - steps: - # Run fcli logout command; note that the calling action/workflow is responsible for installing fcli - - uses: fortify/github-action/internal/run@feat-1.3.0 - with: - cmd: '"${FCLI_CMD}" fod session logout' -branding: - icon: 'shield' - color: 'blue' - diff --git a/internal/run-script/action.yml b/internal/run-script/action.yml new file mode 100644 index 0000000..144470c --- /dev/null +++ b/internal/run-script/action.yml @@ -0,0 +1,23 @@ +name: Run a script with optional post-job cleanup + +description: 'Action to execute a bash script, optionally executing another script on job completion.' + +inputs: + script: + description: 'Script to run' + required: true + post: + description: 'Script to run on job completion' + required: false + cwd: + description: 'Script working directory' + required: false + 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' diff --git a/internal/run-script/main.js b/internal/run-script/main.js new file mode 100644 index 0000000..f6b3775 --- /dev/null +++ b/internal/run-script/main.js @@ -0,0 +1,22 @@ +const { spawn } = require("child_process"); +const { appendFileSync } = require("fs"); +const { EOL } = require("os"); + +function run(script) { + if ( script ) { + const cwd = process.env.INPUT_CWD || process.cwd; + const subprocess = spawn(`bash -c -o pipefail -v ${script}`, { stdio: "inherit", shell: true, cwd: cwd }); + subprocess.on("exit", (exitCode) => { + process.exitCode = exitCode; + }); + } +} + +const key = process.env.INPUT_KEY.toUpperCase(); + +if ( process.env[`STATE_${key}`] !== undefined ) { // Are we in the 'post' step? + run(process.env.INPUT_POST); +} else { // Otherwise, this is the main step + appendFileSync(process.env.GITHUB_STATE, `${key}=true${EOL}`); + run(process.env.INPUT_SCRIPT); +} diff --git a/internal/with-post-step/package-lock.json b/internal/run-script/package-lock.json similarity index 100% rename from internal/with-post-step/package-lock.json rename to internal/run-script/package-lock.json diff --git a/internal/sc-sast-login/action.yml b/internal/sc-sast-login/action.yml index 703c013..e012961 100644 --- a/internal/sc-sast-login/action.yml +++ b/internal/sc-sast-login/action.yml @@ -7,27 +7,17 @@ runs: # TODO If we wait for scan completion, potentially we could generate a CIToken if # SSC_USER and SSC_PASSWORD have been set, and then revoke the token once the # scan has been successfully processed on SSC. - # Define login options - - run: | - if [ -z "$SSC_URL" ]; then - echo "ERROR: SSC_URL environment variable must be set"; exit 1; - fi - if [ -z "$SC_SAST_TOKEN" ]; then - echo "ERROR: SC_SAST_TOKEN environment variable must be set"; exit 1; - fi - if [ -z "SSC_TOKEN" ]; then - echo "ERROR: SSC_TOKEN environment variable must be set"; exit 1; - fi - echo '_SC_SAST_LOGIN_OPTS=--ssc-url "${SSC_URL}" -t "${SSC_TOKEN}" -c "${SC_SAST_TOKEN}" ${EXTRA_SC_SAST_LOGIN_OPTS}' >> $GITHUB_ENV - shell: bash - # Run fcli login command; note that the calling action/workflow is responsible for installing fcli - - uses: fortify/github-action/internal/run@feat-1.3.0 + + # If not run before: check preconditions, run fcli login command, and run + # post-job fcli logout command. + # Note that the calling action/workflow is responsible for installing fcli + - uses: fortify/github-action/internal/run-script@feat-1.3.0 + if: ${{ !env._SC_SAST_LOGGED_IN }} with: - cmd: '"${FCLI_CMD}" sc-sast session login ${_SC_SAST_LOGIN_OPTS}' - # Clean up temporary environment variables - - run: | - echo '_SC_SAST_LOGIN_OPTS=""' >> $GITHUB_ENV - shell: bash + cwd: ${{ github.action_path }} + script: ./sc-sast-login.sh + post: ./sc-sast-logout.sh + branding: icon: 'shield' color: 'blue' diff --git a/internal/sc-sast-login/sc-sast-login.sh b/internal/sc-sast-login/sc-sast-login.sh new file mode 100755 index 0000000..65200df --- /dev/null +++ b/internal/sc-sast-login/sc-sast-login.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +### Start common code +if [ -n "$RUNNER_DEBUG" ]; then + set -v -x +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 +### End common code + +if [ -z "$SSC_URL" ]; then + echo "ERROR: SSC_URL environment variable must be set"; exit 1; +fi +if [ -z "$SC_SAST_TOKEN" ]; then + echo "ERROR: SC_SAST_TOKEN environment variable must be set"; exit 1; +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} +echo '_SC_SAST_LOGGED_IN=true' >> $GITHUB_ENV \ No newline at end of file diff --git a/internal/sc-sast-login/sc-sast-logout.sh b/internal/sc-sast-login/sc-sast-logout.sh new file mode 100755 index 0000000..bdf95fa --- /dev/null +++ b/internal/sc-sast-login/sc-sast-logout.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +### Start common code +if [ -n "$RUNNER_DEBUG" ]; then + set -v -x +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 +### End common code + +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 +fi \ No newline at end of file diff --git a/internal/sc-sast-logout/action.yml b/internal/sc-sast-logout/action.yml deleted file mode 100644 index c4e7cf9..0000000 --- a/internal/sc-sast-logout/action.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: 'Run "fcli fod session login" command' -description: 'Run "fcli fod session login" command based on environment variables' -author: 'Fortify' -runs: - using: composite - steps: - # Run fcli logout command; note that the calling action/workflow is responsible for installing fcli - - uses: fortify/github-action/internal/run@feat-1.3.0 - with: - # TODO If we add functionality for generating a CIToken in the sc-sast-login - # action, we should clean it up here. - cmd: '"${FCLI_CMD}" sc-sast session logout --no-revoke-token' -branding: - icon: 'shield' - color: 'blue' - diff --git a/internal/ssc-login/action.yml b/internal/ssc-login/action.yml index 5911ea4..982c58d 100644 --- a/internal/ssc-login/action.yml +++ b/internal/ssc-login/action.yml @@ -4,27 +4,15 @@ author: 'Fortify' runs: using: composite steps: - # Define login options - - run: | - if [ -z "$SSC_URL" ]; then - echo "ERROR: SSC_URL environment variable must be set"; exit 1; - fi - if [ -n "${SSC_TOKEN}" ]; then - echo '_SSC_LOGIN_OPTS=--url "${SSC_URL}" --token "${SSC_TOKEN}" ${EXTRA_SSC_LOGIN_OPTS}' >> $GITHUB_ENV - elif [ -n "${SSC_USER}" -a -n "${SSC_PASSWORD}" ]; then - echo '_SSC_LOGIN_OPTS=--url "${SSC_URL}" -u "${SSC_USER}" -p "${SSC_PASSWORD}" ${EXTRA_SSC_LOGIN_OPTS}' >> $GITHUB_ENV - else - echo "ERROR: Either SSC_TOKEN, or SSC_USER and SSC_PASSWORD environment variables must be set"; exit 1; - fi - shell: bash - # Run fcli login command; note that the calling action/workflow is responsible for installing fcli - - uses: fortify/github-action/internal/run@feat-1.3.0 + # If not run before: check preconditions, run fcli login command, and run + # post-job fcli logout command. + # Note that the calling action/workflow is responsible for installing fcli + - uses: fortify/github-action/internal/run-script@feat-1.3.0 + if: ${{ !env._SSC_LOGGED_IN }} with: - cmd: '"${FCLI_CMD}" ssc session login ${_SSC_LOGIN_OPTS}' - # Clean up temporary environment variables - - run: | - echo '_SSC_LOGIN_OPTS=""' >> $GITHUB_ENV - shell: bash + cwd: ${{ github.action_path }} + script: ./ssc-login.sh + post: ./ssc-logout.sh branding: icon: 'shield' color: 'blue' diff --git a/internal/ssc-login/ssc-login.sh b/internal/ssc-login/ssc-login.sh new file mode 100755 index 0000000..8de7917 --- /dev/null +++ b/internal/ssc-login/ssc-login.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +### Start common code +if [ -n "$RUNNER_DEBUG" ]; then + set -v -x +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 +### End common code + +if [ -z "$SSC_URL" ]; then + echo "ERROR: SSC_URL environment variable must be set"; exit 1; +fi +if [ -n "${SSC_TOKEN}" ]; then + _SSC_AUTH_OPTS=("--token" "${SSC_TOKEN}") +elif [ -n "${SSC_USER}" -a -n "${SSC_PASSWORD}" ]; then + _SSC_AUTH_OPTS=("-u" "${SSC_USER}" "-p" "${SSC_PASSWORD}") +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} +echo '_SSC_LOGGED_IN=true' >> $GITHUB_ENV \ No newline at end of file diff --git a/internal/ssc-login/ssc-logout.sh b/internal/ssc-login/ssc-logout.sh new file mode 100755 index 0000000..e2254ed --- /dev/null +++ b/internal/ssc-login/ssc-logout.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +### Start common code +if [ -n "$RUNNER_DEBUG" ]; then + set -v -x +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 +### End common code + +if [[ "${_SSC_LOGGED_IN}" == "true" ]]; then + echo '_SSC_LOGGED_IN=false' >> $GITHUB_ENV + if [ -n "${SSC_TOKEN}" ]; then + _SSC_LOGOUT_OPTS=("--no-revoke-token") + elif [ -n "${SSC_USER}" -a -n "${SSC_PASSWORD}" ]; then + _SSC_LOGOUT_OPTS=("-u" "${SSC_USER}" "-p" "${SSC_PASSWORD}") + 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 +fi \ No newline at end of file diff --git a/internal/with-post-step/action.yml b/internal/with-post-step/action.yml deleted file mode 100644 index 69c2a6e..0000000 --- a/internal/with-post-step/action.yml +++ /dev/null @@ -1,42 +0,0 @@ -# ==================================================================================================================== # -# Authors: # -# Patrick Lehmann # -# Unai Martinez-Corral # -# # -# ==================================================================================================================== # -# Copyright 2020-2024 The pyTooling Authors # -# # -# Licensed under the Apache License, Version 2.0 (the "License"); # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -# # -# SPDX-License-Identifier: Apache-2.0 # -# ==================================================================================================================== # -name: With post step - -description: 'Generic JS Action to execute a main command and set a command as a post step.' - -inputs: - main: - description: 'Main command/script.' - required: true - post: - description: 'Post command/script.' - 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' diff --git a/internal/with-post-step/main.js b/internal/with-post-step/main.js deleted file mode 100644 index 04c2a9d..0000000 --- a/internal/with-post-step/main.js +++ /dev/null @@ -1,46 +0,0 @@ -/* ================================================================================================================== * - * Authors: * - * Unai Martinez-Corral * - * * - * ================================================================================================================== * - * Copyright 2021-2022 Unai Martinez-Corral * - * Copyright 2022 Unai Martinez-Corral * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - * * - * SPDX-License-Identifier: Apache-2.0 * - * ================================================================================================================== * - * * - * Context: * - * * https://github.com/docker/login-action/issues/72 * - * * https://github.com/actions/runner/issues/1478 * - * ================================================================================================================== */ -const { spawn } = require("child_process"); -const { appendFileSync } = require("fs"); -const { EOL } = require("os"); - -function run(cmd) { - const subprocess = spawn(cmd, { stdio: "inherit", shell: true }); - subprocess.on("exit", (exitCode) => { - process.exitCode = exitCode; - }); -} - -const key = process.env.INPUT_KEY.toUpperCase(); - -if ( process.env[`STATE_${key}`] !== undefined ) { // Are we in the 'post' step? - run(process.env.INPUT_POST); -} else { // Otherwise, this is the main step - appendFileSync(process.env.GITHUB_STATE, `${key}=true${EOL}`); - run(process.env.INPUT_MAIN); -}