Information Security 10 min read

Using Witness for Software Supply Chain Security in Non‑GitHub Environments

This article explains how to generate and verify software artifact provenance with the Witness framework in non‑GitHub ecosystems, covering installation, key creation, configuration, running, signing, and policy verification to achieve higher SLSA levels.

DevOps Engineer
DevOps Engineer
DevOps Engineer
Using Witness for Software Supply Chain Security in Non‑GitHub Environments

What is Witness

Witness is a pluggable supply‑chain security framework that creates provenance evidence for the entire software development lifecycle (SDLC), ensuring integrity from source code to final artifact. It integrates with most CI and infrastructure providers and enhances security through PKI‑based metadata distribution and verification.

What Witness Can Do

Verify who built the software, how it was built, and which tools were used.

Detect potential tampering or malicious activity.

Ensure that only authorized users or machines can perform each step of the process.

Distribute attestations and policies.

How to Use Witness

The workflow consists of three main commands:

witness run – Execute a command and record an attestation.

witness sign – Sign the generated files with a private key.

witness verify – Verify the attestation against a policy.

Quick Start

Install Witness and clone the demo repository:

bash <(curl -s https://raw.githubusercontent.com/in-toto/witness/main/install-witness.sh)
Latest version of Witness is 0.1.14
Downloading for linux amd64 from https://github.com/in-toto/witness/releases/download/v0.1.14/witness_0.1.14_linux_amd64.tar.gz
expected checksum: f9b67ca04cb391cd854aec3397eb904392ff689dcd3c38305d38c444781a5a67
file checksum:     f9b67ca04cb391cd854aec3397eb904392ff689dcd3c38305d38c444781a5a67
witness v0.1.14-aa35c1f
Witness v0.1.14 has been installed at /usr/local/bin/witness

git clone https://github.com/shenxianpeng/witness-demo.git

Create an Ed25519 key pair for signing:

openssl genpkey -algorithm ed25519 -outform PEM -out witness-demo-key.pem
openssl pkey -in witness-demo-key.pem -pubout > witness-demo-pub.pem

Prepare the Witness Configuration File (.witness.yaml)

run:
    signer-file-key-path: witness-demo-key.pem
    trace: false
verify:
    attestations:
        - "witness-demo-att.json"
    policy: policy-signed.json
    publickey: witness-demo-pub.pem

Record Build Steps as Attestations

witness run --step build -o witness-demo-att.json -- python3 -m pip wheel --no-deps -w dist .
INFO    Using config file: .witness.yaml
INFO    Starting environment attestor...
INFO    Starting git attestor...
INFO    Starting material attestor...
INFO    Starting command-run attestor...
Processing /tmp/witness-demo
Building wheels for collected packages: witness-demo
  Running setup.py bdist_wheel for witness-demo: started
  Running setup.py bdist_wheel for witness-demo: finished with status 'done'
  Stored in directory: /tmp/witness-demo/dist
Successfully built witness-demo
INFO    Starting product attestor...

Insert witness run into any build command to capture its provenance.

View the Signed Attestation

Attestation data is base64‑encoded; decode it to inspect:

cat witness-demo-att.json | jq -r .payload | base64 -d | jq
# Sample output (truncated)
{
  "type": "https://witness.dev/attestations/command-run/v0.1",
  "attestation": {
    "cmd": ["python3","-m","pip","wheel","--no-deps","-w","dist","."],
    "stdout": "Processing /tmp/witness-demo\n...\nSuccessfully built witness-demo\n",
    "exitcode": 0
  },
  "starttime": "2023-11-29T05:15:19.227943473-05:00",
  "endtime": "2023-11-29T05:15:20.078517025-05:00"
},
{ ... product attestation ... }

Create a Policy File (policy.json)

The policy defines required attributes for each step, such as an expiration time:

{
  "expires": "2033-12-17T23:57:40-05:00",
  "steps": {
    "build": {
      "name": "build",
      "attestations": [
        {"type": "https://witness.dev/attestations/material/v0.1", "regopolicies": []},
        {"type": "https://witness.dev/attestations/command-run/v0.1", "regopolicies": []},
        {"type": "https://witness.dev/attestations/product/v0.1", "regopolicies": []}
      ],
      "functionaries": [{"publickeyid": "{{PUBLIC_KEY_ID}}"}]
    }
  },
  "publickeys": {
    "{{PUBLIC_KEY_ID}}": {"keyid": "{{PUBLIC_KEY_ID}}", "key": "{{B64_PUBLIC_KEY}}"}
  }
}

Replace the placeholders with the actual public‑key ID and base64‑encoded key:

id=$(sha256sum witness-demo-pub.pem | awk '{print $1}') && \
sed -i "s/{{PUBLIC_KEY_ID}}/$id/g" policy.json

pubb64=$(cat witness-demo-pub.pem | base64 -w 0) && \
sed -i "s/{{B64_PUBLIC_KEY}}/$pubb64/g" policy.json

Sign the Policy

witness sign -f policy.json --signer-file-key-path witness-demo-key.pem --outfile policy-signed.json
INFO    Using config file: .witness.yaml

Verify an Artifact Against the Policy

witness verify -f dist/witness_demo-1.0.0-py3-none-any.whl -a witness-demo-att.json -p policy-signed.json -k witness-demo-pub.pem
INFO    Using config file: .witness.yaml
INFO    Verification succeeded
INFO    Evidence:
INFO    0: witness-demo-att.json

Conclusion

The steps above demonstrate how to apply Witness for supply‑chain provenance in projects that are not hosted on GitHub. For GitHub‑hosted projects, the most common approach is to use the slsa‑github‑generator and slsa‑verifier tools provided by the SLSA Framework.

CI/CDsecuritysoftware supply chainSLSAProvenanceWitness
DevOps Engineer
Written by

DevOps Engineer

DevOps engineer, Pythonista and FOSS contributor. Created cpp-linter, commit-check, etc.; contributed to PyPA.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.