-
Notifications
You must be signed in to change notification settings - Fork 10
Add check-source-origin Tekton task for sdist supply-chain verification #300
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
base: main
Are you sure you want to change the base?
Changes from all commits
c1ea8c5
0a7caa7
98b5b51
73a363b
5682abc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| --- | ||
| apiVersion: tekton.dev/v1 | ||
| kind: Task | ||
| metadata: | ||
| name: check-source-origin | ||
| annotations: | ||
| tekton.dev/pipelines.minVersion: 0.12.1 | ||
| tekton.dev/tags: security, supply-chain, python, sdist | ||
| labels: | ||
| app.kubernetes.io/version: "0.1" | ||
| spec: | ||
| description: >- | ||
| Verify Python sdist supply-chain integrity by comparing PyPI sdists against | ||
| their VCS source repositories using check-source-origin. Non-blocking: | ||
| gracefully skips when GitHub token is missing. | ||
| params: | ||
| - name: PACKAGES | ||
| description: >- | ||
| JSON array of packages in "name==version" format, e.g. | ||
| '["requests==2.32.0","click==8.1.7"]'. Produced by identify-packages. | ||
| type: string | ||
| - name: CSO_GIT_REF | ||
| description: >- | ||
| Git ref (tag, branch, or commit SHA) of check-source-origin to install. | ||
| Pin to a specific commit or tag for reproducible builds. | ||
| type: string | ||
| default: main | ||
| - name: FAIL_SEVERITY | ||
| description: >- | ||
| Result severity for verification failures and invalid input. Use | ||
| WARNING while validating the task, switch to ERROR once reliable. | ||
| type: string | ||
| default: WARNING | ||
| - name: caTrustConfigMapName | ||
| description: The name of the ConfigMap to read CA bundle data from. | ||
| type: string | ||
| default: trusted-ca | ||
| - name: caTrustConfigMapKey | ||
| description: The name of the key in the ConfigMap that contains the CA bundle data. | ||
| type: string | ||
| default: ca-bundle.crt | ||
| results: | ||
| - name: TEST_OUTPUT | ||
| description: >- | ||
| Source origin check result in JSON format. Possible result values: | ||
| SKIPPED (no token or no packages), SUCCESS (all packages verified), | ||
| WARNING (differences or errors found), ERROR (all checks failed). | ||
| workspaces: | ||
| - name: basic-auth | ||
| description: Git credentials workspace (contains .git-credentials with GitHub token) | ||
| optional: true | ||
| volumes: | ||
| - name: trusted-ca | ||
| configMap: | ||
| items: | ||
| - key: $(params.caTrustConfigMapKey) | ||
| path: ca-bundle.crt | ||
| name: $(params.caTrustConfigMapName) | ||
| optional: true | ||
| - name: workdir | ||
| emptyDir: {} | ||
| steps: | ||
| - name: check-source-origin | ||
| image: registry.access.redhat.com/ubi9/python-312:latest@sha256:16799d5b958c5ce3b5fa6e522c8251c85df3313a6f21983de6a95818cfa14fcd | ||
| volumeMounts: | ||
| - mountPath: /etc/pki/tls/certs/ca-custom-bundle.crt | ||
| name: trusted-ca | ||
| readOnly: true | ||
| subPath: ca-bundle.crt | ||
| - mountPath: /var/workdir | ||
| name: workdir | ||
| env: | ||
| - name: PACKAGES | ||
| value: $(params.PACKAGES) | ||
| script: | | ||
| #!/bin/bash | ||
| set -euo pipefail | ||
|
|
||
| CA_BUNDLE="/etc/pki/tls/certs/ca-custom-bundle.crt" | ||
| if [ -s "${CA_BUNDLE}" ]; then | ||
| export SSL_CERT_FILE="${CA_BUNDLE}" | ||
| export REQUESTS_CA_BUNDLE="${CA_BUNDLE}" | ||
| fi | ||
|
|
||
| RESULT_FILE="$(results.TEST_OUTPUT.path)" | ||
|
|
||
| GIT_CREDENTIALS="$(workspaces.basic-auth.path)/.git-credentials" | ||
| if [ "$(workspaces.basic-auth.bound)" != "true" ] || [ ! -f "${GIT_CREDENTIALS}" ]; then | ||
| echo "Git credentials not found — skipping source origin check." | ||
| echo '{"result":"ERROR","namespace":"default","successes":0,"failures":0,"warnings":0,"note":"git-auth workspace not bound"}' | tee "${RESULT_FILE}" | ||
| exit 0 | ||
| fi | ||
|
|
||
| { set +x; } 2>/dev/null | ||
| GH_TOKEN="$(grep github.com "${GIT_CREDENTIALS}" 2>/dev/null | sed 's|.*://[^:]*:\([^@]*\)@.*|\1|' | head -1 || true)" | ||
| export GH_TOKEN | ||
| if [ -z "${GH_TOKEN}" ]; then | ||
| echo "No GitHub token found in git credentials — skipping." | ||
|
Comment on lines
+95
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (bug_risk): Align the reported result for missing GitHub token with the documented non-blocking behavior This path logs that the check is skipped but still writes |
||
| echo '{"result":"ERROR","namespace":"default","successes":0,"failures":0,"warnings":0,"note":"no github token in git-credentials"}' | tee "${RESULT_FILE}" | ||
| exit 0 | ||
| fi | ||
|
|
||
| cp "${GIT_CREDENTIALS}" ~/.git-credentials | ||
| chmod 600 ~/.git-credentials | ||
| GIT_CONFIG="$(workspaces.basic-auth.path)/.gitconfig" | ||
| if [ -f "${GIT_CONFIG}" ]; then | ||
| cp "${GIT_CONFIG}" ~/.gitconfig | ||
| chmod 600 ~/.gitconfig | ||
| fi | ||
|
|
||
| FAIL_SEVERITY="$(params.FAIL_SEVERITY)" | ||
|
|
||
| if ! PACKAGE_LIST="$(echo "${PACKAGES}" | python3 -c "import json,sys; [print(p) for p in json.load(sys.stdin)]")"; then | ||
| echo "Failed to parse PACKAGES JSON." | ||
| echo "{\"result\":\"${FAIL_SEVERITY}\",\"namespace\":\"default\",\"successes\":0,\"failures\":0,\"warnings\":0,\"note\":\"invalid PACKAGES JSON\"}" | tee "${RESULT_FILE}" | ||
| exit 0 | ||
| fi | ||
| if [ -z "${PACKAGE_LIST}" ]; then | ||
| echo "No packages to check." | ||
| echo "{\"result\":\"${FAIL_SEVERITY}\",\"namespace\":\"default\",\"successes\":0,\"failures\":0,\"warnings\":0,\"note\":\"no packages\"}" | tee "${RESULT_FILE}" | ||
| exit 0 | ||
| fi | ||
|
|
||
| CSO_REF="$(params.CSO_GIT_REF)" | ||
| pip install --quiet "check-source-origin @ git+https://github.com/calungaproject/check-source-origin.git@${CSO_REF}" | ||
|
|
||
| SUCCESSES=0 | ||
| FAILURES=0 | ||
| ERRORS=0 | ||
| TOTAL=0 | ||
|
|
||
| while IFS= read -r pkg; do | ||
| [ -z "${pkg}" ] && continue | ||
| NAME="${pkg%%==*}" | ||
| VERSION="${pkg##*==}" | ||
| TOTAL=$((TOTAL + 1)) | ||
|
|
||
| echo "==================================================" | ||
| echo "Checking: ${NAME}==${VERSION}" | ||
|
|
||
| set +e | ||
| check-source-origin verify "${NAME}" "${VERSION}" --json-output 2>&1 | ||
| RC=$? | ||
| set -e | ||
|
|
||
| if [ ${RC} -eq 0 ]; then | ||
| echo "PASS: ${NAME}==${VERSION}" | ||
| SUCCESSES=$((SUCCESSES + 1)) | ||
| elif [ ${RC} -eq 1 ]; then | ||
| echo "FAIL: ${NAME}==${VERSION}" | ||
| FAILURES=$((FAILURES + 1)) | ||
| else | ||
| echo "ERROR: ${NAME}==${VERSION} (exit code ${RC})" | ||
| ERRORS=$((ERRORS + 1)) | ||
| fi | ||
| done <<< "${PACKAGE_LIST}" | ||
|
|
||
| echo "" | ||
| echo "==================================================" | ||
| echo " SOURCE ORIGIN CHECK SUMMARY" | ||
| echo "==================================================" | ||
| echo "Packages checked: ${TOTAL}" | ||
| echo "Passed: ${SUCCESSES}" | ||
| echo "Failed: ${FAILURES}" | ||
| echo "Errors: ${ERRORS}" | ||
| echo "" | ||
|
|
||
| WARNINGS=$((FAILURES + ERRORS)) | ||
|
|
||
| if [ "${TOTAL}" -eq 0 ]; then | ||
| echo "{\"result\":\"${FAIL_SEVERITY}\",\"namespace\":\"default\",\"successes\":0,\"failures\":0,\"warnings\":0,\"note\":\"no packages\"}" | tee "${RESULT_FILE}" | ||
| elif [ "${ERRORS}" -eq "${TOTAL}" ]; then | ||
| echo "{\"result\":\"${FAIL_SEVERITY}\",\"namespace\":\"default\",\"successes\":0,\"failures\":${ERRORS},\"warnings\":0,\"note\":\"all checks failed\"}" | tee "${RESULT_FILE}" | ||
| elif [ "${WARNINGS}" -gt 0 ]; then | ||
| echo "{\"result\":\"${FAIL_SEVERITY}\",\"namespace\":\"default\",\"successes\":${SUCCESSES},\"failures\":${FAILURES},\"warnings\":${WARNINGS},\"note\":\"source origin differences or errors found\"}" | tee "${RESULT_FILE}" | ||
| else | ||
| echo "{\"result\":\"SUCCESS\",\"namespace\":\"default\",\"successes\":${SUCCESSES},\"failures\":0,\"warnings\":0,\"note\":\"all packages verified against VCS source\"}" | tee "${RESULT_FILE}" | ||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): Consider using a non-error result when intentionally skipping due to missing git credentials
This path reports
"result":"ERROR"while exiting 0 and logging a skip, which conflicts with the task’s "gracefully skip" contract and can mislead consumers that only readTEST_OUTPUT. Please use a non-error result (e.g.,SKIPPED) or connect this toFAIL_SEVERITYso missing credentials are treated as a visible skip rather than a hard error in the output.Suggested implementation:
FAIL_SEVERITY, you may want to introduce aRESULT_STATUSvariable that derives from those conventions and reuse it in allTEST_OUTPUTwrites for consistency."result":"ERROR"as a hard failure may need to be updated to also look for"result":"SKIPPED"to distinguish intentional skips from actual errors.