diff --git a/README.md b/README.md deleted file mode 100644 index ce16ecf5..00000000 --- a/README.md +++ /dev/null @@ -1,212 +0,0 @@ -# Witness [![Go Reference](https://pkg.go.dev/badge/github.com/in-toto/witness.svg)](https://pkg.go.dev/github.com/in-toto/witness) [![Go Report Card](https://goreportcard.com/badge/github.com/in-toto/witness)](https://goreportcard.com/report/github.com/in-toto/witness) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8164/badge)](https://www.bestpractices.dev/projects/8164) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/in-toto/witness/badge)](https://securityscorecards.dev/viewer/?uri=github.com/in-toto/witness) - -
- -**[DOCS](https://witness.dev) • -[CONTRIBUTING](./CONTRIBUTORS.md) • -[LICENSE](./LICENSE)** - **Get Started Now 👇**
-`bash <(curl -s https://raw.githubusercontent.com/in-toto/witness/main/install-witness.sh)`

-
- -Witness project logo - -### What does Witness do?
-✏️ **Attests** - Witness is a dynamic CLI tool that integrates into pipelines and infrastructure to create an - audit trail for your software's entire journey through the software development lifecycle (SDLC) using the in-toto specification.
- -**🧐 Verifies** - Witness also features its own policy engine with embedded support for OPA Rego, so you can - ensure that your software was handled safely from source to deployment. - -### What can you do with Witness? -- Verify how your software was produced and what tools were used -- Ensure that each step of the supply chain was completed by authorized users and machines -- Detect potential tampering or malicious activity -- Distribute attestations and policy across air gaps - -### Key Features - - Integrations with GitLab, GitHub, AWS, and GCP. - - Designed to run in both containerized and non-containerized environments **without** elevated privileges. - - Implements the in-toto specification (including ITE-5, ITE-6 and ITE-7) - - An embedded OPA Rego policy engine for policy enforcement - - Keyless signing with Sigstore and SPIFFE/SPIRE - - Integration with RFC3161 compatible timestamp authorities - - Process tracing and process tampering prevention (Experimental) -- Attestation storage with [Archivista](https://github.com/in-toto/archivista) - -### Demo -![Demo][demo] - -## Quick Start - -### Installation -To install Witness, all you will need is the Witness binary. You can download this from the [releases] -(https://github.com/testifysec/witness/releases) page or use the install script to download the -latest release: -``` -bash <(curl -s https://raw.githubusercontent.com/in-toto/witness/main/install-witness.sh) -``` - -### Tutorial -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: -* [Go](https://go.dev/doc/install) (1.19 or later is recommended) -* [openssl](https://www.openssl.org/) -* [jq](https://jqlang.github.io/jq/) -* [base64](https://www.gnu.org/software/coreutils/manual/html_node/base64-invocation.html) (which is part of GNU coreutils) - -1. Create a Keypair - ->💡 Tip: Witness supports keyless signing with [SPIRE](https://spiffe.io/)! - -``` -openssl genpkey -algorithm ed25519 -outform PEM -out testkey.pem -openssl pkey -in testkey.pem -pubout > testpub.pem -``` - -2. Create a Witness configuration ->💡 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 file -- `witness 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 -``` - -3. Record attestations for a build step ->💡 Tip: You can upload the recorded attestations to an [Archivista](https://github.com/in-toto/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. -- 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 -- go build -o=testapp . -``` - -4. View the attestation data in the signed DSSE Envelope - -- 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 -``` - -5. Create a Policy File - -Look [here](docs/policy.md) 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}}" - } - } -} -``` - -6. Replace the variables in the policy - -``` -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 -``` - -7. Sign The Policy File - -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 -``` - -8. Verify the Binary Meets Policy Requirements - -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` will return a `non-zero` exit and reason in the case of failure. Success will be silent with a `0` exit status for -policies that require multiple steps, multiple attestations are required. - -``` -witness verify -f testapp -a test-att.json -p policy-signed.json -k testpub.pem -``` - -### Check out our other tutorials -##### [Verify an Artifact Policy](https://github.com/testifysec/witness-examples/blob/main/keypair/README.md) -##### [Using Fulcio as a Key Provider](https://github.com/testifysec/witness-examples/blob/main/keyless-fulcio/README.md) - -## How does Witness work? -### Signing -Witness is able to observe your software development life-cycle (SDLC) by wrapping around commands executed within them. By passing any command to Witness as an argument, the tool is able to understand what was executed but also on what infrastructure, by what user or service account and more. The information that Witness gathers while the command is running is down to which [Attestors](docs/attestor.md) are used. Attestors are implementations of an interface that find and assert facts about the system Witness is running on (e.g., [AWS Attestor](docs/attestors/aws-iid.md)). Finally, Witness can compile this information into an [in-toto attestation](https://github.com/in-toto/attestation), place it in a [DSSE Envelope](https://github.com/secure-systems-lab/dsse) and sign that envelope with the key that was supplied by the user. - -### Storing -For storage, the Witness project can upload signed attestations to an [Archivista](https://github.com/in-toto/archivista) server, a graph and storage service for in-toto attestations. This enables the discovery and retrieval of attestations for verification of software artifacts. - -### Verifying -Witness allows users to verify the attestations that they generate by providing the `witness verify` command. To achieve this, Witness uses a [policy file](./docs/policy.md) defined by the user to check for presence of the expected attestations and that they were signed by the appropriate functionaries (Public keys or roots of trust that are trusted to sign certain types of attestation). To verify the attestation body itself, Witness supports defining [OPA Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) policies inside the policy file. This allows users to ensure the facts asserted by the Attestors are reported expected. - -# Media -Check out some of the content out in the wild that gives more detail on how the project can be used. - -##### [Blog/Video - Generating and Verifying Attestations With Witness](https://www.testifysec.com/blog/attestations-with-witness/) -##### [Blog - What is a supply chain attestation, and why do I need it?](https://www.testifysec.com/blog/what-is-a-supply-chain-attestation/) -##### [Talk - Securing the Software Supply Chain with the in-toto & SPIRE projects](https://www.youtube.com/watch?v=4lFbdkB62QI) -##### [Talk - Securing the Software Supply Chain with SBOM and Attestation](https://www.youtube.com/watch?v=wX6aTZfpJv0) - -# Get Involved with the Community! -Join the [CNCF Slack](https://slack.cncf.io/) and join the `#in-toto-witness` channel. You might also be interested in joining the `#in-toto` channel for more general in-toto discussion, as well as -the `#in-toto-archivista` channel for discussion regarding the [Archivista](https://github.com/in-toto/archivista) project. - -[demo]: docs/assets/demo.gif "Demo" - -# Background -This project was created by [TestifySec](https://www.testifysec.com/) before being donated to the in-toto project. The project is maintained by the TestifySec Open Source team and a community of contributors. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..df1f8c08 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,73 @@ +# Witness [![Go Reference](https://pkg.go.dev/badge/github.com/in-toto/witness.svg)](https://pkg.go.dev/github.com/in-toto/witness) [![Go Report Card](https://goreportcard.com/badge/github.com/in-toto/witness)](https://goreportcard.com/report/github.com/in-toto/witness) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8164/badge)](https://www.bestpractices.dev/projects/8164) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/in-toto/witness/badge)](https://securityscorecards.dev/viewer/?uri=github.com/in-toto/witness) + +
+ +**[DOCS](https://witness.dev) • +[CONTRIBUTING](./CONTRIBUTORS.md) • +[LICENSE](./LICENSE)** + **Get Started Now 👇**
+`bash <(curl -s https://raw.githubusercontent.com/in-toto/witness/main/install-witness.sh)`

+
+ +Witness project logo + +### What does Witness do?
+✏️ **Attests** - Witness is a dynamic CLI tool that integrates into pipelines and infrastructure to create an + audit trail for your software's entire journey through the software development lifecycle (SDLC) using the in-toto specification.
+ +**🧐 Verifies** - Witness also features its own policy engine with embedded support for OPA Rego, so you can + ensure that your software was handled safely from source to deployment. + +### What can you do with Witness? +- Verify how your software was produced and what tools were used +- Ensure that each step of the supply chain was completed by authorized users and machines +- Detect potential tampering or malicious activity +- Distribute attestations and policy across air gaps + +### Key Features + - Integrations with GitLab, GitHub, AWS, and GCP. + - Designed to run in both containerized and non-containerized environments **without** elevated privileges. + - Implements the in-toto specification (including ITE-5, ITE-6 and ITE-7) + - An embedded OPA Rego policy engine for policy enforcement + - Keyless signing with Sigstore and SPIFFE/SPIRE + - Integration with RFC3161 compatible timestamp authorities + - Process tracing and process tampering prevention (Experimental) +- Attestation storage with [Archivista](https://github.com/in-toto/archivista) + +### Demo +![Demo][demo] + +## Quick Start + +### Installation +To install Witness, all you will need is the Witness binary. You can download this from the [releases] +(https://github.com/testifysec/witness/releases) page or use the install script to download the +latest release: +``` +bash <(curl -s https://raw.githubusercontent.com/in-toto/witness/main/install-witness.sh) +``` + +### Tutorials +Check out our Tutorials: + +- [Getting Started](tutorials/getting-started.md) +- [Verify an Artifact Policy](tutorials/artifact-policy.md) +- [Using Fulcio as a Key Provider](tutorials/artifact-policy.md) + +## Media +Check out some of the content out in the wild that gives more detail on how the project can be used. + +##### [Blog/Video - Generating and Verifying Attestations With Witness](https://www.testifysec.com/blog/attestations-with-witness/) +##### [Blog - What is a supply chain attestation, and why do I need it?](https://www.testifysec.com/blog/what-is-a-supply-chain-attestation/) +##### [Talk - Securing the Software Supply Chain with the in-toto & SPIRE projects](https://www.youtube.com/watch?v=4lFbdkB62QI) +##### [Talk - Securing the Software Supply Chain with SBOM and Attestation](https://www.youtube.com/watch?v=wX6aTZfpJv0) + +## Get Involved with the Community! +Join the [CNCF Slack](https://slack.cncf.io/) and join the `#in-toto-witness` channel. You might also be interested in joining the `#in-toto` channel for more general in-toto discussion, as well as +the `#in-toto-archivista` channel for discussion regarding the [Archivista](https://github.com/in-toto/archivista) project. + +[demo]: docs/assets/demo.gif "Demo" + +## Background +This project was created by [TestifySec](https://www.testifysec.com/) before being donated to the in-toto project. The project is maintained by the TestifySec Open Source team and a community of contributors. diff --git a/docs/about/how-witness-works.md b/docs/about/how-witness-works.md new file mode 100644 index 00000000..03b3e77f --- /dev/null +++ b/docs/about/how-witness-works.md @@ -0,0 +1,11 @@ +# How Witness Works + +### Signing +Witness is able to observe your software development life-cycle (SDLC) by wrapping around commands executed within them. By passing any command to Witness as an argument, the tool is able to understand what was executed but also on what infrastructure, by what user or service account and more. The information that Witness gathers while the command is running is down to which [Attestors](docs/attestor.md) are used. Attestors are implementations of an interface that find and assert facts about the system Witness is running on (e.g., [AWS Attestor](docs/attestors/aws-iid.md)). Finally, Witness can compile this information into an [in-toto attestation](https://github.com/in-toto/attestation), place it in a [DSSE Envelope](https://github.com/secure-systems-lab/dsse) and sign that envelope with the key that was supplied by the user. + +### Storing +For storage, the Witness project can upload signed attestations to an [Archivista](https://github.com/in-toto/archivista) server, a graph and storage service for in-toto attestations. This enables the discovery and retrieval of attestations for verification of software artifacts. + +### Verifying +Witness allows users to verify the attestations that they generate by providing the `witness verify` command. To achieve this, Witness uses a [policy file](./docs/policy.md) defined by the user to check for presence of the expected attestations and that they were signed by the appropriate functionaries (Public keys or roots of trust that are trusted to sign certain types of attestation). To verify the attestation body itself, Witness supports defining [OPA Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) policies inside the policy file. This allows users to ensure the facts asserted by the Attestors are reported expected. + diff --git a/docs/tutorials/artifact-policy.md b/docs/tutorials/artifact-policy.md new file mode 100644 index 00000000..4886350d --- /dev/null +++ b/docs/tutorials/artifact-policy.md @@ -0,0 +1,302 @@ +# Verifying an Artifact with a Witness Policy + +## Intro +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: + +- [jq](https://jqlang.github.io/jq/) +- [yq](https://kislyuk.github.io/yq/) +- [openssl](https://www.openssl.org/) +- [wget](https://www.gnu.org/software/wget/) +- [base64](https://www.gnu.org/software/coreutils/manual/html_node/base64-invocation.html) (which is part of GNU coreutils) + +You will also of course need to have witness installed, which can be achieved by following the [Quick Start](../README.md#quick-start). + +## Let's Go! + +### Generating a Key Pair +The first step is to generate a key pair that will be used to sign the attestations. This can be done with the following `openssl` command: + +`openssl genrsa -out buildkey.pem 2048` + +Next, we will extract the public key from the key pair: + +`openssl rsa -in buildkey.pem -outform PEM -pubout -out buildpublic.pem` + +### Generating the Attestations +Now that we have created the key pairs, we can use them creating and signing an attestation by running the following command: + +*Important Note: Witness generates the product attestation based on new files in the working directory. Make sure `./hello.txt` does NOT exist when running this command.* + +``` +witness run -s build -a environment -k buildkey.pem -o build-attestation.json -- \ +bash -c "echo 'hello' > hello.txt" +``` + +In this command you will notice a few flags: + +- `-s build` specifies the step name. This is helpful for identifying which step of the supply chain these particular attestations are from. +- `-a environment` specifies the attestor to use. There are a [wide variety of attestors](../attestors) available which can called in a list using this flag. +- `-k buildkey.pem` specifies the private key we generated to use for signing the attestations. +- `-o build-attestation.json` specifies the output file for the attestations to be written to in `json` format. + +Upon running this command (and it exiting successfully), you should see a file named `build-attestation.json` in your current working directory. This file contains the attestations that were generated by the command. + +### Viewing the Attestation +If you view the `build-attestation.json` file, you might be disappointed to find a load of jibberish. Do not fear, it is meant to be this way! The attestation is base64 encoded and stored in a [DSSE Envelope](https://github.com/secure-systems-lab/dsse), which +is a simple, foolproof way of signing arbitrary data. + +To view the contents of the attestation, you can use the following command: + +`cat build-attestation.json | jq -r .payload | base64 -d | jq .` + +This will print the contents of the attestation in a human-readable format. The output should look something like: + +``` +{ + "_type": "https://in-toto.io/Statement/v0.1", + "subject": [ + { + "name": "https://witness.dev/attestations/product/v0.1/file:hello.txt", + "digest": { + "gitoid:sha1": "gitoid:blob:sha1:ce013625030ba8dba906f756967f9e9ca394464a", + "gitoid:sha256": "gitoid:blob:sha256:473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813", + "sha256": "5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03" + } + } + ], + "predicateType": "https://witness.testifysec.com/attestation-collection/v0.1", + "predicate": { + "name": "build", + "attestations": [ + { + "type": "https://witness.dev/attestations/environment/v0.1", + "attestation": { + "os": "darwin", +... +``` + +This is all well and good, but attestations hardly make for good bedtime reading (😴), so let's see if we can define a policy so we can automate the verification process . + +### Specifying the Rego Constraints +One of the key features of Witness is its ability to enforce policies using the [Open Policy Agent (OPA) Rego language](https://www.openpolicyagent.org/docs/latest/policy-language/). This allows us to specify rules that must be followed when generating attestations, and ensures that the artifacts produced by the pipeline meet the requirements specified in the policy. + +To create the Rego policy, we first need to define the rules that we want to enforce. For example, if we want to ensure that the `./hello.txt` file is created with the correct contents we could use the following Rego policy: + +``` +cat <> cmd.rego +package commandrun + +deny[msg] { + input.exitcode != 0 + msg := "exitcode not 0" +} + +deny[msg] { + input.cmd[2] != "echo 'hello' > hello.txt" + msg := "cmd not correct" +} +EOF +``` + +You can save this to a file locally by copying the above code, pasting it into your terminal and pressing `enter`. This will create a file named `cmd.rego` in your current working directory. + +#### But what does it mean? + +This policy specifies two rules: + +1. The policy must 'deny' if the exit code of the command is not 0: +``` +deny[msg] { + input.exitcode != 0 + msg := "exitcode not 0" +} +``` + +2. The policy must 'deny' if the command for creating `./hello.txt` is not what we expect: +``` + +deny[msg] { + input.cmd[2] != "echo 'hello' > hello.txt" + msg := "cmd not correct" +} +``` + +What's brilliant about Rego is that these are just examples. You can define a Rego policy that inspects any attribute within the attestation. + +For example, we could create a policy that checks the user that ran the command: +``` +package environment +deny[msg] { + + input.username != "witty" + msg := "username not correct" +} +``` + +Or the current working directory: +``` +package environment +deny[msg] { + + input.variables.PWD != "/home/witty/secret-lab" + msg := "working directory not correct" +} +``` +This allows you to create highly customizable and granular policies to ensure the integrity and security of your build process. + +### Creating the Witness Policy +Next, we need to place our Rego policy into a Witness Policy. While Rego is going to help us verify the attestation contents, the Witness Policy is going to take care of verifying the presence of each expected attestation, as well as + the signature attached to it. + +Here is an example policy template: +``` +cat <> policy-template.yaml +expires: "2035-12-17T23:57:40-05:00" +steps: + build: + name: build + attestations: + - type: https://witness.dev/attestations/material/v0.1 + - type: https://witness.dev/attestations/product/v0.1 + - type: https://witness.dev/attestations/command-run/v0.1 + regoPolicies: + - name: "exitcode" + module: "{{CMD_MODULE}}" + functionaries: + - type: publickey + publickeyid: "{{KEYID}}" +publickeys: + "{{KEYID}}": + keyid: "{{KEYID}}" + key: +EOF +``` + +You can save this to a file locally by copying the above code, pasting it into your terminal and pressing `enter`. This will create a file named `policy-template.yaml` in your current working directory. + +#### But what does it mean? +In this Witness Policy, we have defined a single step (you can define more than one) that we expect the supply chain of any artifact verified by it should have gone through: +``` +steps: + build: + name: build +``` + +For this step, we expect to find an [Attestation Collection](../attestor.md) that contains three types of attestation: material, product and command-run: +``` + attestations: + - type: https://witness.dev/attestations/material/v0.1 + - type: https://witness.dev/attestations/product/v0.1 + - type: https://witness.dev/attestations/command-run/v0.1 +``` + +For the `command-run` attestation, we will also be using the Rego policy we defined earlier: + +``` + - type: https://witness.dev/attestations/command-run/v0.1 + regoPolicies: + - name: "exitcode" + module: "{{CMD_MODULE}}" +``` + +Finally, we will be using our public key ID (the sha256sum of our public key) to verify the signature of the attestations. This public key is our digital identity, and in this case we are the functionary and we are expected to have signed the attestations for the build step: +``` + functionaries: + - type: publickey + publickeyid: "{{KEYID}}" +``` + +The key IDs are mapped to the base64 encodings of the public keys in the `publickeys` section: +``` + publickeys: + "{{KEYID}}": + keyid: "{{KEYID}}" + key: +``` + +It is important to note that the policy template can be used to define multiple steps in an artifacts supply chain, and each step can have its own set of attestations and rules. This allows us to create complex and granular policies that ensure the integrity of the supply chain from start to finish. + +### Templating the Policy +Before we can use the policy, we need to populate it with the base64 encoded public key, the key ID, and the Rego policy (which also needs to be base64 encoded): + +*Note: This script uses the `shasum` tool on MacOS and `sha256sum` on Linux. If you are using a different operating system, you may need to modify the script to use the appropriate tool. Contributions to make this script more portable are welcome!* +```bash +cat << 'EOF' > template-policy.sh + +# Requires yq v4.2.0 +cmd_b64="$(openssl base64 -A <"cmd.rego")" +pubkey_b64="$(openssl base64 -A <"buildpublic.pem")" +cp policy-template.yaml policy.tmp.yaml + +# Calculate SHA256 hash (macOS and Linux compatible) +if [[ "$(uname)" == "Darwin" ]]; then + + keyid=$(shasum -a 256 buildpublic.pem | awk '{print $1}') + sed -i '' "s/{{KEYID}}/$keyid/g" policy.tmp.yaml + sed -i '' "s/{{CMD_MODULE}}/$cmd_b64/g" policy.tmp.yaml + + +else + keyid=$(sha256sum buildpublic.pem | awk '{print $1}') + sed -i "s/{{KEYID}}/$keyid/g" policy.tmp.yaml + sed -i "s/{{CMD_MODULE}}/$cmd_b64/g" policy.tmp.yaml + + +fi +yq eval ".publickeys.\"${keyid}\".key = \"${pubkey_b64}\"" --inplace policy.tmp.yaml + +# Use `-o=json` instead of deprecated `--tojson` +yq eval -o=json policy.tmp.yaml > policy.json + +# Clean up the temporary file +rm policy.tmp.yaml +EOF +chmod +x template-policy.sh +``` + +Once again, you can save this to a file locally by copying the above code, pasting it into your terminal and pressing `enter`. This will create a file named `template-policy.sh` in your current working directory, but also make it executable (with `chmod +x`). + +Now you can go ahead and run the script, which will output a final `policy.json` file. + +### Signing the Witness Policy + +Signing the policy is an important step in the attestation process, as it ensures the authenticity and integrity of the policy. This is essential for ensuring the security of the build process and preventing tampering of build materials and artifacts. + +In order to sign the policy, we need to use a key pair that is trusted by the verification process. Once again, we can generate this pair with `openssl`: +``` +openssl genrsa -out policykey.pem 2048 +openssl rsa -in policykey.pem -outform PEM -pubout -out policypublic.pem +``` + +Once the key pair has been generated, we can use the private key to sign the policy using the Witness sign command as follows: +``` +witness sign -k policykey.pem -f policy.json -o policy.signed.json +``` + +The above command only has three flags: + +- `-k policykey.pem` specifies the private key that will be used to sign the policy. +- `-f policy.json` specifies the policy file that will be signed. +- `-o policy.signed.json` specifies the output file for the signed policy. + +The signed policy file can now be used to verify the attestations we generated earlier. This ensures that the policy has not been tampered with and that it can be trusted during the verification process. + +Okay, I hear ya, I hear ya, let's verify some attestations already! + +### Verifying the Attestations +Once the policy has been signed and the attestations have been generated, we can use the witness verify command to verify that the attestations meet the requirements specified in the policy. This is done by running the witness verify command with the following arguments: + +``` +witness verify -k policypublic.pem -p policy.signed.json -a build-attestation.json -f hello.txt +``` + +- `-k policypublic.pem` specifies the public key that was used to sign the policy. +- `-p policy.signed.json` specifies the signed policy file. +- `-a build-attestation.json` specifies the attestation file that we generated earlier. +- `-f hello.txt` specifies the artifact that was produced by the pipeline. + + +If the attestations meet the requirements specified in the policy, the witness verify command will output a message indicating that the verification succeeded along with references to the evidence. If the attestations do not meet the requirements, the witness verify command will output an error message indicating which requirement was not met. + +One of the key benefits of using Witness is that it is not only a standalone tool, but also a library that can be embedded into other applications such as admission controllers and runtime visibility tooling. Be sure to check out go-witness [here](https://github.com/in-toto/go-witness). diff --git a/docs/tutorials/getting-started.md b/docs/tutorials/getting-started.md new file mode 100644 index 00000000..1f3d222b --- /dev/null +++ b/docs/tutorials/getting-started.md @@ -0,0 +1,136 @@ +# Getting Started + +## Intro +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: + +- [Go](https://go.dev/doc/install) (1.19 or later is recommended) +- [openssl](https://www.openssl.org/) +- [jq](https://jqlang.github.io/jq/) +- [base64](https://www.gnu.org/software/coreutils/manual/html_node/base64-invocation.html) (which is part of GNU coreutils) + +You will also of course need to have witness installed, which can be achieved by following the [Quick Start](../README.md#quick-start). + +## 1. Create a Keypair + +>💡 Tip: Witness supports keyless signing with [SPIRE](https://spiffe.io/)! + +``` +openssl genpkey -algorithm ed25519 -outform PEM -out testkey.pem +openssl pkey -in testkey.pem -pubout > testpub.pem +``` + +## 2. Create a Witness Configuration +>💡 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 file +- `witness 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 +``` + +## 3. Record attestations for a build step +>💡 Tip: You can upload the recorded attestations to an [Archivista](https://github.com/in-toto/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. +- 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 -- go build -o=testapp . +``` + +## 4. View the attestation data in the signed DSSE Envelope + +- 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 +``` + +## 5. Create a Policy File + +Look [here](docs/policy.md) 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}}" + } + } +} +``` + +## 6. Replace the variables in the policy + +``` +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 +``` + +## 7. Sign The Policy File + +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 +``` + +## 8. Verify the Binary Meets Policy Requirements + +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` will return a `non-zero` exit and reason in the case of failure. Success will be silent with a `0` exit status for +policies that require multiple steps, multiple attestations are required. + +``` +witness verify -f testapp -a test-att.json -p policy-signed.json -k testpub.pem +``` diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..0f3d9318 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,13 @@ +site_name: Witness +theme: + name: material + logo: assets/logo.png +index_page: "README.md" +nav: + - Home: "README.md" + - About: + - "How Witness Works": "about/how-witness-works.md" + - Tutorials: + - "Getting Started": "tutorials/getting-started.md" + - "Verifying an Artifact with a Witness Policy": "tutorials/artifact-policy.md" + - "Using a Fulcio Key Provider": "tutorials/fulcio-key-provider.md"