diff --git a/cmd/witness/options/key.go b/cmd/witness/options/key.go index 96e7a896..323c0050 100644 --- a/cmd/witness/options/key.go +++ b/cmd/witness/options/key.go @@ -29,7 +29,7 @@ type KeyOptions struct { func (ko *KeyOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVarP(&ko.KeyPath, "key", "k", "", "Path to the signing key") cmd.Flags().StringVar(&ko.CertPath, "certificate", "", "Path to the signing key's certificate") - cmd.Flags().StringSliceVarP(&ko.IntermediatePaths, "intermediates", "i", []string{}, "Intermediates that link trust back to a root in the policy") + cmd.Flags().StringSliceVarP(&ko.IntermediatePaths, "intermediates", "i", []string{}, "Intermediates that link trust back to a root of trust in the policy") cmd.Flags().StringVar(&ko.SpiffePath, "spiffe-socket", "", "Path to the SPIFFE Workload API socket") cmd.Flags().StringVar(&ko.FulcioURL, "fulcio", "", "Fulcio address to sign with") cmd.Flags().StringVar(&ko.OIDCIssuer, "fulcio-oidc-issuer", "", "OIDC issuer to use for authentication") diff --git a/cmd/witness/options/run.go b/cmd/witness/options/run.go index 778f2edf..7f41e285 100644 --- a/cmd/witness/options/run.go +++ b/cmd/witness/options/run.go @@ -28,10 +28,10 @@ type RunOptions struct { func (ro *RunOptions) AddFlags(cmd *cobra.Command) { ro.KeyOptions.AddFlags(cmd) - cmd.Flags().StringVarP(&ro.WorkingDir, "workingdir", "d", "", "Directory that commands will be run from") + cmd.Flags().StringVarP(&ro.WorkingDir, "workingdir", "d", "", "Directory from which commands will run") cmd.Flags().StringSliceVarP(&ro.Attestations, "attestations", "a", []string{"environment", "git"}, "Attestations to record") - cmd.Flags().StringVarP(&ro.OutFilePath, "outfile", "o", "", "File to write signed data. Defaults to stdout") + cmd.Flags().StringVarP(&ro.OutFilePath, "outfile", "o", "", "File to which to write signed data. Defaults to stdout") cmd.Flags().StringVarP(&ro.StepName, "step", "s", "", "Name of the step being run") cmd.Flags().StringVarP(&ro.RekorServer, "rekor-server", "r", "", "Rekor server to store attestations") - cmd.Flags().BoolVar(&ro.Tracing, "trace", false, "enable tracing for the command") + cmd.Flags().BoolVar(&ro.Tracing, "trace", false, "Enable tracing for the command") } diff --git a/cmd/witness/options/verify.go b/cmd/witness/options/verify.go index c4d4304d..21e91629 100644 --- a/cmd/witness/options/verify.go +++ b/cmd/witness/options/verify.go @@ -31,6 +31,6 @@ func (vo *VerifyOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringSliceVarP(&vo.AttestationFilePaths, "attestations", "a", []string{}, "Attestation files to test against the policy") cmd.Flags().StringVarP(&vo.PolicyFilePath, "policy", "p", "", "Path to the policy to verify") cmd.Flags().StringVarP(&vo.ArtifactFilePath, "artifactfile", "f", "", "Path to the artifact to verify") - cmd.Flags().StringVarP(&vo.RekorServer, "rekor-server", "r", "", "Rekor server to fetch attestations from") + cmd.Flags().StringVarP(&vo.RekorServer, "rekor-server", "r", "", "Rekor server from which to fetch attestations") cmd.Flags().StringSliceVarP(&vo.CAPaths, "policy-ca", "", []string{}, "Paths to CA certificates to use for verifying the policy") } diff --git a/docs/attestors/aws-iid.md b/docs/attestors/aws-iid.md index c3c9e8c7..f3cc447f 100644 --- a/docs/attestors/aws-iid.md +++ b/docs/attestors/aws-iid.md @@ -1,16 +1,16 @@ # AWS Instance Identity Attestor -The AWS Instance Identity Attestor communicates with the AWS Instance Metadata to collect -information about the instance Witness is being executed on. The documents signature is +The AWS (Amazon Web Services) Instance Identity Attestor communicates with the AWS Instance Metadata to collect +information about the AWS instance Witness on which executing. The document signature is verified with the AWS RSA public certificate available [here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/verify-signature.html). -This currently does not work for the Hong Kong, Bahrain, Cape Town, Milan, China, or +This verification method currently does not work for the Hong Kong, Bahrain, Cape Town, Milan, China, or GovCloud regions. ## Subjects | Subject | Description | | ------- | ----------- | -| `instanceid` | The ID of the instance Witness was executed on | +| `instanceid` | The ID of the AWS instance where Witness was executed | | `accountid` | ID of the account that owns the AWS instance | -| `imageid` | ID of the AMI the instance was running at time of execution | -| `privateip` | IP of the instance at time of execution | +| `imageid` | ID of the AMI ([Amazon Machine Image](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)) the instance was running at time of execution | +| `privateip` | IP address of the instance at time of execution | diff --git a/docs/attestors/commandrun.md b/docs/attestors/commandrun.md index bff2a3e9..57547417 100644 --- a/docs/attestors/commandrun.md +++ b/docs/attestors/commandrun.md @@ -1,7 +1,8 @@ # Command Attestor -The command attestor collects information about a command that witness executes and observes. -The command's arguments, exit code, stdout, and stderr will be collected and added to the attestation. +The Command Attestor collects information about a command that TestifySec Witness executes and observes. +The command arguments, exit code, stdout, and stderr will be collected and added to the attestation. + Witness can optionally trace the command which will record all subprocesses started by the parent process -as well as all files opened by all processes. Please note that tracing is currently only supported on -Linux operating systems and is considered experimental for now. +as well as all files opened by all processes. Please note that tracing is currently supported only on +Linux operating systems and is considered experimental. diff --git a/docs/attestors/environment.md b/docs/attestors/environment.md index a787bbcb..1743071b 100644 --- a/docs/attestors/environment.md +++ b/docs/attestors/environment.md @@ -1,5 +1,5 @@ -# Environment +# Environment Attestor -The environment attestor records the OS, hostname, username, and all environment variables set -of witness at execution time. There is currently no way to block specific environment variables -so please take care to not leak secrets stored in environment variables. +The Environment Attestor records the OS, hostname, username, and all environment variables set +by TestifySec Witness at execution time. Currently there is no means to block specific environment variables +so take care to not leak secrets stored in environment variables. diff --git a/docs/attestors/gcp-iit.md b/docs/attestors/gcp-iit.md index 3fa211a7..51c217af 100644 --- a/docs/attestors/gcp-iit.md +++ b/docs/attestors/gcp-iit.md @@ -1,15 +1,15 @@ # GCP Instance Identity Attestor -The GCP Instance Identity Attestor communicates with the GCP metadata server to collect information -about the instance Witness is being exected on. The instance identity JWT's signature is validated -against Google's JWKS to ensure authenticity. +The [Google Cloud Platform](https://console.cloud.google.com/getting-started?supportedpurview=project) (GCP) Instance Identity Attestor communicates with the [GCP metadata server](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata) to collect information +about the instance on which TestifySec Witness is being exected. The instance identity JSON Web Token signature is validated +against Google's JWKS ([JSON Web Key Set](https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets)) to ensure authenticity. ## Subjects | Subject | Description | | ------- | ----------- | -| `instanceid` | ID of the Google Compute instance Witness was executed on | -| `instancename` | Name of the Compute instance Witness was executed on | -| `projectid` | The ID of the project that the instance belonged to | -| `projectnumber` | Number of the project that the instance belonged to | -| `clusteruid` | UID of the cluster if the execution enviornment was a GKE clister | +| `instanceid` | ID of the Google Compute instance on which Witness was executed | +| `instancename` | Name of the Compute instance on which Witness was executed | +| `projectid` | The ID of the project to which the instance belonged | +| `projectnumber` | Number of the project to which the instance belonged | +| `clusteruid` | UID of the cluster if the execution environment was a [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine) (GKE) cluster | diff --git a/docs/attestors/git.md b/docs/attestors/git.md index 582e8bab..636e1bd4 100644 --- a/docs/attestors/git.md +++ b/docs/attestors/git.md @@ -1,9 +1,9 @@ # Git Attestor -The Git attestor records the current state of the objects in the git repository, including untracked objects. +The Git Attestor records the current state of the objects in the git repository, including untracked objects. Both staged and unstaged states are recorded. ## Subjects -The attestor returns the SHA1 git commit hash as a subject. +The attestor returns the SHA1 ([Secure Hash Algorithm 1](https://en.wikipedia.org/wiki/SHA-1)) git commit hash as a subject. diff --git a/docs/attestors/gitlab.md b/docs/attestors/gitlab.md index 5cfd7751..a183cc25 100644 --- a/docs/attestors/gitlab.md +++ b/docs/attestors/gitlab.md @@ -1,13 +1,13 @@ -# Gitlab Attestor +# GitLab Attestor -The Gitlab attestor records information about the Gitlab CI/CD job execution that -Witness was run in. Witness verifies the JWT provided in `CI_JOB_JWT` against the -instance's JWKS to ensure authenticity at execution time. +The [GitLab](https://about.gitlab.com/) Attestor records information about the GitLab CI/CD job execution in which +TestifySec Witness was run. Witness verifies the JWT ([JSON Web Token](https://en.wikipedia.org/wiki/JSON_Web_Token)) provided in `CI_JOB_JWT` against the +instance's JWKS ([JSON Web Key Set](https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets)) to ensure authenticity at execution time. ## Subjects | Subject | Description | | ------- | ----------- | -| `pipelineurl` | Url of the CI/CD pipeline that this job belonged to | -| `joburl` | Url of the CI/CD job that this attestor describes | -| `projecturl` | Url of the project that owns the CI/CD pipeline and job | +| `pipelineurl` | URL of the CI/CD pipeline to which this job belonged | +| `joburl` | URL of the CI/CD job that this attestor describes | +| `projecturl` | URL of the project that owns the CI/CD pipeline and job | diff --git a/docs/attestors/jwt.md b/docs/attestors/jwt.md index 4357cad3..992ae9f3 100644 --- a/docs/attestors/jwt.md +++ b/docs/attestors/jwt.md @@ -1,4 +1,4 @@ # JWT Attestor -The JWT attestor verifies a JWT against a JWKS and records information about the +The JWT ([JSON Web Token](https://en.wikipedia.org/wiki/JSON_Web_Token)) Attestor verifies a JWT against a JWKS ([JSON Web Key Set](https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets)) and records information about the claims of the JWT. The JWK that was used to verify the JWT is also recorded. diff --git a/docs/attestors/material.md b/docs/attestors/material.md index f1f355a4..bf165a27 100644 --- a/docs/attestors/material.md +++ b/docs/attestors/material.md @@ -1,5 +1,5 @@ # Material Attestor -The material attestor records the digests of all files in the working directory of Witness -at exection time, but before any command is run. This gives information about the state +The Material Attestor records the digests of all files in the working directory of TestifySec Witness +at exection time, but before any command is run. This recording provides information about the state of all files before any changes are made by a command. diff --git a/docs/attestors/maven.md b/docs/attestors/maven.md index 76795820..1fb48210 100644 --- a/docs/attestors/maven.md +++ b/docs/attestors/maven.md @@ -1,10 +1,10 @@ # Maven Attestor -The Maven attestor records project and dependency information from a provided pom.xml. +The [Maven](https://maven.apache.org/) Attestor records project and dependency information from a provided pom.xml ([Maven Project Object Model](https://maven.apache.org/guides/introduction/introduction-to-the-pom.html)). ## Subjects | Subject | Description | | ------- | ----------- | -| `project:group/artifact@version` | The group, artifact, and version of the project that the pom.xml belongs to | +| `project:group/artifact@version` | The group, artifact, and version of the project to which the pom.xml belongs | | `dependency:group/artifact@version` | The group, artifact, and verion of each dependency in the pom.xml | diff --git a/docs/attestors/oci.md b/docs/attestors/oci.md index c01b9ca4..51898cbf 100644 --- a/docs/attestors/oci.md +++ b/docs/attestors/oci.md @@ -1,7 +1,7 @@ # OCI Attestor -The OCI attestor records information about a provided OCI image stored on disk as a tarball. -Information about the image's tags, layers, and manifest are collected and reported in this +The OCI Attestor records information about a provided [Open Container Initiative](https://opencontainers.org/) (OCI) image stored on disk as a tarball. +Information about the image tags, layers, and manifest are collected and reported in this attestation. ## Subjects diff --git a/docs/attestors/product.md b/docs/attestors/product.md index 3a73e32c..e3fd59a5 100644 --- a/docs/attestors/product.md +++ b/docs/attestors/product.md @@ -1,7 +1,7 @@ # Product Attestor -The product attestor looks at any materials recorded before a command was run and records all -products of the command. Digests and mime tyeps of any changed or created files are recorded as products. +The Product Attestor examines materials recorded before a command was run and records all +products in the command. Digests and MIME types of any changed or created files are recorded as products. ## Subjects diff --git a/docs/config.md b/docs/config.md index 9615f8b8..80932553 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1,6 +1,6 @@ ## Witness Configuration -Witness looks for the configuration file `.witness.yaml` in the current directory. +TestifySec Witness looks for the configuration file `.witness.yaml` in the current directory. Any values in the configuration file will be overridden by the command line arguments. @@ -29,4 +29,4 @@ verify: attestations: stringSlice publickey: string policy: string -``` \ No newline at end of file +``` diff --git a/docs/policy.md b/docs/policy.md index 5701e608..263cfb95 100644 --- a/docs/policy.md +++ b/docs/policy.md @@ -1,44 +1,48 @@ # Policies -Witness policies allow users to make assertions and test attestation collections generated during `witness run`. -Examples of when a policy could be enforced include within a Kubernetes admission controller, at the end of a CI/CD -pipeline, prior to image promotion, or before deployment to an execution environment. +TestifySec Witness policies allow users to make assertions and test attestation collections generated during a `Witness run`. +Examples of when a policy could be enforced include -Policies enable the ability to ensure all expected attestations are within a collection and support embedded +- within a [Kubernetes admission controller](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/) +- at the end of a CI/CD pipeline +- prior to image promotion, or +- before deployment to an execution environment. + +Policies help you ensure that all expected attestations are within a collection and support embedded [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) policies to make determinations about the content -of each attestation. Attestation signatures cal be linked to trusted functionaries with embedded public keys or X509 +of each attestation. Attestation signatures can be linked to trusted functionaries with embedded public keys or [X.509](https://en.wikipedia.org/wiki/X.509) roots of trust. -With these powers combined Witness policies ultimately allow users to automatically make decisions about the -trustworthiness of an artifact. Details of who, how, when, and where an artifact was built are all able to be considered +Combining these powers, Witness policies ultimately allow users to make decisions automatically about the +trustworthiness of an artifact. Details of who, how, when, and where an artifact was built can all be considered when evaluating policies. ## Verification Process -`witness verify` will evaluate a set of attestation collections against a policy document. If the attestation -collections satisfy the policy witness will exit with an exit code of 0. Any other exit code indicates an error or +`Witness verify` will evaluate a set of attestation collections against a policy document. If the attestation +collections satisfy the policy, Witness will exit with an exit code of 0. Any other exit code indicates an error or policy failure. Evaluating a Witness policy involves a few different steps: -1. Verify signatures on collections against publickeys and roots within the policy. Any collections that fail signature +1. Verify signatures on collections against public keys and trust roots within the policy. Any collections that fail signature verification will not be used. 1. Verify the signer of each collection maps to a trusted functionary for the corresponding step in the policy. -1. Verify materials recorded in each collection is consistent with the artifacts (materials + products) of other +1. Verify that materials recorded in each collection are consistent with the artifacts (materials + products) of other collections as configured by the policy. 1. Verify all rego policies embedded in the policy evaluate successfully against collections. ## Schema -Policies are JSON documents that are signed and wrapped in a DSSE envelope. The DSSE payload type will be +Policies are JSON documents that are signed and wrapped in [DSSE envelopes](https://github.com/secure-systems-lab/dsse). The DSSE payload type will be `https://witness.testifysec.com/policy/v0.1`. ### `policy` Object | Key | Type | Description | | --- | ---- | ----------- | -| `expires` | string | ISO-8601 formatted time. This defines an expiration time for the policy. Evaluation of expired policies always fail. | -| `roots` | object | Trusted X509 root certificates. Attestations that are signed with a certificate that belong to this root will be trusted. Keys of the object are the root certificate's Key ID, values are a `root` object. | +| `expires` | string | [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) formatted time. This key defines an expiration time for the policy. Evaluation of expired policies always fails. | +| `roots` | object | Trusted [X.509 root certificates](https://en.wikipedia.org/wiki/X.509). Attestations that are signed with a certificate that belong to this root will be trusted. Keys of the object are the root certificate's Key ID, values are a `root` object. | | `publickeys` | object | Trusted public keys. Attestations that are signed with one of these keys will be trusted. Keys of the object are the public key's Key ID, values are a `publickey` object. | | `steps` | object | Expected steps that must appear to satisfy the policy. Each step requires an attestation collection with a matching name and the expected attestations. Keys of the object are the step's name, values are a `step` object. | @@ -46,14 +50,14 @@ Policies are JSON documents that are signed and wrapped in a DSSE envelope. The | Key | Type | Description | | --- | ---- | ----------- | -| `certificate` | string | Base64 encoded PEM block that describes a valid X509 root certificate. | -| `intermediates` | array of strings | Array of base64 encoded PEM blocks that describe valid X509 intermediate certificates belonging to `certificate` | +| `certificate` | string | [Base64](https://en.wikipedia.org/wiki/Base64) encoded [PEM](https://pkg.go.dev/encoding/pem) block that describes a valid X.509 root certificate. | +| `intermediates` | array of strings | Array of base64 encoded PEM blocks that describe valid X.509 intermediate certificates belonging to `certificate` | ### `publickey` Object | Key | Type | Description | | --- | ---- | ----------- | -| `keyid` | string | sha256sum of the public key | +| `keyid` | string | [sha256sum](https://linux.die.net/man/1/sha256sum) of the public key | | `key` | string | Base64 encoded public key | ### `step` Object @@ -70,7 +74,7 @@ Policies are JSON documents that are signed and wrapped in a DSSE envelope. The | Key | Type | Description | | --- | ---- | ----------- | | `type` | string | Type of functionary. Valid values are "root" or "publickey". | -| `certConstraint` | `certConstraint` object | Object defining constraints about the signer's certificate for "root" functionaries. Only valid if `type` is "root". | +| `certConstraint` | `certConstraint` object | Object defining constraints upon the signer's certificate for "root" functionaries. Only valid if `type` is "root". | | `publickeyid` | string | Key ID of a public key that is trusted to sign this step. Only valid if `type` is "publickey". | ### `certConstraint` Object @@ -85,9 +89,9 @@ Policies are JSON documents that are signed and wrapped in a DSSE envelope. The | `roots` | array of strings | Array of Key IDs the signer's certificate must belong to to be trusted. | Every attribute of the certificate must match the attributes defined by the constraint exactly. A certificate must match -at least one constraint to pass the policy. Wildcards are allowed if they are the only elemnt in the constraint. +at least one constraint to pass the policy. Wildcards are allowed if they are the only element in the constraint. -Example of a constraint that would allow any certificate, as long as it belongs to a root defined in the policy: +Example of a constraint that would allow use of any certificate, as long as it belongs to a root defined in the policy: ``` { @@ -100,7 +104,7 @@ Example of a constraint that would allow any certificate, as long as it belongs } ``` -SPIFFE IDs are defined as URIs on the certificate, so a policy that would enforce a SPIFFE ID may look like: +[SPIFFE](https://spiffe.io/) IDs are defined as URIs on the certificate, so a policy that would enforce a SPIFFE ID may look like: ``` { @@ -118,7 +122,7 @@ SPIFFE IDs are defined as URIs on the certificate, so a policy that would enforc | Key | Type | Description | | --- | ---- | ----------- | | `type` | string | Type reference of an attestation that must appear in a step. | -| `regopolicies` | array of `regopolicy` objects | Rego policies that will be run against the attestation. All must pass. | +| `regopolicies` | array of `regopolicy` objects | [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) policies that will be run against the attestation. All must pass. | ### `regopolicy` Object @@ -127,9 +131,11 @@ SPIFFE IDs are defined as URIs on the certificate, so a policy that would enforc | `name` | string | Name of the rego policy. Will be reported on failures. | | `module` | string | Base64 encoded rego module | -Rego modules are expected to output a data with the name of `deny` in the case a rego policy evaluation is failed. -`deny` can be a string or an array of strings and should be populated with a human readable string describing why the -policy was denied. Any other data output by the module will be ignored. An example of a valid rego policy may look like: +Rego modules are expected to output a data with the name of `deny` in the case of a rego policy evaluation failure. +`deny` can be a string or an array of strings and should be populated with a human-readable string describing why the +policy was denied. Any other data output by the module will be ignored. + +Following is an example output for a valid rego policy: ``` package commandrun.exitcode @@ -235,7 +241,7 @@ deny[msg] { } ``` -The above example policy requires two attestation collections are present, one named "clone" and one named "build". Both +The above example policy requires that two attestation collections be present, one named "clone" and one named "build". Both collections must have a material, command-run, and product attestor within them. The command-run attestor for the "build" collection must have recorded a command of `go build -o=testapp .` to pass the embedded rego policy. The build step is configured to ensure the materials used are consistent with the artifacts from the clone step, assuring that diff --git a/docs/witness_run.md b/docs/witness_run.md index f1911160..5986fe30 100644 --- a/docs/witness_run.md +++ b/docs/witness_run.md @@ -15,14 +15,14 @@ witness run [cmd] [flags] --fulcio-oidc-client-id string OIDC client ID to use for authentication --fulcio-oidc-issuer string OIDC issuer to use for authentication -h, --help help for run - -i, --intermediates strings Intermediates that link trust back to a root in the policy + -i, --intermediates strings Intermediates that link trust back to a root of trust in the policy -k, --key string Path to the signing key - -o, --outfile string File to write signed data. Defaults to stdout + -o, --outfile string File to which to write signed data. Defaults to stdout -r, --rekor-server string Rekor server to store attestations --spiffe-socket string Path to the SPIFFE Workload API socket -s, --step string Name of the step being run - --trace enable tracing for the command - -d, --workingdir string Directory that commands will be run from + --trace Enable tracing for the command + -d, --workingdir string Directory from which commands will run ``` ### Options inherited from parent commands diff --git a/docs/witness_sign.md b/docs/witness_sign.md index 064677c9..8127357c 100644 --- a/docs/witness_sign.md +++ b/docs/witness_sign.md @@ -20,7 +20,7 @@ witness sign [file] [flags] --fulcio-oidc-issuer string OIDC issuer to use for authentication -h, --help help for sign -f, --infile string Witness policy file to sign - -i, --intermediates strings Intermediates that link trust back to a root in the policy + -i, --intermediates strings Intermediates that link trust back to a root of trust in the policy -k, --key string Path to the signing key -o, --outfile string File to write signed data. Defaults to stdout --spiffe-socket string Path to the SPIFFE Workload API socket diff --git a/docs/witness_verify.md b/docs/witness_verify.md index 92025364..32c60eec 100644 --- a/docs/witness_verify.md +++ b/docs/witness_verify.md @@ -19,7 +19,7 @@ witness verify [flags] -p, --policy string Path to the policy to verify --policy-ca strings Paths to CA certificates to use for verifying the policy -k, --publickey string Path to the policy signer's public key - -r, --rekor-server string Rekor server to fetch attestations from + -r, --rekor-server string Rekor server from which to fetch attestations ``` ### Options inherited from parent commands