Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 2 Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.access.redhat.com/ubi9/go-toolset:1.23.6-1745328278 as check-payload-build
FROM registry.access.redhat.com/ubi9/go-toolset:1.25.3-1765311584 as check-payload-build

WORKDIR /opt/app-root/src

Expand Down
2 changes: 1 addition & 1 deletion 2 rox/auth-task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ spec:
- name: rox_central_endpoint
description: The address:port tuple for RHACS Stackrox Central.
type: string
default: central.stackrox.svc:443
default: https://acs-d3t60hcejrms73e5dk6g.acs.rhcloud.com
- name: insecure-skip-tls-verify
description: |
Do not verify TLS certificates.
Expand Down
380 changes: 380 additions & 0 deletions 380 rox/rox-sample-task.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,380 @@
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: rhacs-m2m-authenticate
labels:
app.kubernetes.io/version: "0.1"
annotations:
tekton.dev/tags: security
tekton.dev/categories: Security
tekton.dev/displayName: "Exchange a service account token for a Red Hat Advanced Cluster Security short-lived token"
tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le,linux/s390x,darwin/amd64,darwin/arm64,windows/amd64"
tekton.dev/pipelines.minVersion: "0.50.0"
spec:
description: >-
Exchanges a kubernetes service account token against a Red Hat Advanced Cluster Security short-lived token.
params:
- name: image-digest
description: Image digest to scan.
default: sha256:18f99f1ede83f7e522a96180dae9a0f25924e5afacf3e1357ffcd8a6d635d510
- name: rox_image
description: Image providing the roxctl tool.
default: 'registry.redhat.io/advanced-cluster-security/rhacs-roxctl-rhel8@sha256:d6d5e50d1deda1e7b232d4e3f60fda6f3d27266b6fc007c8ec48a324e1c6c15c'
- name: rox_central_endpoint
description: The address:port tuple for RHACS Stackrox Central.
type: string
default: https://acs-d3t60hcejrms73e5dk6g.acs.rhcloud.com
- name: image
type: string
description: |
Full name of image to scan.

SHA 256 digest may be included to ensure scan of sequental runs with same tag.
Examples: 'gcr.io/rox/sample:5.0-rc1', '$(params.IMAGE)', '$(params.IMAGE)@$(tasks.buildah.results.IMAGE_DIGEST)'
default: quay.io/redhat-user-workloads-stage/kpavic-tenant/test-project-minimal:on-pr-92951c0ca7e0dccb9fe87c30d5033f3044c0c97d
- name: insecure-skip-tls-verify
description: |
Do not verify TLS certificates.

