Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.
/ policy-tool Public archive

utility for creating and validating witness policy

Notifications You must be signed in to change notification settings

testifysec/policy-tool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Witness Policy Tool

The Witness Policy Tool is a command-line utility designed to create, and validate Witness policies. These policies play a crucial role in maintaining the integrity and security of your software development lifecycle (SDLC) by requiring the presence of specific attestations and values throughout every stage. To learn more about Witness, visit its GitHub repository , and for further information on policies, consult the Witness policy documentation .

This tool is experimental. When stable this functionality will be incorporated into Witness

Download

You can download the latest linux x64 release of policy-tool from GitHub.

If you need support for other arch/platforms please compile from source

Usage

The tool is run from the command line and supports various commands and flags to create, and check, Witness policies. The check command allows you to validate an unsigned policy file, while the create command helps you create a new policy file with specific attestations, steps, and constraints.

To generate a Witness policy from existing attestations, you can instrument your pipeline with Witness and retrieve the gitoids for the attestations generated at each step. You can then pass these gitoids, along with the necessary CA certificates, to the policy tool to generate your policy.

Additionally, the tool includes a Rego Module Generator that helps you create Rego modules for validating attestation data based on key-value pairs provided in a YAML configuration file.

Generating Policy From Existing Attestations

The policy tool supports generating attestations from attestation collections. The user should instrument their pipeline with Witness and take note of all of the gitoids for the attestations generated at each step. If the user is not using Archivista they should manually download all of the envelopes to pass into the tool

ex Witness log message level=info msg="Stored in [Archivista](http:https://github.com/testifysec/archivista) as e03b606faa2522f5262fcaf8c014f85972f22b2ce669692d2d0706aee493cdd2\n"

The identifier is e03b606faa2522f5262fcaf8c014f85972f22b2ce669692d2d0706aee493cdd2

SAST=ff6c90ec2b0525df2d365115b84550a8d9df510a1a0bc1a01273363fda4a6e29
TEST=3366cec6c729723072b8cd8675514fe2b834abe9b5014c4bf262494242b30f8d
BUILD=e03b606faa2522f5262fcaf8c014f85972f22b2ce669692d2d0706aee493cdd2

You will need to pass in the CAs used for signing the attestations either as a URL or a file

CERT="./CA/ca.crt"
TSA_CERT="https://freetsa.org/files/cacert.pem"

Sticky values allow policy writers to specify certain key-value pairs in attestation documents that should be enforced in all subsequent evaluations. The idea behind sticky values is that they capture the properties of the input that should not change over time, and thus should be consistently enforced across all policy decisions.

We need to create a document specifying what are "sticky values are"

https:https://witness.dev/attestations/gitlab/v0.1:
  - jwt.claims.project_id
  - jwt.claims.iss
  - ciconfigpath
  - jwt.verifiedBy.jwksUrl

https:https://witness.dev/attestations/gcp-iit/v0.1:
  - jwt.claims.iss
  - jwt.claims.aud
  - jwt.claims.email
  - jwt.claims.sub
  - jwt.verifiedBy.jwksUrl  

  - project_id
  - project_number
  - cluster_name
  - cluster_uid
  - cluster_location
  - zone

https:https://witness.dev/attestations/command-run/v0.1:
  - cmd

Now we can run the policy tool to generate our Witness Policy

policy-tool create -x $SAST -y sticky.yaml -r $CERT -x $TEST -r $CERT -y sticky.yaml -x $BUILD -r $CERT -y sticky.yaml -t $TSA_CERT > policy.json

Now you can ensure the policy is valid, check does some basic checks on the policy to make sure the certs are not expired and it is formated correctly

policy-tool check -p policy.json

This policy is now ready for review, signing, and deployment.

Examples Using Command Line Provided Info

Simple example

create --step test -r /path/to/root.pem --attestations https://witness.dev/attestations/commandrun/v0.1

This command creates a policy file with a root certificate located at /path/to/root.pem and an acommandRun attestation. The policy file will contain a single step named test.

Complex example

policy-tool create \
                   ##Step1 \
                   -s step1 \
                   -r /path/to/root.pem \
                   -i /path/to/intermediate.pem \
                   -a https://witness.dev/attestations/aws/v0.1 \
                   -g /path/to/rego/file.rego \
                   -a https://witness.dev/attestations/commandrun/v0.1 \
                   -g /path/to/rego/file.rego \
                   ##Step2 \
                   -s step2 \
                   -i /path/to/intermediate.pem \
                   -a https://witness.dev/attestations/aws/v0.1 \
                   -a https://witness.dev/attestations/commandrun/v0.1 \
                   -g /path/to/rego/file.rego

This is an example command for using the policy-tool to create a complex Witness policy with multiple steps.

The command starts with policy-tool create, indicating that the create command should be used to generate a new policy. Then, it defines two steps using the -s flag: step1 and step2. For each step, it specifies the intermediate certificate using -i, and the attestations using -a. In step 1, two attestations are specified, along with the path to a Rego policy file (-g) for each attestation. Step 2 also has two attestations, but only one Rego policy file is used for both.

Each line in the command corresponds to a separate flag or parameter for the create command. The use of the backslash character () at the end of each line indicates that the command continues onto the next line for readability purposes.

