This quick tutorial will walk you through a simple example of how Witness can be used. To complete it successfully, you will need the following:
You will also of course need to have witness installed, which can be achieved by following the Quick Start.
💡 Tip: Witness supports keyless signing with SPIRE!
openssl genpkey -algorithm ed25519 -outform PEM -out testkey.pem
openssl pkey -in testkey.pem -pubout > testpub.pem
💡 Tip: Witness supports creating attestations for a wide variety of services, including Github Actions
- This file generally resides in your source code repository along with the public keys generated above.
.witness.yaml
is the default location for the configuration filewitness help
will show all configuration options- command-line arguments overrides configuration file values.
## .witness.yaml
run:
signer-file-key-path: testkey.pem
trace: false
verify:
attestations:
- "test-att.json"
policy: policy-signed.json
publickey: testpub.pem
💡 Tip: You can upload the recorded attestations to an Archivista server by using the
--enable-archivista
flag!
- The
-a {attestor}
flag allows you to define which attestors run - ex.
-a maven -a gcp -a gitlab
would be used for a maven build running on a GitLab runner on GCP. - Witness has a set of attestors that are always run. You can see them in the output of the
witness attestors list
command. - Defining step names is important, these will be used in the policy.
- This should happen as a part of a CI step
witness run --step build -o test-att.json -a slsa --attestor-slsa-export -- go build -o=testapp .
💡 Tip: The
-a slsa
option allows to generate the SLSA Provenace predicate in the attestation. The--attestor-slsa-export
option allows to write the Provenance in a dedicated file. This is a mandatory requirement for SLSA Level 1
- This data can be stored and retrieved from Archivista
- This is the data that is evaluated against the Rego policy
cat test-att.json | jq -r .payload | base64 -d | jq
Look here for full documentation on Witness Policies.
- Make sure to replace the keys in this file with the ones from the step above (sed command below).
- Rego policies should be base64 encoded
- Steps are bound to keys. Policy can be written to check the certificate data. For example, we can require a step is signed by a key with a specific
CN
attribute.- Witness will require all attestations to succeed
- Witness will evaluate the rego policy against the JSON object in the corresponding attestor
## policy.json
{
"expires": "2023-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}}"
}
}
}
id=`sha256sum testpub.pem | awk '{print $1}'` && sed -i "s/{{PUBLIC_KEY_ID}}/$id/g" policy.json
pubb64=`cat testpub.pem | base64 -w 0` && sed -i "s/{{B64_PUBLIC_KEY}}/$pubb64/g" policy.json
Keep this key safe, its owner will control the policy gates.
witness sign -f policy.json --signer-file-key-path testkey.pem --outfile policy-signed.json
This process works across air-gap as long as you have the signed policy file, correct binary, and public key or certificate authority corresponding to the private key that signed the policy.
witness verify -f testapp -a test-att.json -p policy-signed.json -k testpub.pem
witness verify
will return a non-zero
exit and reason in the case of failure, but hopefully you should have gotten sweet sweet silence with a 0
exit status, victory! If not, try again and if that fails please file an issue!
If you enjoyed this intro to Witness, you might benefit from taking things a step further by learning about Witness Policies.