# Hashicorp Integration with Tekton Chains

### In this tutorial, we will be running [Chains Signed Provenance Tutorial](https://github.com/tektoncd/chains/blob/main/docs/tutorials/signed-provenance-tutorial.md) using `kms` solution by integrating Tekton Chains with Hashicorp Vault

**NOTE**
* Prerequisite
    * Hashicorp vault should be installed
        * If not installed, you can also try on a minikube or a kind cluster. For more info see [here](https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-minikube-raft)  
        * This provider also requires that the `transit` secret engine is enabled
        * If not done, you can login into the vault provider and run the following command

          ```bash=
          $ vault secrets enable transit
          Success! Enabled the transit secrets engine at: transit/
          ```
    * You can get more info about `transit` secrets [here](https://developer.hashicorp.com/vault/docs/secrets/transit#setup)

    * Make sure Tekton Pipelines and Tekton Chains is installed


### [Chains Signed Provenance Tutorial](https://github.com/tektoncd/chains/blob/main/docs/tutorials/signed-provenance-tutorial.md) using `kms` solution by integrating with Hashicorp Vault

### Step 1: Generate a Key Pair

This provider requires that the standard Vault environment variables (`$VAULT_ADDR, $VAULT_TOKEN`) are set correctly.

```bash=
$ export VAULT_ADDR=http://localhost:8200
$ export VAULT_TOKEN=testtoken
$ vault secrets enable transit  ---> Ignore if you have already done
```

Now run the following command

```bash=
$ cosign generate-key-pair --kms hashivault://$keyname
```

**NOTE**:- If you enabled transit secret engine at different path with the use of -path flag (i.e., $ vault secrets enable -path="someotherpath" transit), you can use TRANSIT_SECRET_ENGINE_PATH environment variable to specify this path while generating a key pair like the following:

In that case the command will be

```bash=
$ TRANSIT_SECRET_ENGINE_PATH="someotherpath" cosign generate-key-pair --kms hashivault://$keyname
```

### Step 2: Set up Authenticaion

There are two forms of authentication that need to be set up:

1.  The Chains controller will be pushing signatures to an OCI registry using the credentials linked to your TaskRun's service account. See our authentication [doc](https://github.com/tektoncd/chains/blob/main/docs/authentication.md)
2.  The Kaniko Task that will build and push the image needs push permissions for your registry.

To set up auth for the Kaniko Task, you'll need a Kubernetes secret of a docker config.json file which contains the required auth. You can create the secret by running:

```bash=
kubectl create secret generic [DOCKERCONFIG_SECRET_NAME] --from-file [PATH TO CONFIG.JSON]
```

### Step 3: Configuring Tekton Chains

You'll need to make these changes to the Tekton Chains configMap i.e. `chains-config` configMap:

```yaml
* artifacts.taskrun.format: slsa/v1
* artifacts.taskrun.storage: oci
* artifacts.taskrun.signer: kms
* artifacts.pipelinerun.signer: kms
* artifacts.oci.signer: kms
* transparency.enabled: "true"
* signers.kms.kmsref: hashivault://$keyname
* signers.kms.auth.address: <VAULT_ADDR>
* signers.kms.auth.token: <VAULT_TOKEN>
```

### Step 4: Start the Kaniko Task

* First apply the

```bash
kubectl apply -f examples/kaniko/kaniko.yaml
```
Substitute with the URI or file path to your Kaniko task.

* Set the following enviornment variables:

```bash=
export REGISTRY=<url_of_registry>
export DOCKERCONFIG_SECRET_NAME=<name_of_the_secret_in_docker_config_json>
```

Substitute with the URL of the registry where you want to push the image.
Substitute with the name of the secret in the docker config.json file.

* Start the Kaniko Task

```bash=
tkn task start --param IMAGE=$REGISTRY/kaniko-chains --use-param-defaults --workspace name=source,emptyDir="" --workspace name=dockerconfig,secret=$DOCKERCONFIG_SECRET_NAME kaniko-chains
```

* Wait for a minute to allow Tekton Chains to generate the provenance and sign it, and then check the availability of the chains.tekton.dev/signed=true annotation on the task run.

```bash=
kubectl get tr <task_run_name> -o json | jq -r .metadata.annotations
{
	"chains.tekton.dev/signed": "true",
	...
}
```

### Step 5: Verify the image and the attestation

```bash=
cosign verify --key cosign.pub $REGISTRY/kaniko-chains
cosign verify-attestation --key cosign.pub --type slsaprovenance $REGISTRY/kaniko-chains
```

or you can use the hashivault://$keyname as key as well

```bash=
cosign verify --key hashivault://testkey $REGISTRY/kaniko-chains
cosign verify-attestation --key hashivault://testkey --type slsaprovenance $REGISTRY/kaniko-chains
```


The output would be like this

```bash=
Verification for index.docker.io/$REGISTRY/kaniko-chains:latest --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The claims were present in the transparency log
  - The signatures were integrated into the transparency log when the certificate was valid
  - The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"index.docker.io/$REGISTRY/kaniko-chains"},"image":{"docker-manifest-digest":"sha256:e14396b283abcbacddba403a923a7fdecf2c54537a1d6a1ee1076767bec742d1"},"type":"cosign container image signature"},"optional":null}]

Verification for docker.io/$REGISTRY/kaniko-chains --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The claims were present in the transparency log
  - The signatures were integrated into the transparency log when the certificate was valid
  - The signatures were verified against the specified public key
{"payloadType":"application/vnd.in-toto+json","payload":" ","signatures":[{"keyid":"SHA256:wvNLyVMa1zxAWD9ZjvKanoCuukphRbKYdLM24TEEAj0","sig":"MEYCIQDsMLBOWKZKDBiiVJOz4ZQbPTKfQwhdBgsbVupJlvlN+gIhAPxMbCfjKGSl1ity9RS9/UMXRcI5QtkCH+LX6t4V5/Ft"}]}

```