Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ COMPUTE_PCRS_IMAGE=$(REGISTRY)/compute-pcrs:$(TAG)
REG_SERVER_IMAGE=$(REGISTRY)/registration-server:$(TAG)
ATTESTATION_KEY_REGISTER_IMAGE=$(REGISTRY)/attestation-key-register:$(TAG)
TRUSTEE_IMAGE ?= quay.io/trusted-execution-clusters/key-broker-service:v0.17.0
TEST_IMAGE ?= quay.io/trusted-execution-clusters/fedora-coreos-kubevirt:20260129
TEST_IMAGE ?= quay.io/trusted-execution-clusters/fedora-coreos-kubevirt:clevis-attest-reg
# tagged as 42.20251012.2.0
APPROVED_IMAGE ?= quay.io/trusted-execution-clusters/fedora-coreos@sha256:6997f51fd27d1be1b5fc2e6cc3ebf16c17eb94d819b5d44ea8d6cf5f826ee773

Expand Down Expand Up @@ -143,10 +143,15 @@ push-all: push push-bundle ## Pushes all operator and bundle images
install: $(YQ)
ifndef TRUSTEE_ADDR
$(error TRUSTEE_ADDR is undefined)
endif
ifndef AK_REGISTRATION_ADDR
$(error AK_REGISTRATION_ADDR is undefined)
endif
scripts/clean-cluster-kind.sh $(OPERATOR_IMAGE) $(COMPUTE_PCRS_IMAGE) $(REG_SERVER_IMAGE) $(ATTESTATION_KEY_REGISTER_IMAGE)
$(YQ) '.spec.publicTrusteeAddr = "$(TRUSTEE_ADDR):8080"' \
-i $(DEPLOY_PATH)/trusted_execution_cluster_cr.yaml
$(YQ) '.spec.publicAttestationKeyRegisterAddr = "http://$(AK_REGISTRATION_ADDR):8001/register-ak"' \
-i $(DEPLOY_PATH)/trusted_execution_cluster_cr.yaml
sed "s/NAMESPACE/$(NAMESPACE)/g" config/rbac/kustomization.yaml.in > config/rbac/kustomization.yaml
$(KUBECTL) apply -f $(DEPLOY_PATH)/operator.yaml
$(KUBECTL) apply -f config/crd
Expand Down
17 changes: 9 additions & 8 deletions api/trusted-cluster-gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,15 @@ func generateTrustedExecutionClusterCR(args *Args) error {
Namespace: args.namespace,
},
Spec: v1alpha1.TrustedExecutionClusterSpec{
TrusteeImage: args.trusteeImage,
PcrsComputeImage: args.pcrsComputeImage,
RegisterServerImage: args.registerServerImage,
AttestationKeyRegisterImage: &args.attestationKeyRegisterImage,
PublicTrusteeAddr: nil,
TrusteeKbsPort: 0,
RegisterServerPort: 0,
AttestationKeyRegisterPort: 0,
TrusteeImage: args.trusteeImage,
PcrsComputeImage: args.pcrsComputeImage,
RegisterServerImage: args.registerServerImage,
AttestationKeyRegisterImage: &args.attestationKeyRegisterImage,
PublicAttestationKeyRegisterAddr: nil,
PublicTrusteeAddr: nil,
TrusteeKbsPort: 0,
RegisterServerPort: 0,
AttestationKeyRegisterPort: 0,
},
}

