Skip to content

Commit ed73907

Browse files
authored
Merge pull request #12 from Jakob-Naucke/compute-pcrs
Compute PCRs
2 parents c72d854 + a5ed684 commit ed73907

File tree

18 files changed

+1761
-296
lines changed

18 files changed

+1761
-296
lines changed

Cargo.lock

Lines changed: 1330 additions & 128 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
11
[workspace]
2-
members = ["crds", "operator", "manifest-gen"]
2+
members = ["compute-pcrs", "crds", "operator", "manifest-gen"]
33
resolver = "3"
4+
5+
[workspace.package]
6+
edition = "2024"
7+
8+
[workspace.dependencies]
9+
anyhow = "1.0.99"
10+
clap = "4.5.41"
11+
env_logger = "0.11.8"
12+
k8s-openapi = { version = "0.25.0", features = ["v1_33"] }
13+
kube = "1.1.0"
14+
log = "0.4.27"
15+
serde = "1.0.219"
16+
serde_json = "1.0.141"
17+
tokio = "1.46.1"

Makefile

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
KUBECTL=kubectl
55

66
REGISTRY ?= quay.io
7-
IMAGE=$(REGISTRY)/confidential-clusters/cocl-operator:latest
7+
OPERATOR_IMAGE=$(REGISTRY)/confidential-clusters/cocl-operator:latest
8+
COMPUTE_PCRS_IMAGE=$(REGISTRY)/confidential-clusters/compute-pcrs:latest
89

910
all: build tools
1011

@@ -19,8 +20,9 @@ manifests-dir:
1920

2021
manifests: tools
2122
target/debug/manifest-gen --output-dir manifests \
22-
--image $(IMAGE) \
23-
--trustee-namespace operators
23+
--image $(OPERATOR_IMAGE) \
24+
--trustee-namespace operators \
25+
--pcrs-compute-image $(COMPUTE_PCRS_IMAGE)
2426

2527
cluster-up:
2628
scripts/create-cluster-kind.sh
@@ -29,17 +31,21 @@ cluster-down:
2931
scripts/delete-cluster-kind.sh
3032

3133
image: build
32-
podman build -t $(IMAGE) -f Containerfile .
34+
podman build -t $(OPERATOR_IMAGE) -f Containerfile .
35+
podman build -t $(COMPUTE_PCRS_IMAGE) \
36+
-f compute-pcrs/Containerfile \
37+
--env K8S_OPENAPI_ENABLED_VERSION=$(K8S_VERSION) .
3338

3439
# TODO: remove the tls-verify, right now we are pushing only on the local registry
3540
push: image
36-
podman push $(IMAGE) --tls-verify=false
41+
podman push $(OPERATOR_IMAGE) --tls-verify=false
42+
podman push $(COMPUTE_PCRS_IMAGE) --tls-verify=false
3743

3844
install-trustee:
3945
scripts/install-trustee.sh
4046

4147
install:
42-
scripts/clean-cluster-kind.sh $(IMAGE)
48+
scripts/clean-cluster-kind.sh $(OPERATOR_IMAGE) $(COMPUTE_PCRS_IMAGE)
4349
$(KUBECTL) apply -f manifests/operator.yaml
4450
$(KUBECTL) apply -f manifests/confidential_cluster_crd.yaml
4551
$(KUBECTL) apply -f manifests/confidential_cluster_cr.yaml

README.md

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,6 @@ within the cluster.
2727

2828
### Quick Start
2929

