-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use kustomize to build sast-coverity-check
... from the build-container task
- Loading branch information
Showing
4 changed files
with
1,092 additions
and
247 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
apiVersion: kustomize.config.k8s.io/v1beta1 | ||
kind: Kustomization | ||
|
||
resources: | ||
- ../../buildah/0.2 | ||
|
||
patches: | ||
- path: patch.yaml | ||
target: | ||
kind: Task |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,349 @@ | ||
# 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: Tekton task test output. | ||
name: TEST_OUTPUT | ||
|
||
################### | ||
# 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:4c17d06f245d124bed3f8f50085144d5237fd09e9c72897fde84a694780c65de | ||
|
||
# Change build step resources | ||
- op: replace | ||
path: /spec/steps/0/computeResources/limits/cpu | ||
value: 16 | ||
- op: replace | ||
path: /spec/steps/0/computeResources/limits/memory | ||
value: 16Gi | ||
- op: replace | ||
path: /spec/steps/0/computeResources/requests/cpu | ||
value: 4 | ||
- op: replace | ||
path: /spec/steps/0/computeResources/requests/memory | ||
value: 4Gi | ||
|
||
# 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 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: "" | ||
|
||
# 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 | ||
/usr/libexec/csgrep-static:/usr/libexec/csgrep-static | ||
# Add prepare step | ||
- op: add | ||
path: /spec/steps/0 | ||
value: | ||
name: prepare | ||
image: quay.io/redhat-user-workloads/sast-tenant/sast-scanner/coverity@sha256:4c17d06f245d124bed3f8f50085144d5237fd09e9c72897fde84a694780c65de | ||
workingDir: $(workspaces.source.path) | ||
env: | ||
- name: DOCKERFILE | ||
value: $(params.DOCKERFILE) | ||
volumeMounts: | ||
- name: cov-license | ||
mountPath: "/etc/secrets/cov" | ||
readOnly: true | ||
script: | | ||
#!/bin/bash -x | ||
# FIXME: 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 | ||
# install Coverity license file | ||
install -vm0644 /etc/secrets/cov/cov-license /shared/license.dat | ||
# pre-create directory for SAST scaning results | ||
mkdir "/shared/sast-results" | ||
# create a wrapper script to instrument RUN lines | ||
tee /shared/cmd-wrap.sh << EOF | ||
#!/bin/bash -x | ||
id >&2 | ||
# use current directory as project directory by default | ||
proj_dir=\$(pwd) | ||
# if current directory is "/", fallback to user's home directory | ||
[ / = "\$proj_dir" ] && proj_dir=\$HOME | ||
[ -z "\$proj_dir" ] && proj_dir=\$(echo ~) | ||
# wrap the RUN command with "coverity capture" | ||
/opt/coverity/bin/coverity --ticker-mode=no-spin capture --dir=/tmp/idir --project-dir="\$proj_dir" -- "\$@" | ||
EC=\$? | ||
# install Coverity license file | ||
install -vm0644 /{shared,opt/coverity/bin}/license.dat | ||
# use cov-analyze instead of "coverity analyze" so that we can handle $COV_ANALYZE_ARGS | ||
/opt/coverity/bin/cov-analyze --dir=/tmp/idir $COV_ANALYZE_ARGS | ||
# export scan results and embed source code context into the scan results | ||
/opt/coverity/bin/cov-format-errors --dir=/tmp/idir --json-output-v10 /dev/stdout \ | ||
| /usr/libexec/csgrep-static --mode=json --embed-context=3 \ | ||
> \$(mktemp /shared/sast-results/\$\$-XXXX.json) | ||
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 | ||
|
||
# Add postprocess step | ||
- op: add | ||
path: /spec/steps/2 | ||
value: | ||
name: postprocess | ||
image: quay.io/redhat-user-workloads/sast-tenant/sast-scanner/coverity@sha256:4c17d06f245d124bed3f8f50085144d5237fd09e9c72897fde84a694780c65de | ||
computeResources: | ||
limits: | ||
memory: 4Gi | ||
cpu: 4 | ||
requests: | ||
memory: 2Gi | ||
cpu: 2 | ||
volumeMounts: | ||
- name: trusted-ca | ||
mountPath: "/mnt/trusted-ca" | ||
readOnly: true | ||
env: | ||
- name: IMAGE_URL | ||
value: $(params.IMAGE_URL) | ||
- name: COV_ANALYZE_ARGS | ||
value: $(params.COV_ANALYZE_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: | | ||
#!/bin/bash -ex | ||
# shellcheck source=/dev/null | ||
set -o pipefail | ||
. /usr/local/share/konflux-test/utils.sh | ||
trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT | ||
[ -n "${PROJECT_NAME}" ] || PROJECT_NAME="${COMPONENT_LABEL}" | ||
echo "The PROJECT_NAME used is: ${PROJECT_NAME}" | ||
# 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 [ -z "$(ls /shared/sast-results/)" ]; then ( | ||
set +e | ||
# fallback to buildless scan if we have no scan results from buildful | ||
# shellcheck disable=SC2086 | ||
env HOME=/var/tmp/coverity/home /opt/coverity/bin/coverity capture --disable-build-command-inference --dir /tmp/idir --project-dir "$(workspaces.source.path)" | ||
# install Coverity license file | ||
install -vm0644 /{shared,opt/coverity/bin}/license.dat | ||
# shellcheck disable=SC2086 | ||
/opt/coverity/bin/cov-analyze $COV_ANALYZE_ARGS --dir=/tmp/idir | ||
# export scan results | ||
/opt/coverity/bin/cov-format-errors --dir=/tmp/idir --json-output-v10 /dev/stdout \ | ||
| csgrep --mode=json --embed-context=3 \ | ||
> /shared/sast-results/coverity-buildless.json | ||
) fi | ||
# collect scan results | ||
csgrep --mode=json --remove-duplicates --file-glob '/shared/sast-results/*' \ | ||
| tee /tmp/coverity-results.json \ | ||
| csgrep --mode=evtstat | ||
# 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 | ||
csgrep --mode=json --imp-level="$IMP_LEVEL" --remove-duplicates /tmp/coverity-results.json \ | ||
| tee coverity-results-raw.json \ | ||
| csgrep --mode=evtstat | ||
# 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 | ||
# convert the scan results into SARIF | ||
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)" | ||
# upload scan results | ||
# TODO: upload excluded-findings.json if enabled | ||
UPLOAD_FILE="coverity-results.sarif" | ||
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}" |
Oops, something went wrong.