Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node Attestation with x509 via Keylime [** DON'T MERGE YET] #133

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
7 changes: 7 additions & 0 deletions charts/spire/templates/agent-configmap.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ data:
plugin_data {
}
}
{{- else if .Values.x509 }}
NodeAttestor "x509pop" {
plugin_data {
private_key_path = "/run/spire/agent/node.key.pem"
certificate_path = "/run/spire/agent/node-bundle.cert.pem"
}
}
{{- else }}
NodeAttestor "k8s_psat" {
plugin_data {
Expand Down
8 changes: 8 additions & 0 deletions charts/spire/templates/agent-daemonset.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ spec:
readOnly: true
- name: spire-agent-token
mountPath: /var/run/secrets/tokens
readOnly: true
- name: agent-x509
mountPath: /run/spire/agent
readOnly: true
livenessProbe:
exec:
command:
Expand All @@ -68,6 +72,10 @@ spec:
hostPath:
path: {{ .Values.spireAgent.socketDir }}
type: DirectoryOrCreate
- name: agent-x509
hostPath:
path: /run/spire/x509
type: Directory
- name: spire-agent-token
projected:
sources:
Expand Down
2 changes: 1 addition & 1 deletion charts/spire/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ region: sample-region
# SPIRE server
trustdomain: spiretest.com
# SPIRE version:
spireVersion: 1.0.2
spireVersion: 1.1.3

# spireServer - location of the SPIRE server
spireServer:
Expand Down
7 changes: 7 additions & 0 deletions charts/tornjak/templates/server-configmap.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ data:
data_dir = "/run/spire/data"
log_level = "DEBUG"
default_svid_ttl = "1h"
# extended to 7 days, just for testing
ca_ttl = "168h"
socket_path = "{{ .Values.spireServer.socketDir }}/{{ .Values.spireServer.socketFile }}"

{{- if .Values.oidc.enable }}
Expand Down Expand Up @@ -70,6 +72,11 @@ data:
}
}
}
NodeAttestor "x509pop" {
plugin_data {
ca_bundle_path = "/opt/spire/sample-x509/rootCA.pem"
}
}

{{- if .Values.attestors.aws_iid -}}
{{- if .Values.attestors.aws_iid.access_key_id -}}
Expand Down
6 changes: 6 additions & 0 deletions charts/tornjak/templates/server-statefulset.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ spec:
# not needed if using volumeClaimTemplates and sockets
privileged: true
volumeMounts:
- name: sample-x509
mountPath: /opt/spire/sample-x509
- name: spire-config
mountPath: /run/spire/config
readOnly: true
Expand Down Expand Up @@ -124,6 +126,10 @@ spec:
mountPath: {{ .Values.oidc.socketDir }}
{{- end }}
volumes:
- name: sample-x509
secret:
defaultMode: 0400
secretName: sample-x509
- name: spire-config
configMap:
name: spire-server
Expand Down
8 changes: 3 additions & 5 deletions charts/tornjak/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@ clustername: spire-example
# trustdomain is arbitrary but needs to match between Server and Agent
trustdomain: spiretest.com
# SPIRE version used for consistency across components
spireVersion: 1.0.2
spireVersion: 1.1.3

# SPIRE Server configuration
spireServer:
# tornjakImage - Tornjak with SPIRE Server
# TODO this is just a temporary image with several patches. It
# should be removed after the patches are available in the SPIRE main
# img: ghcr.io/spiffe/tornjak-spire-server
img: tsidentity/local-spire-server
img: ghcr.io/spiffe/tornjak-spire-server

