Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix scripts for migration from tfsec to trivy #1

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
40 changes: 20 additions & 20 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defaults:

jobs:
test-check:
name: tfsec (github-check)
name: trivy (github-check)
runs-on: ubuntu-latest

steps:
Expand All @@ -31,13 +31,13 @@ jobs:
- name: Check return codes
if: success() || failure ()
run: |
tfsec_return="${{ steps.test.outputs.tfsec-return-code }}"
trivy_return="${{ steps.test.outputs.trivy-return-code }}"
reviewdog_return="${{ steps.test.outputs.reviewdog-return-code }}"

if [[ "$tfsec_return" -eq 1 ]]; then
echo "tfsec correctly returned failure ${tfsec_return}"
if [[ "$trivy_return" -eq 1 ]]; then
echo "trivy correctly returned failure ${trivy_return}"
else
echo "tfsec returned ${tfsec_return}, expected '1'. Failing..."
echo "trivy returned ${trivy_return}, expected '1'. Failing..."
exit 1
fi

Expand All @@ -50,7 +50,7 @@ jobs:

test-pr-check:
if: github.event_name == 'pull_request'
name: tfsec (github-pr-check)
name: trivy (github-pr-check)
runs-on: ubuntu-latest

steps:
Expand All @@ -69,13 +69,13 @@ jobs:
- name: Check return codes
if: success() || failure ()
run: |
tfsec_return="${{ steps.test.outputs.tfsec-return-code }}"
trivy_return="${{ steps.test.outputs.trivy-return-code }}"
reviewdog_return="${{ steps.test.outputs.reviewdog-return-code }}"

if [[ "$tfsec_return" -eq 1 ]]; then
echo "tfsec correctly returned failure ${tfsec_return}"
if [[ "$trivy_return" -eq 1 ]]; then
echo "trivy correctly returned failure ${trivy_return}"
else
echo "tfsec returned ${tfsec_return}, expected '1'. Failing..."
echo "trivy returned ${trivy_return}, expected '1'. Failing..."
exit 1
fi

Expand All @@ -88,7 +88,7 @@ jobs:

test-pr-review:
if: github.event_name == 'pull_request'
name: tfsec (github-pr-review)
name: trivy (github-pr-review)
runs-on: ubuntu-latest

steps:
Expand All @@ -109,13 +109,13 @@ jobs:
- name: Check return codes
if: success() || failure ()
run: |
tfsec_return="${{ steps.test.outputs.tfsec-return-code }}"
trivy_return="${{ steps.test.outputs.trivy-return-code }}"
reviewdog_return="${{ steps.test.outputs.reviewdog-return-code }}"

if [[ "$tfsec_return" -eq 1 ]]; then
echo "tfsec correctly returned failure ${tfsec_return}"
if [[ "$trivy_return" -eq 1 ]]; then
echo "trivy correctly returned failure ${trivy_return}"
else
echo "tfsec returned ${tfsec_return}, expected '1'. Failing..."
echo "trivy returned ${trivy_return}, expected '1'. Failing..."
exit 1
fi

Expand All @@ -131,7 +131,7 @@ jobs:
fail-fast: false
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
name: tfsec (${{ matrix.platform }})
name: trivy (${{ matrix.platform }})
runs-on: ${{ matrix.platform }}

steps:
Expand All @@ -150,13 +150,13 @@ jobs:
- name: Check return codes
if: success() || failure ()
run: |
tfsec_return="${{ steps.test.outputs.tfsec-return-code }}"
trivy_return="${{ steps.test.outputs.trivy-return-code }}"
reviewdog_return="${{ steps.test.outputs.reviewdog-return-code }}"

if [[ "$tfsec_return" -eq 1 ]]; then
echo "tfsec correctly returned failure ${tfsec_return}"
if [[ "$trivy_return" -eq 1 ]]; then
echo "trivy correctly returned failure ${trivy_return}"
else
echo "tfsec returned ${tfsec_return}, expected '1'. Failing..."
echo "trivy returned ${trivy_return}, expected '1'. Failing..."
exit 1
fi

Expand Down
30 changes: 15 additions & 15 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'Run tfsec with reviewdog'
description: '🐶 Run tfsec with reviewdog on pull requests to enforce security best practices'
name: 'Run trivy with reviewdog'
description: '🐶 Run trivy with reviewdog on pull requests to enforce security best practices'
author: 'vlaaaaaaad (reviewdog)'

inputs:
Expand All @@ -20,8 +20,8 @@ inputs:
tool_name:
description: |
The name for the report as it will show up in GitHub's interface.
Default is tfsec.
default: 'tfsec'
Default is trivy.
default: 'trivy'
required: false
reporter:
description: |
Expand All @@ -45,33 +45,33 @@ inputs:
description: 'Additional reviewdog flags'
default: ''
required: false
tfsec_version:
trivy_version:
description: |
The version of tfsec to install.
The version of trivy to install.
Default is latest.
default: 'latest'
required: false
tfsec_flags:
trivy_flags:
description: |
List of arguments to send to tfsec
List of arguments to send to trivy
For the output to be parsable by reviewdog --format=checkstyle is enforced
Default is blank.
default: ''
required: false