When set to "true", skip verifying the TLS certs of the Central endpoint.
type: string
default: "false"
- name: output_format
type: string
description: Results output format (json | csv | table)
default: json
- name: rox_token_file
description: |
Path to the API Token file (if authentication through API token).
Mutually exclusive with rox_config_dir.
The path must be prefixed with "/rox-api-token-auth".
Example "/rox-api-token-auth/rox_api_token"
type: string
default: ""
- name: rox_config_dir
type: string
description: |
Path to the roxtl config directory within the roxctl-config workspace.
The path must be prefixed with "/roxctl-config".
default: ""
- name: output_file
type: string
description: |
Path to a file where to write the roxctl standard output stream.
If empty, the output stream goes to the container standard output.
default: /tekton/home/output.yaml
- name: error_file
type: string
description: |
Path to a file where to write the roxctl standard error stream.
If empty, the error stream goes to the container standard error.
default: /tekton/home/error.yaml
results:
- name: TEST_OUTPUT
description: Tekton task test output.
- name: SCAN_OUTPUT
description: Clair scan result.
- name: IMAGES_PROCESSED
description: Images processed in the task.
- name: REPORTS
description: Mapping of image digests to report digests
stepTemplate:
env:
- name: INSECURE
value: $(params.insecure-skip-tls-verify)
- name: ROX_ENDPOINT
value: $(params.rox_central_endpoint)
- name: ROX_CONFIG_DIR
value: /tekton/home
- name: ROX_EXECUTION_ENV
value: Tekton
- name: ROX_OUTPUT_FILE
value: $(params.output_file)
- name: ROX_ERROR_FILE
value: $(params.error_file)
steps:
- name: exchange-service-account-token
workingDir: /tekton/home
image: $(params.rox_image)
volumeMounts:
- name: token-vol
mountPath: /service-account-token
args:
- central
- m2m
- exchange
- --insecure-skip-tls-verify=$(INSECURE)
- --token-file=/service-account-token/token
- name: get-image-manifests
image: quay.io/konflux-ci/konflux-test:v1.4.40@sha256:99eb8bcc7bcb35bdd5edea7b0ac333bbdb67586dea6b4dab92baf2b8fb32bf2c
# the clair-in-ci image neither has skopeo or jq installed. Hence, we create an extra step to get the image manifest digests
computeResources:
limits:
memory: 512Mi
requests:
memory: 256Mi
cpu: 100m
env:
- name: IMAGE_URL
value: $(params.image)
- name: IMAGE_DIGEST
value: $(params.image-digest)
securityContext:
capabilities:
add:
- SETFCAP
script: |
#!/usr/bin/env bash
set -euo pipefail
# shellcheck source=/dev/null
. /utils.sh

imagewithouttag=$(echo -n $IMAGE_URL | sed "s/\(.*\):.*/\1/")
# strip new-line escape symbol from parameter and save it to variable
imageanddigest=$(echo $imagewithouttag@$IMAGE_DIGEST)
echo "Inspecting raw image manifest $imageanddigest."

# Get the arch and image manifests by inspecting the image. This is mainly for identifying image indexes
image_manifests=$(get_image_manifests -i "${imageanddigest}")
if [ -n "$image_manifests" ]; then
echo "$image_manifests" | jq -r 'to_entries[] | "\(.key) \(.value)"' | while read -r arch arch_sha; do
echo "$arch_sha" > /tekton/home/image-manifest-$arch.sha
done
else
echo "Failed to get image manifests from image \"$imageanddigest\""
note="Task $(context.task.name) failed: Failed to get image manifests from image \"$imageanddigest\". For details, check Tekton task log."
ERROR_OUTPUT=$(make_result_json -r "ERROR" -t "$note")
echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)"
exit 0
fi
- name: rox-image-scan
image: $(params.rox_image)
env:
- name: HOME
value: /tekton/home
- name: IMAGE
value: $(params.image)
- name: INSECURE
value: $(params.insecure-skip-tls-verify)
- name: OUTPUT
value: $(params.output_format)
- name: ROX_CONFIG_DIR
value: $(params.rox_config_dir)
- name: ROX_API_TOKEN_FILE
value: $(params.rox_token_file)
- name: ROX_ENDPOINT
value: $(params.rox_central_endpoint)
- name: ROX_EXECUTION_ENV
value: Tekton
- name: ROX_OUTPUT_FILE
value: $(params.output_file)
- name: ROX_ERROR_FILE
value: $(params.error_file)
script: |
#!/usr/bin/env bash
roxctl image scan --insecure-skip-tls-verify=$INSECURE --output=$OUTPUT --image=$IMAGE | tee /tekton/home/rox-output.json
- name: proccess-output
image: quay.io/konflux-ci/konflux-test:v1.4.42@sha256:32112ba0f1b8a3944f4905be40308713c32beb6c059c42ef0bc2b5fe7947ff2f
env:
- name: IMAGE_URL
value: $(params.image)
- name: IMAGE_DIGEST
value: $(params.image-digest)
workingDir: /tekton/home
script: |
#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail
# shellcheck source=/utils.sh
. /utils.sh