socketDir: /run/spire-server/private
socketFile: api.sock
# selfSignedCA - SPIRE will create the self signed CA unless this value
Expand Down
70 changes: 70 additions & 0 deletions docs/spire-workload-registrar.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,76 @@ or delete them, if needed, using `Entry ID` value:
-socketPath /run/spire/sockets/registration.sock
```

## IMPORTANT: For non-k8s node attestors
When using NodeAttestor other than *k8s_psa*
you must create entries to tie your agents to the parent ID with specific attestation
(see issue [852](https://github.com/spiffe/spire/issues/852))

Once the workload registrar entry is created (as above),
the registrar will create entries for each node.
For example:
* spiffe://openshift.space-x.com/k8s-workload-registrar/spire-01/node/10.170.231.21
- k8s_psat:cluster:spire-01
- k8s_psat:agent_node_uid:7f450925-f3b3-4274-bfe9-e9d09bafbc12
* spiffe://openshift.space-x.com/k8s-workload-registrar/spire-01/node/10.170.231.14
- k8s_psat:cluster:spire-01
- k8s_psat:agent_node_uid:c8b69816-f5f9-4e90-aaa1-6445d5bba11a

with `spiffe://openshift.space-x.com/spire/server` as Parent ID

Now we have to create new entries that would tie the above SPIFFE IDs to the
attested entries.
Look at the agent list and gather the selectors:

For example, agents:
```
* spiffe://openshift.space-x.com/spire/agent/x509pop/ca34d6728cf332689646010a1d9012d8fa449a3f

"selectors": [
{
"type": "x509pop",
"value": "ca:fingerprint:42cd4a9e007c67a52bfb28cf3f4a8cfd576fbfd2"
},
{
"type": "x509pop",
"value": "ca:fingerprint:df27569b5adc9c44db043ea1f509c9f79a049e2d"
},
{
"type": "x509pop",
"value": "subject:cn:some common name1"
}

* spiffe://openshift.space-x.com/spire/agent/x509pop/1753fc2737195744cd52942d9723e1d7d2804249

"selectors": [
{
"type": "x509pop",
"value": "ca:fingerprint:42cd4a9e007c67a52bfb28cf3f4a8cfd576fbfd2"
},
{
"type": "x509pop",
"value": "ca:fingerprint:df27569b5adc9c44db043ea1f509c9f79a049e2d"
},
{
"type": "x509pop",
"value": "subject:cn:some common name2"
}
]
```

So now we have to tie them together. Create new entries, one per each node:

For example (pick one of the selector values to guarantee uniqueness):

* SPIFFE ID: spiffe://openshift.space-x.com/k8s-workload-registrar/spire-01/node/10.170.231.14
- Parent ID: spiffe://openshift.space-x.com/spire/agent/x509pop/1753fc2737195744cd52942d9723e1d7d2804249
- Selectors: x509pop:ca:fingerprint:42cd4a9e007c67a52bfb28cf3f4a8cfd576fbfd2
* SPIFFE ID: spiffe://openshift.space-x.com/k8s-workload-registrar/spire-01/node/10.170.231.21
- Parent ID: spiffe://openshift.space-x.com/spire/agent/x509pop/ca34d6728cf332689646010a1d9012d8fa449a3f
- Selectors: x509pop:subject:cn:"some common name1"

No ADMIN selection required.

## Create sample deployment
To see this environment in action, let’s deploy a sample workload with a simple SPIRE client. This example starts a pod that contains SPIRE agent binaries. We can use them to get SPIFFE identity.
Before deploying the client, let’s take a look at the deployment file:
Expand Down
10 changes: 10 additions & 0 deletions docs/x509-create.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ The steps are following:

### Generating RootCA

This example comes with sample x509 certificates and keys to demonstrate
`x509pop` nodeAttestor capabilities.

