Skip to content

Commit

Permalink
use kustomize to build sast-coverity-check
Browse files Browse the repository at this point in the history
... from the build-container task
  • Loading branch information
kdudka committed Nov 26, 2024
1 parent 234a4e1 commit 6dc6006
Show file tree
Hide file tree
Showing 3 changed files with 1,103 additions and 247 deletions.
10 changes: 10 additions & 0 deletions task/sast-coverity-check/0.2/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1

Check failure on line 1 in task/sast-coverity-check/0.2/kustomization.yaml

View workflow job for this annotation

GitHub Actions / Check Trusted Artifact variants

Task is using a workspace(s): source, to share data and needs a corresponding Trusted Artifacts Task variant in task/sast-coverity-check-oci-ta/0.2/
kind: Kustomization

resources:
- ../../buildah/0.2

patches:
- path: patch.yaml
target:
kind: Task
360 changes: 360 additions & 0 deletions task/sast-coverity-check/0.2/patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,360 @@
# Task name
- op: replace
path: /metadata/name
value: sast-coverity-check

# Task description
- op: replace
path: /spec/description
value: |-
Scans source code for security vulnerabilities, including common issues such as SQL injection, cross-site scripting (XSS), and code injection attacks using Coverity. At the moment, this task only uses the buildless mode, which does not build the project in order to analyze it.
# Replace task results
- op: replace
path: /spec/results
value:
- description: Short summary of SAST scan results.
name: SCAN_OUTPUT
- description: Tekton task test output.
name: TEST_OUTPUT
- description: SAST scanning results artifact URL.
name: SAST_RESULT_URL

###################
# Task steps
###################

# Remove all buildah task steps except build
- op: remove
path: /spec/steps/5 # upload-sbom
- op: remove
path: /spec/steps/4 # inject-sbom-and-push
- op: remove
path: /spec/steps/3 # prepare-sboms
- op: remove
path: /spec/steps/2 # analyse-dependencies-java-sbom
- op: remove
path: /spec/steps/1 # sbom-syft-generate

# Tune the build step (the only one left).

# Change build step image
- op: replace
path: /spec/steps/0/image
# New image shoould be based on quay.io/konflux-ci/buildah-task:latest or have all the tooling that the original image has.
value: quay.io/redhat-user-workloads/sast-tenant/sast-scanner/coverity@sha256:fdbe6b5c8d335c1f6cba2950c411ade10a3e4ab9530aae983069ced2b60470d8

# Change build step resources
- op: replace
path: /spec/steps/0/computeResources/limits/cpu
value: 4
- op: replace
path: /spec/steps/0/computeResources/limits/memory
value: 4Gi
- op: replace
path: /spec/steps/0/computeResources/requests/cpu
value: 2
- op: replace
path: /spec/steps/0/computeResources/requests/memory
value: 2Gi

# Additional volumes
- op: add
path: /spec/volumes/-
value:
name: cov-license
secret:
secretName: $(params.COV_LICENSE)
optional: false
- op: add
path: /spec/steps/0/env/-
value:
name: ADDITIONAL_VOLUME_MOUNTS
value: |-
/opt:/opt
/shared:/shared
# Additional parameters
- op: add
path: /spec/params/-
value:
name: IMAGE_URL
type: string
- op: add
path: /spec/params/-
value:
name: COV_LICENSE
type: string
description: Name of secret which contains the Coverity license
default: "cov-license"
- op: add
path: /spec/params/-
value:
name: PROJECT_NAME
type: string
default: ""
- op: add
path: /spec/params/-
value:
name: RECORD_EXCLUDED
type: string
default: "false"
- op: add
path: /spec/params/-
value:
description: Arguments to be appended to the coverity capture command
name: COV_CAPTURE_ARGS
type: string
default: ""
- op: add
path: /spec/params/-
value:
description: Arguments to be appended to the cov-analyze command
name: COV_ANALYZE_ARGS
type: string
default: "--enable HARDCODED_CREDENTIALS --security --concurrency --spotbugs-max-mem=4096"
- op: add
path: /spec/params/-
value:
name: IMP_FINDINGS_ONLY
type: string
description: Report only important findings. Default is true. To report all findings, specify "false"
default: "true"
- op: add
path: /spec/params/-
value:
name: KFP_GIT_URL
type: string
description: URL from repository to download known false positives files
# FIXME: Red Hat internal projects will default to https://gitlab.cee.redhat.com/osh/known-false-positives.git when KONFLUX-4530 is resolved
default: ""

# Add prepare and postprocess steps