imagewithouttag=$(echo -n $IMAGE_URL | sed "s/\(.*\):.*/\1/")
images_processed_template='{"image": {"pullspec": "'"$IMAGE_URL"'", "digests": [%s]}}'
digests_processed=()

# the quay report format used by the Conftest rules in the
# conftest-vulnerabilities step doesn't contain the "issued" date which
# we require in the policy rules, so we resort to running clair-action
# twice to produce both quay and clair formatted output
# UPDATE ^^^^^^^

for sha_file in image-manifest-*.sha; do
if [ -e "$sha_file" ]; then
arch_sha=$(cat "$sha_file")
arch=$(basename "$sha_file" | sed 's/image-manifest-//;s/.sha//')
arch_specific_digest="$imagewithouttag@$arch_sha"

digests_processed+=("\"$arch_sha\"")
fi
done

# If the image is an Image Index, also add the Image Index digest to the list.
if [[ "${digests_processed[*]}" != *"$IMAGE_DIGEST"* ]]; then
digests_processed+=("\"$IMAGE_DIGEST\"")
fi
digests_processed_string=$(IFS=,; echo "${digests_processed[*]}")

images_processed=$(echo "${images_processed_template/\[%s]/[$digests_processed_string]}")
echo "$images_processed" > images-processed.json
- name: oci-attach-report
image: quay.io/konflux-ci/oras:latest@sha256:4542f5a2a046ca36653749a8985e46744a5d2d36ee10ca14409be718ce15129e
workingDir: /tekton/home
env:
- name: IMAGE_URL
value: $(params.image)
script: |
#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail
ls /tekton/home

if ! compgen -G "rox-output*.json" > /dev/null; then
echo 'No Rox reports generated. Skipping upload.'
exit 0
fi

echo "Selecting auth"
select-oci-auth "$IMAGE_URL" > "$HOME/auth.json"

repository="${IMAGE_URL/:*/}"

arch() {
report_file="$1"
arch="${report_file/*-}"
echo "${arch/.json/}"
}

MEDIA_TYPE='application/vnd.redhat.rox-report+json'

reports_json=""
for f in image-manifest-*.sha; do
digest=$(cat "image-manifest-$(arch "$f")")
image_ref="${repository}@${digest}"
echo "Attaching $f to ${image_ref}"
if ! report_digest="$(retry oras attach --no-tty --format go-template='{{.digest}}' --registry-config \
"$HOME/auth.json" --artifact-type "${MEDIA_TYPE}" "${image_ref}" "$f:${MEDIA_TYPE}")"
then
echo "Failed to attach ${f} to ${image_ref}"
exit 1
fi
# shellcheck disable=SC2016
reports_json="$(yq --output-format json --indent=0 eval-all '. as $i ireduce ({}; . * $i)' <(echo "${reports_json}") <(echo "${digest}: ${report_digest}"))"
done
echo "${reports_json}" > reports.json
- name: conftest-vulnerabilities
image: quay.io/konflux-ci/konflux-test:v1.4.42@sha256:32112ba0f1b8a3944f4905be40308713c32beb6c059c42ef0bc2b5fe7947ff2f
# per https://kubernetes.io/docs/concepts/containers/images/#imagepullpolicy-defaulting
# the cluster will set imagePullPolicy to IfNotPresent
computeResources:
limits:
memory: 2Gi
requests:
memory: 256Mi
cpu: 100m
securityContext:
capabilities:
add:
- SETFCAP
script: |
#!/usr/bin/env bash
set -euo pipefail
. /utils.sh
trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT

rox_result_files=$(ls /tekton/home/rox-output*.json)
if [ -z "$rox_result_files" ]; then
echo "Previous step [get-vulnerabilities] failed: No rox-output files found in /tekton/home."
fi

