Skip to content
Closed
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: 2 additions & 0 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion rs/ic_os/sev/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")

package(default_visibility = ["//rs:ic-os-pkg"])
package(default_visibility = [
"//rs:ic-os-pkg",
"//rs/orchestrator:__pkg__",
])

DEPENDENCIES = [
# Keep sorted.
Expand Down
4 changes: 4 additions & 0 deletions rs/orchestrator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ rust_library(
"//rs/http_endpoints/metrics",
"//rs/http_utils",
"//rs/ic_os/guest_upgrade/server",
"//rs/ic_os/sev",
"//rs/interfaces",
"//rs/interfaces/registry",
"//rs/monitoring/logger",
Expand Down Expand Up @@ -68,6 +69,7 @@ rust_library(
"@crate_index//:serde",
"@crate_index//:serde_cbor",
"@crate_index//:serde_json",
"@crate_index//:sev",
"@crate_index//:slog",
"@crate_index//:slog-async",
"@crate_index//:strum",
Expand Down Expand Up @@ -111,6 +113,7 @@ rust_test(
"//rs/crypto/test_utils/tls",
"//rs/crypto/tls_interfaces/mocks",
"//rs/ic_os/config:config_lib",
"//rs/ic_os/sev",
"//rs/registry/fake",
"//rs/registry/proto_data_provider",
"//rs/registry/subnet_type",
Expand All @@ -124,6 +127,7 @@ rust_test(
"@crate_index//:mockall",
"@crate_index//:rcgen",
"@crate_index//:rustls",
"@crate_index//:sev",
"@crate_index//:tokio-rustls",
],
)
2 changes: 2 additions & 0 deletions rs/orchestrator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ ic-registry-client-helpers = { path = "../registry/helpers" }
ic-registry-keys = { path = "../registry/keys" }
ic-registry-local-store = { path = "../registry/local_store" }
ic-registry-replicator = { path = "./registry_replicator" }
ic_sev = { path = "../ic_os/sev" }
ic-sys = { path = "../sys" }
ic-types = { path = "../types/types" }
idna = { workspace = true }
Expand All @@ -59,6 +60,7 @@ rand = { workspace = true }
serde = { workspace = true }
serde_cbor = { workspace = true }
serde_json = { workspace = true }
sev = { workspace = true }
slog = { workspace = true }
slog-async = { workspace = true }
strum = { workspace = true }
Expand Down
61 changes: 61 additions & 0 deletions rs/orchestrator/src/orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ use std::{
use tokio::task::JoinSet;
use tokio_util::sync::CancellationToken;

#[cfg(target_os = "linux")]
use {
ic_sev::guest::is_sev_active,
sev::firmware::guest::{AttestationReport, Firmware},
sev::parser::ByteParser,
};

const CHECK_INTERVAL_SECS: Duration = Duration::from_secs(10);

/// The subnet is initially in the `Unknown` state. After the upgrade loop runs for the first time,
Expand Down Expand Up @@ -94,6 +101,52 @@ fn load_version_from_file(logger: &ReplicaLogger, path: &Path) -> Result<Replica
})
}

/// Retrieves the AMD SEV chip ID from the attestation report, if SEV is active.
/// Returns `None` if SEV is not active or if there's any error retrieving the chip ID.
#[cfg(target_os = "linux")]
fn get_sev_chip_id(logger: &ReplicaLogger) -> Option<Vec<u8>> {
if !is_sev_active().unwrap_or(false) {
info!(
logger,
"SEV is not active, chip_id will not be included in registration"
);
return None;
}

let mut firmware = match Firmware::open() {
Ok(f) => f,
Err(e) => {
warn!(logger, "Failed to open SEV firmware: {:?}", e);
return None;
}
};

let report_bytes = match firmware.get_report(None, None, None) {
Ok(bytes) => bytes,
Err(e) => {
warn!(
logger,
"Failed to get attestation report from SEV firmware: {:?}", e
);
return None;
}
};

match AttestationReport::from_bytes(&report_bytes) {
Ok(report) => {
info!(
logger,
"Successfully retrieved chip_id from SEV attestation report"
);
Some(report.chip_id.to_vec())
}
Err(e) => {
warn!(logger, "Failed to parse attestation report: {:?}", e);
None
}
}
}

impl Orchestrator {
pub async fn new(
args: OrchestratorArgs,
Expand Down Expand Up @@ -210,6 +263,13 @@ impl Orchestrator {
.with_label_values(&[replica_version.as_ref()])
.set(1);

// Get the chip_id from SEV firmware if SEV is active
#[cfg(target_os = "linux")]
let chip_id: Option<Vec<u8>> = get_sev_chip_id(&logger);

#[cfg(not(target_os = "linux"))]
let chip_id: Option<Vec<u8>> = None;

let mut registration = NodeRegistration::new(
logger.clone(),
config.clone(),
Expand All @@ -218,6 +278,7 @@ impl Orchestrator {
node_id,
Arc::clone(&crypto) as _,
registry_local_store.clone(),
chip_id,
);

let replica_process = Arc::new(Mutex::new(ProcessManager::new(logger.clone())));
Expand Down
6 changes: 5 additions & 1 deletion rs/orchestrator/src/registration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub(crate) struct NodeRegistration {
local_store: Arc<dyn LocalStore>,
signer: Box<dyn Signer>,
display_qr_code: bool,
chip_id: Option<Vec<u8>>,
}

impl NodeRegistration {
Expand All @@ -84,6 +85,7 @@ impl NodeRegistration {
node_id: NodeId,
key_handler: Arc<dyn NodeRegistrationCrypto>,
local_store: Arc<dyn LocalStore>,
chip_id: Option<Vec<u8>>,
) -> Self {
// If we can open a PEM file under the path specified in the replica config,
// we use the given node operator private key to register the node.
Expand Down Expand Up @@ -127,6 +129,7 @@ impl NodeRegistration {
// fully complete and tested, this will be the default, and will be
// removed.
display_qr_code: cfg!(test),
chip_id,
}
}

Expand Down Expand Up @@ -275,7 +278,7 @@ impl NodeRegistration {
.expect("Invalid endpoints in message routing config."),
http_endpoint: http_config_to_endpoint(&self.log, &self.node_config.http_handler)
.expect("Invalid endpoints in http handler config."),
chip_id: None,
chip_id: self.chip_id.clone(),
public_ipv4_config: process_ipv4_config(
&self.log,
&self.node_config.initial_ipv4_config,
Expand Down Expand Up @@ -1133,6 +1136,7 @@ mod tests {
node_id,
Arc::new(key_handler),
local_store,
None,
);

Setup {
Expand Down
Loading