The sample keys are present in [../sample-x509](../sample-x509) directory.
You can create a new set of certs and keys:
* [using a script](#generate_keys_using_a_script)
* [manually (recommended)](#generate_keys_manually)

## Generate keys using a script
To create new sample certs and keys:
```console
mkdir x509/ca
cd x509/ca
Expand Down
87 changes: 87 additions & 0 deletions docs/x509.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Tornjak + SPIRE with x509pop (Proof of Possession) for Confidential Computing project
The `x509pop` nodeAttestor plugin attests nodes that have been provisioned with
an x509 identity through an out-of-band mechanism.
It verifies that the certificate is rooted to a trusted set of CAs
and issues a signature based proof-of-possession challenge to the agent plugin
to verify that the node is in possession of the private key.

## Index
* Create x509 certs and keys using a script
* Create x509 certs and keys manually (recommended)
* Deploy the

## Pre-install: Get the code and create Keys
### Get the code
Obtain the clone of the repo:

```console
git clone https://github.com/IBM/trusted-service-identity.git
git checkout conf_container
```
### Create keys and certificates for testing
Keys are already created in `sample-x509` directory.

The script for generating keys is based on:
https://github.com/spiffe/spire/blob/v1.2.0/test/fixture/nodeattestor/x509pop/generate.go

To create new sample keys:
```console
cd sample-x509
go run generate.go
cd ..
```

Setting up the keys for SPIRE Server:
* generate rootCA key
* create rootCert (rootKey)
* generate intermediate Key
* create intermediateCert(intermKey, rootKey, rootCert)


## Install the SPIRE Server with OIDC and Vault
Create a new namespace
```console
kubectl create ns tornjak
```

Server NodeAttestor just needs the rootCA cert for verification (rootCA.pem)

Pass the cert as a Secret:
```console

kubectl -n tornjak create secret generic sample-x509 \
--from-file=rootCA.pem="sample-x509/root.cert.pem"
```

### Server deployment
Here we are using OpenShift cluster in IBM Cloud.
Setup `KUBECONFIG` and deploy:

```console
# use a script to get CLUSTER_NAME
utils/get-cluster-info.sh

# or set it up explicitly:
export CLUSTER_NAME=openshift-ibmcloud-01
utils/install-open-shift-tornjak.sh -c $CLUSTER_NAME -t openshift.space-x.com --oidc
```

Test access to Tornjak and OIDC, as shown at the end of the deployment.

Capture the `spire-bundle` to be used for Spire Agents:

```console
kubectl -n tornjak get configmap spire-bundle -oyaml | kubectl patch --type json --patch '[{"op": "replace", "path": "/metadata/namespace", "value":"spire"}]' -f - --dry-run=client -oyaml > spire-bundle.yaml
```

### Setup Vault with OIDC:
https://github.com/IBM/trusted-service-identity/blob/main/docs/spire-oidc-vault.md

## Deploy SPIRE Agents in Remote Clusters
Follow the deployment of [agent with x509](./x509-agent.md)

### To cleanup the cluster (removes everything)

```console
utils/install-open-shift-tornjak.sh --clean
```
3 changes: 2 additions & 1 deletion utils/install-open-shift-spire.sh
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ oc_cli adm policy add-scc-to-user privileged -z $SPIRE_AG_SA
helm install --set "spireServer.address=$SPIRESERVER" --set "namespace=$PROJECT" \
--set "clustername=$CLUSTERNAME" --set "trustdomain=$TRUSTDOMAIN" \
--set "region=$REGION" \
--set "openShift=true" spire charts/spire # --debug
--set "x509=true" \
--set "openShift=true" spire charts/spire --debug

cat << EOF

Expand Down
4 changes: 4 additions & 0 deletions utils/install-open-shift-tornjak.sh
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,10 @@ echo "$INGRESS"

# setup TLS secret:
CRN=$(ibmcloud oc ingress secret get -c "$CLUSTERNAME" --name "$INGSEC" --namespace openshift-ingress --output json | jq -r '.crn')

# not needed for k8s 1.22 anymore:
#ibmcloud oc ingress secret create --cluster "$CLUSTERNAME" --cert-crn "$CRN" --name "$INGSEC" --namespace "$PROJECT"

if [ "$?" == "0" ]; then
echo "All good"
fi
Expand All @@ -230,6 +232,8 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: spireingress
annotations:
kubernetes.io/ingress.class: "public-iks-k8s-nginx"
spec:
tls:
- hosts:
Expand Down