Expand Down
14 changes: 9 additions & 5 deletions api/v1alpha1/crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var (
// +kubebuilder:rbac:groups=trusted-execution-clusters.io,resources=trustedexecutionclusters/status;machines/status;approvedimages/status;attestationkeys/status,verbs=get;patch;update

// TrustedExecutionClusterSpec defines the desired state of TrustedExecutionCluster
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.publicAttestationKeyRegisterAddr) || has(self.publicAttestationKeyRegisterAddr)", message="Value is required once set"
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.publicTrusteeAddr) || has(self.publicTrusteeAddr)", message="Value is required once set"
type TrustedExecutionClusterSpec struct {
// Image reference to Trustee all-in-one image
Expand All @@ -52,6 +53,11 @@ type TrustedExecutionClusterSpec struct {
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
AttestationKeyRegisterImage *string `json:"attestationKeyRegisterImage"`

// Address where attester can connect to Attestation Key Register
// +optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
PublicAttestationKeyRegisterAddr *string `json:"publicAttestationKeyRegisterAddr,omitempty"`

// Address where attester can connect to Trustee
// +optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
Expand Down Expand Up @@ -115,8 +121,6 @@ type MachineSpec struct {
// Machine ID, typically a UUID
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
Id string `json:"id"`
// Machine IP address at registration time
RegistrationAddress *string `json:"registrationAddress"`
}

// MachineStatus defines the observed state of Machine.
Expand Down Expand Up @@ -208,9 +212,9 @@ type AttestationKeySpec struct {
// +required
PublicKey string `json:"publicKey"`

// Address defines the address of the machine associated to the attestation key.
// +optional
Address *string `json:"address,omitempty"`
// Uuid define the identifier to which the registration key is registered with. It needs
// to match with the id of the machine for the key to be approved.
Uuid *string `json:"uuid,omitempty"`
}

// AttestationKeyStatus defines the observed state of AttestationKey.
Expand Down
20 changes: 5 additions & 15 deletions attestation-key-register/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,17 @@ struct Args {
#[derive(Debug, Deserialize, Serialize)]
struct AttestationKeyRegistration {
/// Public attestation key
#[serde(alias = "attestation_key")]
public_key: String,
/// Optional address of the machine. If not provided, the request IP will be used.
#[serde(skip_serializing_if = "Option::is_none")]
address: Option<String>,

/// Optional platform for the machine corresponding to the attestation key.
/// Optional uuid used for the machine registration
#[serde(skip_serializing_if = "Option::is_none")]
platform: Option<String>,
uuid: Option<String>,
}

async fn handle_registration(
registration: AttestationKeyRegistration,
client: Client,
addr: Option<SocketAddr>,
) -> Result<impl warp::Reply, Infallible> {
info!("Received registration request: {registration:?}");

Expand Down Expand Up @@ -107,10 +104,6 @@ async fn handle_registration(
}
}

let address = registration
.address
.or_else(|| addr.map(|socket_addr| socket_addr.ip().to_string()));

let name = format!("ak-{}", Uuid::new_v4());
let attestation_key = AttestationKey {
metadata: ObjectMeta {
Expand All @@ -120,7 +113,7 @@ async fn handle_registration(
},
spec: AttestationKeySpec {
public_key: registration.public_key,
address,
uuid: registration.uuid,
},
status: None,
};
Expand Down Expand Up @@ -174,12 +167,9 @@ async fn main() -> anyhow::Result<()> {
.and(warp::path(ATTESTATION_KEY_REGISTER_RESOURCE))
.and(warp::body::json())
.and(with_client(client))
.and(warp::addr::remote())
.and_then(handle_registration);

let addr = SocketAddr::from(([0, 0, 0, 0], args.port));
info!("Listening on {addr}");

let addr: SocketAddr = ([0, 0, 0, 0], args.port).into();
warp::serve(register).run(addr).await;

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion examples/vm-coreos-ign.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ spec:
volumes:
- name: containerdisk
containerDisk:
image: "quay.io/trusted-execution-clusters/fedora-coreos-kubevirt:20260129"
image: "quay.io/trusted-execution-clusters/fedora-coreos-kubevirt:clevis-attest-reg"
imagePullPolicy: IfNotPresent
- name: cloudinitdisk
cloudInitConfigDrive:
Expand Down
13 changes: 3 additions & 10 deletions operator/src/attestation_key_register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ async fn ak_reconcile(
ControllerError::Anyhow(e.into())
})?;
for machine in &machine_list.items {
if ak.spec.address.as_ref() == Some(&machine.spec.registration_address) {
if ak.spec.uuid.as_ref() == Some(&machine.spec.id) {
approve_ak(&ak, machine, client.clone()).await?;
return Ok(Action::await_change());
}
Expand All @@ -170,22 +170,15 @@ async fn machine_reconcile(
return Ok(Action::await_change());
}

let machine_address = machine.spec.registration_address.clone();

if machine_address.is_empty() {
info!("Machine IP not set, skipping reconciliation");
return Ok(Action::await_change());
}

let aks: Api<AttestationKey> = Api::default_namespaced(client.clone());
let lp = ListParams::default();
let ak_list: ObjectList<AttestationKey> = aks.list(&lp).await.map_err(|e| {
eprintln!("Error fetching attestation key list: {e}");
ControllerError::Anyhow(e.into())
})?;
for ak in ak_list.items {
if let Some(ak_address) = &ak.spec.address
&& *ak_address == machine_address
if let Some(ak_uuid) = &ak.spec.uuid
&& *ak_uuid == machine.spec.id
{
approve_ak(&ak, &machine, client.clone()).await?;
return Ok(Action::await_change());
Expand Down
1 change: 1 addition & 0 deletions operator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ async fn install_register_server(client: Client, cluster: &TrustedExecutionClust
client.clone(),
owner_reference.clone(),
&cluster.spec.register_server_image,
cluster.spec.public_attestation_key_register_addr.as_deref(),
)
.await
{
Expand Down
17 changes: 14 additions & 3 deletions operator/src/register_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub async fn create_register_server_deployment(
client: Client,
owner_reference: OwnerReference,
image: &str,
attestation_key_register_addr: Option<&str>,
) -> Result<()> {
let app_label = "register-server";
let labels = BTreeMap::from([("app".to_string(), app_label.to_string())]);
Expand Down Expand Up @@ -67,7 +68,15 @@ pub async fn create_register_server_deployment(
container_port: REGISTER_SERVER_PORT,
..Default::default()
}]),
args: Some(vec!["--port".to_string(), REGISTER_SERVER_PORT.to_string()]),
args: {
let mut args =
vec!["--port".to_string(), REGISTER_SERVER_PORT.to_string()];
if let Some(addr) = attestation_key_register_addr {
args.push("--attestation-key-registration-url".to_string());
args.push(addr.to_string());
}
Some(args)
},
..Default::default()
}],
..Default::default()
Expand Down Expand Up @@ -205,13 +214,15 @@ mod tests {

#[tokio::test]
async fn test_create_reg_server_depl_success() {
let clos = |client| create_register_server_deployment(client, Default::default(), "image");
let clos =
|client| create_register_server_deployment(client, Default::default(), "image", None);
test_create_success::<_, _, Deployment>(clos).await;
}

#[tokio::test]
async fn test_create_reg_server_depl_error() {
let clos = |client| create_register_server_deployment(client, Default::default(), "image");
let clos =
|client| create_register_server_deployment(client, Default::default(), "image", None);
test_create_error(clos).await;
}

Expand Down
Loading