The final policy file generated by this command would contain two steps, with the specified intermediate certificate, attestations, and associated Rego policy files for each step.

Adding custom Rego modules and Cert Constraints

policy-tool create -x $SAST_ATTESTATION_ID \
                   -a "https://witness.dev/attestations/material/v0.1" \
                   -g test.rego \
                   -y sticky.yaml \
                   -r $CERT \
                   [email protected] \
                   -x $TEST_ATTESTATION_ID \
                   -r $CERT \
                   -y sticky.yaml \
                   -x $BUILD_ATTESTATION_ID \
                   -r $CERT \
                   -y sticky.yaml \
                   -t $TSA_CERT > policy.json

This example demonstrates how to create a policy using attestations, custom Rego modules, and certificate constraints. The Rego modules are defined in the sticky.yaml file and the test.rego file. Note that you must specify which attestation the Rego module belongs to by using the -a flag preceding the module. Certificate constraints should be placed after the root CA flag -r.

Create Command

create - Creates a policy file.

Flags

  -u, --archivsita-url string             URL of the [Archivista](http:https://github.com/testifysec/archivista) instance to use for DSSE envelope retrieval (default "https://archivista.testifysec.io/download/")
  -a, --attestations string               Attestations to include in the policy for a step; should be used after a step flag
      --constraint-commonname string      Certificate common name constraint
      --constraint-dnsnames string        Certificate DNS names constraint (comma-separated)
      --constraint-emails string          Certificate emails constraint (comma-separated)
      --constraint-organizations string   Certificate organizations constraint (comma-separated)
      --constraint-uris string            Certificate URIs constraint (comma-separated)
  -d, --dsse string                       Path to a DSSE envelope file to associate with an functionary, should be used instread of a step flag
  -x, --dsse-[Archivista](http:https://github.com/testifysec/archivista) string            gitoid of the DSSE envelope in Archivista; should be used instead of a step flag
  -e, --expires duration                  Expiration duration for the policy (e.g., 24h, 7d) (default 24h0m0s)
  -h, --help                              help for create
  -i, --intermediate string               Path to the intermediate PEM file (optional); should be used after a step flag
  -o, --output string                     Output file to save the policy (default id stdout)
  -k, --public-key string                 Path to a public key file to associate with an attestation; should be used after a step flag
  -g, --rego string                       Path to a Rego policy file to associate with an attestation; should be used after an attestation flag
  -r, --root-ca string                    Path to the root CA PEM file; should be used after a step flag
  -s, --step string                       Step name to bind subsequent flags to (e.g., root CA, intermediate, attestations, Rego policy)
  -y, --sticky-keys string                Path to a file containing a list of sticky keys to use for the policy
  -t, --tsa-ca string                     Path to the TSA CA PEM file; should be used after a step flag

Notes

  • The tool requires that the --root-ca or --public-key and --attestations flags are used at least once.
  • Flags should be used after a step flag, which binds the flags to a specific step in the policy file.
  • The Rego policy file specified with the --rego flag is encoded as a base64 string in the policy file.

Check Command

check - Checks a policy file

Flags

  -p, --policy string   path to policy file

Rego Module Generator Details

This utility generates Rego modules for validating attestation data based on a set of key-value pairs provided in a YAML configuration file. Attestations are used to prove the integrity of data, and this generator will create Rego modules with OPA (Open Policy Agent) rules to validate the provided attestation JSON.

YAML Configuration

The input YAML file should list the attestation types as keys, with their corresponding required keys as an array of strings. Below is an example of the YAML configuration format:

https://witness.dev/attestations/gitlab/v0.1:
  - jwt.claims.project_id
  - jwt.claims.iss
  - ciconfigpath
  - jwt.verifiedBy.jwksUrl

https://witness.dev/attestations/gcp-iit/v0.1:
  - jwt.claims.iss
  - jwt.claims.aud
  - jwt.claims.email
  - jwt.claims.sub
  - jwt.verifiedBy.jwksUrl
  - project_id
  - project_number
  - cluster_name
  - cluster_uid
  - cluster_location
  - zone

https://witness.dev/attestations/command-run/v0.1:
  - cmd

Limitations

Types

The createRule function in the generator has some limitations in handling the types of keys in the attestation data. Currently, it supports two key value types:

  1. String: A single string value can be used as a key value. The generated Rego rule will check if the input key value is not equal to the provided string value.

  2. Slice of strings: A slice of strings can also be used as a key value. In this case, the generated Rego rule will check if the input key value is not equal to the entire slice of strings.

  3. Number: Any number type (int, int32, int64, float32, float64, etc.) can be used as a key value. The generated Rego rule will check if the input key value is not equal to the provided number value.

  4. Bool: A boolean value can be used as a key value. The generated Rego rule will check if the input key value is not equal to the provided boolean value.

Nested Structures

The generator does not support complex nested structures such as maps or nested slices. If your attestation data contains keys with nested structures, you will need to extend the createRule function to handle these cases and generate appropriate Rego rules.

Complex Validation Logic

The generated Rego rules only perform basic validation, such as checking for value inequality. If your use case requires more complex validation logic, such as value ranges, regular expressions, or custom predicates, you may need to manually create rego policies and add them to the policy.