# Prepare step
- op: add
path: /spec/steps/0
value:
name: prepare
image: quay.io/redhat-user-workloads/sast-tenant/sast-scanner/coverity@sha256:fdbe6b5c8d335c1f6cba2950c411ade10a3e4ab9530aae983069ced2b60470d8
computeResources:
limits:
memory: 1Gi
cpu: '1'
requests:
memory: 0.5Gi
cpu: '0.5'
workingDir: $(workspaces.source.path)
env:
- name: DOCKERFILE
value: $(params.DOCKERFILE)
script: |
set -x
# Dockerfile discovery logic is copied from buildah task
SOURCE_CODE_DIR=source
if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then
dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE"
elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then
dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE"
elif echo "$DOCKERFILE" | grep -q "^https\?://"; then
echo "Fetch Dockerfile from $DOCKERFILE"
dockerfile_path=$(mktemp --suffix=-Dockerfile)
http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE")
if [ "$http_code" != 200 ]; then
echo "No Dockerfile is fetched. Server responds $http_code"
exit 1
fi
http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore")
if [ "$http_code" = 200 ]; then
echo "Fetched .dockerignore from $DOCKERFILE.dockerignore"
mv "$dockerfile_path.dockerignore.tmp" "$SOURCE_CODE_DIR/$CONTEXT/.dockerignore"
fi
else
echo "Cannot find Dockerfile $DOCKERFILE"
exit 1
fi
# create a wrapper script to instrument RUN lines
tee /shared/cmd-wrap.sh << EOF
#!/bin/bash -x
id >&2
proj_dir=\$(pwd)
[ / = "\$proj_dir" ] && proj_dir=\$HOME
[ -z "\$proj_dir" ] && proj_dir=\$(echo ~)
# TODO: propagate COV_CAPTURE_ARGS
env COV_HOST=konflux /opt/coverity/bin/coverity --ticker-mode=no-spin capture --dir=/shared/idir --project-dir="\$proj_dir" -- "\$@"
EC=\$?
# make sure that idir will be writable by other users in subsequent RUN directives
chmod -R a+rwX /shared/idir
exit \$EC
EOF
chmod 0755 /shared/cmd-wrap.sh
# instrument all RUN lines in Dockerfile
cstrans-df-run --verbose /shared/cmd-wrap.sh < "$dockerfile_path" > /shared/Containerfile
# Make the buildah task use the instrumented Dockerfile
- op: replace
path: /spec/steps/1/env/1/value # steps -> build -> env -> DOCKERFILE
value: /shared/Containerfile

# Postprocess step
- op: add
path: /spec/steps/2
value:
name: postprocess
image: quay.io/redhat-user-workloads/sast-tenant/sast-scanner/coverity@sha256:fdbe6b5c8d335c1f6cba2950c411ade10a3e4ab9530aae983069ced2b60470d8
computeResources:
limits:
memory: 4Gi
cpu: 4
requests:
memory: 2Gi
cpu: 2
volumeMounts:
- name: cov-license
mountPath: "/etc/secrets/cov"
readOnly: true
- name: trusted-ca
mountPath: /mnt/trusted-ca
readOnly: true
env:
- name: IMAGE_URL
value: $(params.IMAGE_URL)
- name: COV_LICENSE
value: $(params.COV_LICENSE)
- name: COV_ANALYZE_ARGS
value: $(params.COV_ANALYZE_ARGS)
- name: COV_CAPTURE_ARGS
value: $(params.COV_CAPTURE_ARGS)
- name: KFP_GIT_URL
value: $(params.KFP_GIT_URL)
- name: IMP_FINDINGS_ONLY
value: $(params.IMP_FINDINGS_ONLY)
- name: PROJECT_NAME
value: $(params.PROJECT_NAME)
- name: RECORD_EXCLUDED
value: $(params.RECORD_EXCLUDED)
- name: COMPONENT_LABEL
valueFrom:
fieldRef:
fieldPath: metadata.labels['appstudio.openshift.io/component']