outputs:
tfsec-return-code:
description: 'tfsec command return code'
value: ${{ steps.tfsec.outputs.tfsec-return-code }}
trivy-return-code:
description: 'trivy command return code'
value: ${{ steps.trivy.outputs.trivy-return-code }}
reviewdog-return-code:
description: 'reviewdog command return code'
value: ${{ steps.tfsec.outputs.reviewdog-return-code }}
value: ${{ steps.trivy.outputs.reviewdog-return-code }}

runs:
using: 'composite'
steps:
- run: $GITHUB_ACTION_PATH/script.sh
id: tfsec
id: trivy
shell: bash
env:
# We may want to allow specifying reviewdog version as
Expand All @@ -87,8 +87,8 @@ runs:
INPUT_FILTER_MODE: ${{ inputs.filter_mode }}
INPUT_FAIL_ON_ERROR: ${{ inputs.fail_on_error }}
INPUT_FLAGS: ${{ inputs.flags }}
INPUT_TFSEC_VERSION: ${{ inputs.tfsec_version }}
INPUT_TFSEC_FLAGS: ${{ inputs.tfsec_flags }}
INPUT_TRIVY_VERSION: ${{ inputs.trivy_version }}
INPUT_TRIVY_FLAGS: ${{ inputs.trivy_flags }}

branding:
icon: 'edit'
Expand Down
55 changes: 34 additions & 21 deletions script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,50 @@ cd "${GITHUB_WORKSPACE}/${INPUT_WORKING_DIRECTORY}" || exit
echo '::group::Preparing ...'
unameOS="$(uname -s)"
case "${unameOS}" in
Linux*) os=linux;;
Darwin*) os=darwin;;
CYGWIN*) os=windows;;
MINGW*) os=windows;;
MSYS_NT*) os=windows;;
Linux*) os=Linux;;
Darwin*) os=macOS;;
CYGWIN*) os=Windows;;
MINGW*) os=Windows;;
MSYS_NT*) os=Windows;;
*) echo "Unknown system: ${unameOS}" && exit 1
esac

unameArch="$(uname -m)"
case "${unameArch}" in
x86*) arch=amd64;;
arm64) arch=arm64;;
x86*) arch=64bit;;
arm64) arch=ARM64;;
*) echo "Unsupported architecture: ${unameArch}. Only AMD64 and ARM64 are supported by the action" && exit 1
esac

case "${os}" in
windows) archive_extension="zip";;
*) archive_extension="tar.gz";;
esac

TEMP_PATH="$(mktemp -d)"
echo "Detected ${os} running on ${arch}, will install tools in ${TEMP_PATH}"
REVIEWDOG_PATH="${TEMP_PATH}/reviewdog"
TFSEC_PATH="${TEMP_PATH}/tfsec"
TRIVY_PATH="${TEMP_PATH}/trivy"
echo '::endgroup::'

echo "::group::🐶 Installing reviewdog (${REVIEWDOG_VERSION}) ... https://github.com/reviewdog/reviewdog"
curl -sfL https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s -- -b "${REVIEWDOG_PATH}" "${REVIEWDOG_VERSION}" 2>&1
echo '::endgroup::'

echo "::group:: Installing tfsec (${INPUT_TFSEC_VERSION}) ... https://github.com/aquasecurity/tfsec"
test ! -d "${TFSEC_PATH}" && install -d "${TFSEC_PATH}"
echo "::group:: Installing trivy (${INPUT_TRIVY_VERSION}) ... https://github.com/aquasecurity/trivy"
test ! -d "${TRIVY_PATH}" && install -d "${TRIVY_PATH}"

binary="tfsec"
if [[ "${INPUT_TFSEC_VERSION}" = "latest" ]]; then
binary="trivy"
if [[ "${INPUT_TRIVY_VERSION}" = "latest" ]]; then
# latest release is available on this url.
# document: https://docs.github.com/en/repositories/releasing-projects-on-github/linking-to-releases
url="https://github.com/aquasecurity/tfsec/releases/latest/download/tfsec-${os}-${arch}"
latest_url="https://github.com/aquasecurity/trivy/releases/latest/"
release=$(curl $latest_url -s -L -I -o /dev/null -w '%{url_effective}' | awk -F'/' '{print $NF}')
else
url="https://github.com/aquasecurity/tfsec/releases/download/${INPUT_TFSEC_VERSION}/tfsec-${os}-${arch}"
release="${INPUT_TRIVY_VERSION}"
fi
release_num=$(echo $release | sed -e 's/^v//')
nayuta marked this conversation as resolved.
Show resolved Hide resolved
nayuta marked this conversation as resolved.
Show resolved Hide resolved
nayuta marked this conversation as resolved.
Show resolved Hide resolved
url="https://github.com/aquasecurity/trivy/releases/download/${release}/trivy_${release_num}_${os}-${arch}.${archive_extension}"
if [[ "${os}" = "windows" ]]; then
url+=".exe"
binary+=".exe"
Expand All @@ -57,21 +65,26 @@ echo "::group:: Installing tfsec (${INPUT_TFSEC_VERSION}) ... https://github.com
curl --silent --show-error --fail \
--location "${url}" \
--output "${binary}"
install tfsec "${TFSEC_PATH}"
if [[ "${os}" = "windows" ]]; then
unzip "${binary}"
else
tar -xzf "${binary}"
fi
install trivy "${TRIVY_PATH}"
echo '::endgroup::'