missing_vulnerabilities_files=""
for file in $rox_result_files; do
file_suffix=$(basename "$file" | sed 's/rox-result-//;s/.json//')
if [ ! -s "$file" ]; then
echo "Previous step [get-vulnerabilities] failed: $file is empty."
else
/usr/bin/conftest test --no-fail $file \
--policy /project/roxctl/vulnerabilities-check.rego --namespace required_checks \
--output=json | tee /tekton/home/rox-vulnerabilities-$file_suffix.json || true
fi

#check for missing "rox-vulnerabilities-<arch>/image-index" file and create a string
if [ ! -f "/tekton/home/rox-vulnerabilities-$file_suffix.json" ]; then
missing_vulnerabilities_files+="${missing_vulnerabilities_files:+, }/tekton/home/rox-vulnerabilities-$file_suffix.json"
fi
done

if [ -n "$missing_vulnerabilities_files" ]; then
note="Task $(context.task.name) failed: $missing_vulnerabilities_files did not generate. For details, check Tekton task log."
TEST_OUTPUT=$(make_result_json -r "ERROR" -t "$note")
echo "$missing_vulnerabilities_files did not generate correctly. For details, check conftest command in Tekton task log."
echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path)
exit 0
fi

scan_result='{"vulnerabilities":{"critical":0, "high":0, "medium":0, "low":0, "unknown":0}, "unpatched_vulnerabilities":{"critical":0, "high":0, "medium":0, "low":0, "unknown":0}}'
for file in /tekton/home/rox-vulnerabilities-*.json; do
result=$(jq -rce \
'{
vulnerabilities:{
critical: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_critical_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
high: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_high_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
medium: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_medium_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
low: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_low_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
unknown: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_unknown_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0)
},
unpatched_vulnerabilities:{
critical: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_unpatched_critical_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
high: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_unpatched_high_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
medium: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_unpatched_medium_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
low: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_unpatched_low_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0),
unknown: (.[] | .warnings? // [] | map(select(.metadata.details.name=="roxctl_unpatched_unknown_vulnerabilities").metadata."vulnerabilities_number" // 0)| add // 0)
}
}' "$file")

scan_result=$(jq -s -rce \
'.[0].vulnerabilities.critical += .[1].vulnerabilities.critical |
.[0].vulnerabilities.high += .[1].vulnerabilities.high |
.[0].vulnerabilities.medium += .[1].vulnerabilities.medium |
.[0].vulnerabilities.low += .[1].vulnerabilities.low |
.[0].vulnerabilities.unknown += .[1].vulnerabilities.unknown |
.[0].unpatched_vulnerabilities.critical += .[1].unpatched_vulnerabilities.critical |
.[0].unpatched_vulnerabilities.high += .[1].unpatched_vulnerabilities.high |
.[0].unpatched_vulnerabilities.medium += .[1].unpatched_vulnerabilities.medium |
.[0].unpatched_vulnerabilities.low += .[1].unpatched_vulnerabilities.low |
.[0].unpatched_vulnerabilities.unknown += .[1].unpatched_vulnerabilities.unknown |
.[0]' <<<"$scan_result $result")
done

echo "$scan_result" | tee "$(results.SCAN_OUTPUT.path)"

cat /tekton/home/images-processed.json | tee $(results.IMAGES_PROCESSED.path)
# shellcheck disable=SC2154
cat /tekton/home/reports.json > "$(results.REPORTS.path)"

note="Task $(context.task.name) completed: Refer to Tekton task result SCAN_OUTPUT for vulnerabilities scanned by Rox."
TEST_OUTPUT=$(make_result_json -r "SUCCESS" -t "$note")
echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path)
volumes:
- name: token-vol
projected:
sources:
- serviceAccountToken:
audience: rhacs
path: token
expirationSeconds: 3600
- name: trusted-ca
configMap:
name: $(params.ca-trust-config-map-name)
items:
- key: $(params.ca-trust-config-map-key)
path: ca-bundle.crt
optional: true




Morty Proxy This is a proxified and sanitized view of the page, visit original site.