workingDir: $(workspaces.source.path)
script: |
set -exo pipefail
# shellcheck source=/dev/null
. /usr/local/share/konflux-test/utils.sh
trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT
export HOME="/var/tmp/coverity/home"
if [[ -z "${PROJECT_NAME}" ]]; then
PROJECT_NAME=${COMPONENT_LABEL}
fi
echo "The PROJECT_NAME used is: ${PROJECT_NAME}"
COVERITY_DIR=/shared/idir
COVERITY_RESULTS_FILE=$(workspaces.source.path)/coverity-results.json
COV_LICENSE_PATH=/etc/secrets/cov/cov-license
SOURCE_CODE_DIR=$(workspaces.source.path)
# Installing Coverity license
cp "$COV_LICENSE_PATH" /opt/coverity/bin/license.dat
# Installation of Red Hat certificates for cloning Red Hat internal repositories
ca_bundle=/mnt/trusted-ca/ca-bundle.crt
if [ -f "$ca_bundle" ]; then
echo "INFO: Using mounted CA bundle: $ca_bundle"
cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors
update-ca-trust
fi
if ! [ -d "$COVERITY_DIR" ]; then
# fallback to buildless scan if $COVERITY_DIR does not exist
echo -e 'capture:\n build-command-inference: false' > "$SOURCE_CODE_DIR"/coverity.yml
# shellcheck disable=SC2086
env COV_HOST=konflux /opt/coverity/bin/coverity capture $COV_CAPTURE_ARGS --project-dir "$SOURCE_CODE_DIR" --dir "$COVERITY_DIR" || :
fi
# analyze the intermediate code captured in $COVERITY_DIR
# shellcheck disable=SC2086
/opt/coverity/bin/cov-analyze $COV_ANALYZE_ARGS --dir="$COVERITY_DIR"
# export scan results
/opt/coverity/bin/cov-format-errors --dir="$COVERITY_DIR" --json-output-v10 "$COVERITY_RESULTS_FILE"
# We parse the results, embed context, remove duplicates and store them in SARIF format.
IMP_LEVEL=1
if [ "${IMP_FINDINGS_ONLY}" == "false" ]; then
IMP_LEVEL=0
fi
(cd "$SOURCE_CODE_DIR" && csgrep --mode=json --imp-level="$IMP_LEVEL" --remove-duplicates --embed-context=3 "$COVERITY_RESULTS_FILE") \
| csgrep --mode=json --strip-path-prefix="$SOURCE_CODE_DIR"/source/ \
| csgrep --mode=json --strip-path-prefix="$HOME" \
> coverity-results-raw.json
csgrep --mode=evtstat coverity-results-raw.json
# We check if the KFP_GIT_URL variable is set to apply the filters or not
if [[ -z "${KFP_GIT_URL}" ]]; then
echo "KFP_GIT_URL variable not defined. False positives won't be filtered"
mv coverity-results-raw.json coverity-results.json
else
echo "Filtering false positives in results files using csfilter-kfp..."
CMD=(
csfilter-kfp
--verbose
--kfp-git-url="${KFP_GIT_URL}"
--project-nvr="${PROJECT_NAME}"
)
if [ "${RECORD_EXCLUDED}" == "true" ]; then
CMD+=(--record-excluded="excluded-findings.json")
fi
"${CMD[@]}" coverity-results-raw.json > coverity-results.json
status=$?
if [ "$status" -ne 0 ]; then
echo "Error: failed to filter known false positives" >&2
return 1
else
echo "Message: Succeed to filter known false positives" >&2
fi
echo "Results after filtering:"
(set -x $$ csgrep --mode=evtstat coverity-results.json)
fi
csgrep --mode=sarif coverity-results.json > "$(workspaces.source.path)"/coverity-results.sarif
if [[ -z "$(csgrep --mode=evtstat coverity-results.json)" ]]; then
note="Task $(context.task.name) success: No finding was detected"
ERROR_OUTPUT=$(make_result_json -r SUCCESS -t "$note")
echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)"
else
TEST_OUTPUT=
parse_test_output "$(context.task.name)" sarif "$(workspaces.source.path)"/coverity-results.sarif || true
note="Task $(context.task.name) failed: For details, check Tekton task log."
echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)"
fi
echo "${TEST_OUTPUT:-${ERROR_OUTPUT}}" | tee "$(results.TEST_OUTPUT.path)"
# =====================================================================================
sast_dir="/shared/sast-results"
ls -l "$sast_dir"
# read the collected SAST scanning results
UPLOAD_FILE=gcc-analyzer.sarif
csgrep --mode=sarif --event=^warning --remove-duplicates --file-glob "${sast_dir}/*" \
| tee "${UPLOAD_FILE}" | csgrep
# upload scan results
MEDIA_TYPE=application/sarif+json
echo "Selecting auth"
select-oci-auth "${IMAGE_URL}" > "${HOME}/auth.json"
echo "Attaching to ${IMAGE_URL}"
oras attach --no-tty --registry-config "${HOME}/auth.json" --artifact-type "${MEDIA_TYPE}" "${IMAGE_URL}" "${UPLOAD_FILE}:${MEDIA_TYPE}"
Loading

0 comments on commit 6dc6006

Please sign in to comment.