-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
caf0de1
commit 87248a4
Showing
7 changed files
with
244 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Deploying witness-webhook | ||
|
||
witness-webhook includes a Helm chart to help deploy the service. At the core of it, witness-webhook is a simple service that listens for configured webhook events, creates an in-toto attestation describing the captured events, signs the attestation with a configured signer, and then stores the attestation either to a configured directory or to a configured Archivista instance. | ||
|
||
witness-webhook is configured via some environment variables for basic service configuration, and a yaml file that configures the different webhooks the service will listen for. witness-webhook will create an endpoint for each configured webhook in this yaml file at the path `/webhook/{webhook-name}`. Each configured webhook has it's own signer configured to support the case where webhooks from different sources may need to be signed differently. For more details on the specific configuration variables and this yaml file, see the README in the root directory. | ||
|
||
## Github and Vault | ||
|
||
This example will walk through a sample deployment of witness-webhook that listens for events from Github and signs attestations with a Vault transit key with Kubernetes authentication to Vault. This example will use a local minikube instance to deploy witness-webhook into and a local Vault development instance. This example will assume you have the npm, [minikube](https://minikube.sigs.k8s.io/docs/start), [Vault](https://www.markdownguide.org/basic-syntax/), [Helm](https://helm.sh/docs/intro/install), and [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) CLI tools installed. | ||
|
||
### Setting up minikube | ||
|
||
Once minikube is installed, simply running `minikube start` will be enough to bring up a minikube instance sufficient for this example. Your kubecontext should automatically be switched to point to the minikube instance, but just in case or if you switch your kubecontext, running `minikube update-context` will set it back. | ||
|
||
Any files referenced in the following steps are available in the docs/example-vault directory, and all commands assume you are running in the docs/example-vault directory. | ||
|
||
### Setting up Vault | ||
|
||
1. Start the Vault server with `vault server -dev -dev-root-token-id root -dev-listen-address 0.0.0.0:8200 -log-level=debug` | ||
1. Set VAULT_ADDR to point to the local dev server with `export VAULT_ADDR=http://127.0.0.1:8200` | ||
1. Enable kubernetes authentication `vault auth enable kubernetes` | ||
1. Enable the transit secrets engine `vault secrets enable transit` | ||
1. Create a transit key with `vault write transit/keys/testkey type=ecdsa-p521` | ||
1. Create a vault service account for the Token Reviewer: `kubectl create serviceaccount vault-token-reviewer` | ||
1. Apply the cluster role for Token Reivew `kubectl apply -f cluterrole.yaml` | ||
1. Create a token for the Token Reviewer service account `export REVIEWER_TOKEN=$(kubectl create token vault-token-reviewer)` | ||
1. Get the Kubernetes CA `export KUBE_CA=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode)` | ||
1. Get the Kubernetes host `` export KUBE_HOST=`$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.server}')` `` | ||
1. Configure kubernetes auth for Vault `vault write auth/kubernetes/config token_reviewer_jwt="${REVIEWER_TOKEN}" kubernetes_host="${KUBE_HOST}" kubernetes_ca_cert="${KUBE_CA}" issuer="https://kubernetes.default.svc.cluster.local"` | ||
1. Apply a Vault policy allowing access to the transit secret engine `vault write sys/policy/witness-webhook [email protected]` | ||
1. Create a role that will bind to witness-webhook's service account `vault write auth/kubernetes/role/witness-webhook bound_service_account_names="witness-webhook" bound_service_account_namespaces="default" policies="witness-webhook" ttl=5m` | ||
|
||
### Deploying witness-webhook | ||
|
||
1. Create a service account for witness-webhook `kubectl create service account witness-webhook` | ||
1. Create a secret for the webhook, `echo -n supersecretkey > githubsecret` and `kubectl create secret generic githubwebhooksecret --from-file githubsecret` | ||
1. SSH into minikube to get the IP we'll talk to Vault with `minikube ssh dig +short host.docker.internal` | ||
1. Use the IP address above to modify the values.yaml in the example's directory, updating the `hashivault-addr` variable's value. While here, observe the values.yaml. A few things of note: we are mounting the previously created secret into the pod. This mounted secret is then referred to in the witness-webhook's yaml configuration. We are setting a few global Vault configuration variables with the VAULT_ environment variables. | ||
1. Install the Helm chart `helm install witness-webhook ../../chart -f values.yaml` | ||
1. Port forward to the pod: | ||
|
||
``` | ||
1. Get the application URL by running these commands: | ||
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=witness-webhook,app.kubernetes.io/instance=witness-webhook" -o jsonpath="{.items[0].metadata.name}") | ||
export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") | ||
echo "Visit http://127.0.0.1:8080 to use your application" | ||
kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT | ||
``` | ||
|
||
1. Use smee.io to setup forwarding to the locally running witness-webhook `npm install -g smee-client` and `smee -t http://localhost:8080/webhook/github` . Make note of the URL smee provides. | ||
|
||
### Setting up webhook events from a Github repository | ||
|
||
Navigate to a repository of your choice, and enter the Settings tag. From here find the Webhooks section. Add a new webhook. | ||
|
||
For the Payload URL, use the URL smee provided to you. It should look similar to <https://smee.io/tjywPLhwk6tJyLus> . | ||
|
||
Select application/json as the Content type | ||
|
||
For the Secret, insert `supersecretkey`, matching the secret we created earlier. | ||
|
||
Select which events you would like to receive. | ||
|
||
Once this is setup, try to trigger one of the events. | ||
|
||
You can follow the witness-webhook logs with `kubectl logs -f $POD_NAME` and should see something similar to the following if all is successful | ||
|
||
``` | ||
2024/12/09 23:08:39 attestation stored in archivista for webhook github with gitoid d3b05a8d9b2771b082f845d418936b144adcc8d38b5f5cb10a66e063f6090d5c | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIC7jCCAdagAwIBAgIQLG6VSalCZxOnQLmnZiPYRDANBgkqhkiG9w0BAQsFADAR | ||
MQ8wDQYDVQQKEwZtc3dpZnQwHhcNMjQwODIyMjAxNTAwWhcNMjcwODA3MjAxNTAw | ||
WjARMQ8wDQYDVQQKEwZtc3dpZnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK | ||
AoIBAQCXEhBPjugNKvAAlaSygh6UNXEmyNlgCBF1Y6c2YloO8SjhArv+H2qzIBWP | ||
QgQVz9RDMWt7oVmPcABeZt1xfcbH4rIZsANf/ymIMdM85L/WurSzaBSgOTUSqKpw | ||
uMCZ1ZLyC+ezekXp6PQIK9R+YDNnl9NYOjk1lpsXv6HrHeCxpiYz45Huyn7h+G4p | ||
uQsqtiG/1POGT0M0HGxSu5lXQkmCr2RGx5f6Y2zbTFN9epqh6LvBRLY3JkIefbnD | ||
A5QR9AIqtiR43dZpx0vgzMzFsOKWXtQdQ0UEIMhabUgG4w6k0F87V8sXTytgUumv | ||
gooNtv1IvZfpv4I1pw5bwOezskhtAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwICrDAP | ||
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRLUF2M68Nn43e5NOU3AfpQo3jisTAN | ||
BgkqhkiG9w0BAQsFAAOCAQEAYSjacIl/TXV6JFSkTGv1SezNlpWOUJHy6qftR7z5 | ||
SUxjVcD0ztfKZX4gIvqkHV7xjGbsVo+dJ663G6WI0P1+8ZakINCbEy0HFvdmJ5h9 | ||
AXZPxmFGMVhFLDxa+JNWe05s1cTCgHNGWFf+MCxNT77ICoadUdVaVrv3SngVkUDo | ||
2Ihz51aGkiNFvD/ICnzZxKhT1RP8CzQow4UaWC3cN3KetqD+qL/cgOR3BvJLi7DS | ||
+yOgJS1aVSu9w3kW6LU5zs5kmYcAra+NAIA4ZhT4bn+hgVMAYKr3ABg6PLF4bFAO | ||
oh4ZHrAJ03GlsTbL8uVPTorEiovbDpWpNDd+WdD84hYJkQ== | ||
-----END CERTIFICATE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRoleBinding | ||
metadata: | ||
name: role-tokenreview-binding | ||
namespace: default | ||
roleRef: | ||
apiGroup: rbac.authorization.k8s.io | ||
kind: ClusterRole | ||
name: system:auth-delegator | ||
subjects: | ||
- kind: ServiceAccount | ||
name: vault-token-reviewer | ||
namespace: default |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
serviceAccount: | ||
create: false | ||
name: "witness-webhook" | ||
|
||
volumes: | ||
- name: githubwebhooksecret | ||
secret: | ||
secretName: githubwebhooksecret | ||
|
||
# Additional volumeMounts on the output Deployment definition. | ||
volumeMounts: | ||
- name: githubwebhooksecret | ||
mountPath: /etc/githubwebhooksecret | ||
readonly: true | ||
|
||
env: | ||
- name: VAULT_NAMESPACE | ||
value: ADMIN | ||
|
||
# witness webhook application specific config | ||
# see README.md section on the YAML config for values here. | ||
witnesswebhook: | ||
archivistaUrl: https://archivista.testifysec.io | ||
webhooks: | ||
github: | ||
type: "github" | ||
signer: "kms" | ||
signerOptions: | ||
ref: "hashivault://testkey" | ||
hashivault-addr: http://192.168.65.254:8200 | ||
hashivault-auth-method: kubernetes | ||
hashivault-auth-mount-path: kubernetes | ||
hashivault-role: witness-webhook | ||
options: | ||
secret-file-path: "/etc/githubwebhooksecret/githubsecret" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Allow tokens to look up their own properties | ||
path "auth/token/lookup-self" { | ||
capabilities = ["read"] | ||
} | ||
|
||
# Allow tokens to renew themselves | ||
path "auth/token/renew-self" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow tokens to revoke themselves | ||
path "auth/token/revoke-self" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow a token to look up its own capabilities on a path | ||
path "sys/capabilities-self" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow a token to look up its own entity by id or name | ||
path "identity/entity/id/{{identity.entity.id}}" { | ||
capabilities = ["read"] | ||
} | ||
path "identity/entity/name/{{identity.entity.name}}" { | ||
capabilities = ["read"] | ||
} | ||
|
||
|
||
# Allow a token to look up its resultant ACL from all policies. This is useful | ||
# for UIs. It is an internal path because the format may change at any time | ||
# based on how the internal ACL features and capabilities change. | ||
path "sys/internal/ui/resultant-acl" { | ||
capabilities = ["read"] | ||
} | ||
|
||
# Allow a token to renew a lease via lease_id in the request body; old path for | ||
# old clients, new path for newer | ||
path "sys/renew" { | ||
capabilities = ["update"] | ||
} | ||
path "sys/leases/renew" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow looking up lease properties. This requires knowing the lease ID ahead | ||
# of time and does not divulge any sensitive information. | ||
path "sys/leases/lookup" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow a token to manage its own cubbyhole | ||
path "cubbyhole/*" { | ||
capabilities = ["create", "read", "update", "delete", "list"] | ||
} | ||
|
||
# Allow a token to wrap arbitrary values in a response-wrapping token | ||
path "sys/wrapping/wrap" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow a token to look up the creation time and TTL of a given | ||
# response-wrapping token | ||
path "sys/wrapping/lookup" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow a token to unwrap a response-wrapping token. This is a convenience to | ||
# avoid client token swapping since this is also part of the response wrapping | ||
# policy. | ||
path "sys/wrapping/unwrap" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow general purpose tools | ||
path "sys/tools/hash" { | ||
capabilities = ["update"] | ||
} | ||
path "sys/tools/hash/*" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow checking the status of a Control Group request if the user has the | ||
# accessor | ||
path "sys/control-group/request" { | ||
capabilities = ["update"] | ||
} | ||
|
||
# Allow a token to make requests to the Authorization Endpoint for OIDC providers. | ||
path "identity/oidc/provider/+/authorize" { | ||
capabilities = ["read", "update"] | ||
} | ||
|
||
# Allow permissions to transit | ||
path "transit/keys/*" { | ||
capabilities = [ "read", "update", "create" ] | ||
} | ||
|
||
path "transit/sign/*" { | ||
capabilities = [ "read", "update", "create" ] | ||
} |