30-
Fill the file `operator/src/reference-values-in.json` with the desired PCR values, e.g. by
31-
32-
```bash
33-
$ for i in {4,7,14}; do
34-
sudo tpm2_pcrread sha256:${i} | awk -F: '/0x/ {sub(/.*0x/, "", $2); gsub(/[^0-9A-Fa-f]/, "", $2); print tolower($2)}'
35-
done
36-
6401162a80170f039aabff2606d2c7b4843c592edcdc082abd66f644131d83c8
37-
b3a56a06c03a65277d0a787fcabc1e293eaa5d6dd79398f2dda741f7b874c65d
38-
17cdefd9548f4383b67a37a901673bf3c8ded6f619d36c8007562de1d93c81cc
39-
```
40-
41-
i.e.
42-
43-
```json
44-
{
45-
"pcr4": "6401162a80170f039aabff2606d2c7b4843c592edcdc082abd66f644131d83c8",
46-
"pcr7": "b3a56a06c03a65277d0a787fcabc1e293eaa5d6dd79398f2dda741f7b874c65d",
47-
"pcr14": "17cdefd9548f4383b67a37a901673bf3c8ded6f619d36c8007562de1d93c81cc"
48-
}
49-
```
50-
51-
> Hint: You can stop tracking changes to this file with `git update-index --skip-worktree operator/src/reference-values-in.json`.
52-
5330
Create the cluster, install [trustee operator](https://github.com/confidential-containers/trustee-operator) and deploy
5431
the operator.
5532

compute-pcrs/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "compute-pcrs"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
description = "A cocl-operator optimized compute-pcrs interface"
6+
7+
[dependencies]
8+
anyhow.workspace = true
9+
chrono = "0.4.41"
10+
clap = { workspace = true, features = ["derive"] }
11+
compute-pcrs-lib = { git = "https://github.com/confidential-clusters/compute-pcrs", version = "0.1.0" }
12+
k8s-openapi.workspace = true
13+
kube.workspace = true
14+
log.workspace = true
15+
serde = { workspace = true, features = ["derive"] }
16+
serde_json.workspace = true
17+
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }

compute-pcrs/Containerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM ghcr.io/confidential-clusters/compute-pcrs/buildroot AS builder
2+
WORKDIR /compute-pcrs
3+
COPY Cargo.toml Cargo.lock .
4+
COPY compute-pcrs compute-pcrs
5+
# Hack: Set compute-pcrs as sole member to avoid needing to copy other crates.
6+
# In that case, a rebuild would be triggered upon any change in those crates.
7+
RUN sed -i 's/members =.*/members = ["compute-pcrs"]/' Cargo.toml && \
8+
git clone --depth 1 https://github.com/confidential-clusters/reference-values && \
9+
cargo build --release -p compute-pcrs
10+
11+
FROM quay.io/fedora/fedora:42
12+
COPY --from=builder /compute-pcrs/target/release/compute-pcrs /usr/local/bin
13+
COPY --from=builder /compute-pcrs/reference-values /reference-values