echo "::group:: Print tfsec details ..."
"${TFSEC_PATH}/tfsec" --version
echo "::group:: Print trivy details ..."
"${TRIVY_PATH}/trivy" --version
echo '::endgroup::'

echo '::group:: Running tfsec with reviewdog 🐶 ...'
echo '::group:: Running trivy with reviewdog 🐶 ...'
export REVIEWDOG_GITHUB_API_TOKEN="${INPUT_GITHUB_TOKEN}"

# Allow failures now, as reviewdog handles them
set +Eeuo pipefail

# shellcheck disable=SC2086
"${TFSEC_PATH}/tfsec" --format=json ${INPUT_TFSEC_FLAGS:-} . 2> /dev/null \
"${TRIVY_PATH}/trivy" --format json ${INPUT_TRIVY_FLAGS:-} config . 2> /dev/null \
| jq -r -f "${GITHUB_ACTION_PATH}/to-rdjson.jq" \
| "${REVIEWDOG_PATH}/reviewdog" -f=rdjson \
-name="${INPUT_TOOL_NAME}" \
Expand All @@ -81,8 +94,8 @@ echo '::group:: Running tfsec with reviewdog 🐶 ...'
-filter-mode="${INPUT_FILTER_MODE}" \
${INPUT_FLAGS}

tfsec_return="${PIPESTATUS[0]}" reviewdog_return="${PIPESTATUS[2]}" exit_code=$?
echo "tfsec-return-code=${tfsec_return}" >> "$GITHUB_OUTPUT"
trivy_return="${PIPESTATUS[0]}" reviewdog_return="${PIPESTATUS[2]}" exit_code=$?
echo "trivy-return-code=${trivy_return}" >> "$GITHUB_OUTPUT"
echo "reviewdog-return-code=${reviewdog_return}" >> "$GITHUB_OUTPUT"
echo '::endgroup::'

Expand Down
2 changes: 1 addition & 1 deletion testdata/example.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ resource "aws_security_group" "example" {

resource "aws_security_group_rule" "example_rule" {
security_group_id = aws_security_group.example.id
description = "Allow all traffic from Internet which will make tfsec throw an error"
description = "Allow all traffic from Internet which will make trivy throw an error"

type = "ingress"
from_port = "0"
Expand Down
38 changes: 24 additions & 14 deletions to-rdjson.jq
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
# Convert TFsec JSON output to Reviewdog Diagnostic Format (rdjson)
# Convert trivy JSON output to Reviewdog Diagnostic Format (rdjson)
# https://github.com/reviewdog/reviewdog/blob/f577bd4b56e5973796eb375b4205e89bce214bd9/proto/rdf/reviewdog.proto
{
source: {
name: "tfsec",
url: "https://github.com/aquasecurity/tfsec"
name: "trivy",
url: "https://github.com/aquasecurity/trivy"
},
diagnostics: (.results // {}) | map({
message: .description,
diagnostics: [(.Results[]
| .Target as $target
| .Misconfigurations
| select(. != null)
| .[]
| .Title as $title | .ID as $id | .PrimaryURL as $primaryURL | .Severity as $severity
| .CauseMetadata | {
message: $title,
code: {
value: .rule_id,
url: .links[0],
value: $id,
url: $primaryURL,
} ,
location: {
path: .location.filename,
path: $target,
range: {
start: {
line: .location.start_line,
line: .StartLine,
},
# Not in for tfsec
#end: {
# line: .EndLine,
#},
}
},
severity: (if .severity | startswith("CRITICAL") then
severity: (if $severity | startswith("CRITICAL") then
"ERROR"
elif .severity | startswith("HIGH") then
elif $severity | startswith("HIGH") then
"ERROR"
elif .severity | startswith("MEDIUM") then
elif $severity | startswith("MEDIUM") then
"WARNING"
elif .severity | startswith("LOW") then
elif $severity | startswith("LOW") then
"INFO"
else
null
end),
})
})]
}
Loading