compute-pcrs/src/main.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use anyhow::Result;
2+
use chrono::{DateTime, TimeDelta, Utc};
3+
use clap::Parser;
4+
use compute_pcrs_lib::*;
5+
use k8s_openapi::api::core::v1::ConfigMap;
6+
use kube::api::{ObjectMeta, PostParams};
7+
use kube::{Api, Client};
8+
use log::info;
9+
use serde::{Serialize, Serializer};
10+
use std::collections::BTreeMap;
11+
12+
fn primitive_date_time_to_str<S>(d: &DateTime<Utc>, s: S) -> Result<S::Ok, S::Error>
13+
where
14+
S: Serializer,
15+
{
16+
s.serialize_str(&d.format("%Y-%m-%dT%H:%M:%SZ").to_string())
17+
}
18+
19+
/// Sync with Trustee
20+
/// reference_value_provider_service::reference_value::ReferenceValue
21+
/// (cannot import directly because its expiration doesn't serialize
22+
/// right)
23+
#[derive(Serialize)]
24+
struct ReferenceValue {
25+
pub version: String,
26+
pub name: String,
27+
#[serde(serialize_with = "primitive_date_time_to_str")]
28+
pub expiration: DateTime<Utc>,
29+
pub value: serde_json::Value,
30+
}
31+
32+
#[derive(Parser)]
33+
#[command(version, about)]
34+
struct Args {
35+
/// Path to the kernel modules directory
36+
#[arg(short, long)]
37+
kernels: String,
38+
/// Path to the ESP directory
39+
#[arg(short, long)]
40+
esp: String,
41+
/// Path to the directory storing EFIVar files
42+
#[arg(short = 's', long)]
43+
efivars: String,
44+
/// Path to directory storing MokListRT, MokListTrustedRT and MokListXRT
45+
#[arg(short, long)]
46+
mokvars: String,
47+
/// ConfigMap name to write to
48+
#[arg(short, long)]
49+
configmap: String,
50+
/// Namespace to write ConfigMap to
51+
#[arg(short, long)]
52+
namespace: String,
53+
}
54+
55+
#[tokio::main]
56+
async fn main() -> Result<()> {
57+
let args = Args::parse();
58+
59+
let mut pcrs: Vec<_> = [
60+
compute_pcr4(&args.kernels, &args.esp, false, true),
61+
compute_pcr7(Some(&args.efivars), &args.esp, true),
62+
compute_pcr14(&args.mokvars),
63+
]
64+
.iter()
65+
.map(|pcr| (format!("pcr{}", pcr.id), pcr.value.clone()))
66+
.collect();
67+
pcrs.push(("svn".to_string(), "1".to_string()));
68+
69+
let reference_values: Vec<_> = pcrs
70+
.iter()
71+
.map(|(name, value)| ReferenceValue {
72+
version: "0.1.0".to_string(),
73+
name: format!("tpm_{name}"),
74+
expiration: Utc::now() + TimeDelta::days(365),
75+
value: serde_json::Value::Array(vec![serde_json::Value::String(value.to_string())]),
76+
})
77+
.collect();
78+
let reference_values_json = serde_json::to_string(&reference_values)?;
79+
let data = BTreeMap::from([(
80+
"reference-values.json".to_string(),
81+
reference_values_json.to_string(),
82+
)]);
83+
84+
let config_map = ConfigMap {
85+
metadata: ObjectMeta {
86+
name: Some(args.configmap.clone()),
87+
namespace: Some(args.namespace.clone()),
88+
..Default::default()
89+
},
90+
data: Some(data),
91+
..Default::default()
92+
};
93+
94+
let client = Client::try_default().await?;
95+
let config_maps: Api<ConfigMap> = Api::namespaced(client, &args.namespace);
96+
match config_maps
97+
.create(&PostParams::default(), &config_map)
98+
.await
99+
{
100+
Ok(_) => info!("Create ConfigMap {}", args.configmap),
101+
Err(kube::Error::Api(ae)) if ae.code == 409 => {
102+
info!("ConfigMap {} already exists", args.configmap)
103+
}
104+
Err(e) => return Err(e.into()),
105+
}
106+
107+
Ok(())
108+
}

crds/Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[package]
22
name = "crds"
33
version = "0.1.0"
4-
edition = "2024"
4+
edition.workspace = true
55

66
[dependencies]
7-
k8s-openapi = { version = "0.25.0", features = ["v1_33"] }
8-
kube = { version = "1.1.0", features = ["derive"] }
7+
k8s-openapi.workspace = true
8+
kube = { workspace = true, features = ["derive"] }
99
schemars = { version = "0.8", features = ["derive"] }
10-
serde = { version = "1.0.219", features = ["derive"] }
11-
serde_json = "1.0.141"
10+
serde = { workspace = true, features = ["derive"] }
11+
serde_json.workspace = true

crds/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize};
1212
)]
1313
pub struct ConfidentialClusterSpec {
1414
pub trustee: Trustee,
15+
pub pcrs_compute_image: String,
1516
}
1617

1718
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]

kind/config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ nodes:
99
extraPortMappings:
1010
- containerPort: 31000
1111
hostPort: 8080
12+
featureGates:
13+
"ImageVolume": true

0 commit comments

Comments
 (0)