diff --git a/Cargo.Bazel.Fuzzing.json.lock b/Cargo.Bazel.Fuzzing.json.lock index c3958e68a3e..3d8eda5e6c1 100644 --- a/Cargo.Bazel.Fuzzing.json.lock +++ b/Cargo.Bazel.Fuzzing.json.lock @@ -1,5 +1,5 @@ { - "checksum": "7576f905197c598c36ac08832711e09df68c426937e036249ed041bb9cab3e7e", + "checksum": "da244b91cf0bcee2fc2e8d01bd6b0a77a191023585c05505d0420e068ef38b9f", "crates": { "abnf 0.12.0": { "name": "abnf", diff --git a/Cargo.Bazel.StaticOpenSSL.json.lock b/Cargo.Bazel.StaticOpenSSL.json.lock index 02568b70f86..d6f82186149 100644 --- a/Cargo.Bazel.StaticOpenSSL.json.lock +++ b/Cargo.Bazel.StaticOpenSSL.json.lock @@ -1,5 +1,5 @@ { - "checksum": "c76d92d7ad673ee8aadd0c439326793f2143301066e6572adcd5f3643c2e7a44", + "checksum": "f5d289e5eff4cd04d46317c2ae6dbc677770d1a6719abcdf29d8b5b5d103ab75", "crates": { "abnf 0.12.0": { "name": "abnf", @@ -13955,7 +13955,7 @@ "target": "serial_test" }, { - "id": "sev 1.2.0", + "id": "sev 1.2.1", "target": "sev" }, { @@ -45383,13 +45383,13 @@ }, "license": "MIT/Apache-2.0" }, - "sev 1.2.0": { + "sev 1.2.1": { "name": "sev", - "version": "1.2.0", + "version": "1.2.1", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/sev/1.2.0/download", - "sha256": "9c77eff933413b557ad3af20f6ddb198471d639d611b4738bcb78d32d7941892" + "url": "https://crates.io/api/v1/crates/sev/1.2.1/download", + "sha256": "7fd749a01c88a51ac718b59fe571177b31e478dfe059267977042477a0531224" } }, "targets": [ @@ -45477,7 +45477,7 @@ "target": "serde_bytes" }, { - "id": "sev 1.2.0", + "id": "sev 1.2.1", "target": "build_script_build" }, { @@ -45492,7 +45492,7 @@ "selects": {} }, "edition": "2018", - "version": "1.2.0" + "version": "1.2.1" }, "build_script_attrs": { "data_glob": [ diff --git a/Cargo.Bazel.StaticOpenSSL.toml.lock b/Cargo.Bazel.StaticOpenSSL.toml.lock index a861471e592..7e2e9736e07 100644 --- a/Cargo.Bazel.StaticOpenSSL.toml.lock +++ b/Cargo.Bazel.StaticOpenSSL.toml.lock @@ -8786,9 +8786,9 @@ dependencies = [ [[package]] name = "sev" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c77eff933413b557ad3af20f6ddb198471d639d611b4738bcb78d32d7941892" +checksum = "7fd749a01c88a51ac718b59fe571177b31e478dfe059267977042477a0531224" dependencies = [ "bincode", "bitfield", diff --git a/Cargo.Bazel.json.lock b/Cargo.Bazel.json.lock index 02568b70f86..d6f82186149 100644 --- a/Cargo.Bazel.json.lock +++ b/Cargo.Bazel.json.lock @@ -1,5 +1,5 @@ { - "checksum": "c76d92d7ad673ee8aadd0c439326793f2143301066e6572adcd5f3643c2e7a44", + "checksum": "f5d289e5eff4cd04d46317c2ae6dbc677770d1a6719abcdf29d8b5b5d103ab75", "crates": { "abnf 0.12.0": { "name": "abnf", @@ -13955,7 +13955,7 @@ "target": "serial_test" }, { - "id": "sev 1.2.0", + "id": "sev 1.2.1", "target": "sev" }, { @@ -45383,13 +45383,13 @@ }, "license": "MIT/Apache-2.0" }, - "sev 1.2.0": { + "sev 1.2.1": { "name": "sev", - "version": "1.2.0", + "version": "1.2.1", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/sev/1.2.0/download", - "sha256": "9c77eff933413b557ad3af20f6ddb198471d639d611b4738bcb78d32d7941892" + "url": "https://crates.io/api/v1/crates/sev/1.2.1/download", + "sha256": "7fd749a01c88a51ac718b59fe571177b31e478dfe059267977042477a0531224" } }, "targets": [ @@ -45477,7 +45477,7 @@ "target": "serde_bytes" }, { - "id": "sev 1.2.0", + "id": "sev 1.2.1", "target": "build_script_build" }, { @@ -45492,7 +45492,7 @@ "selects": {} }, "edition": "2018", - "version": "1.2.0" + "version": "1.2.1" }, "build_script_attrs": { "data_glob": [ diff --git a/Cargo.Bazel.toml.lock b/Cargo.Bazel.toml.lock index a861471e592..7e2e9736e07 100644 --- a/Cargo.Bazel.toml.lock +++ b/Cargo.Bazel.toml.lock @@ -8786,9 +8786,9 @@ dependencies = [ [[package]] name = "sev" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c77eff933413b557ad3af20f6ddb198471d639d611b4738bcb78d32d7941892" +checksum = "7fd749a01c88a51ac718b59fe571177b31e478dfe059267977042477a0531224" dependencies = [ "bincode", "bitfield", diff --git a/Cargo.lock b/Cargo.lock index 7d7dac2c718..8a5f1dc5b8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7517,6 +7517,7 @@ dependencies = [ name = "ic-icos-sev" version = "0.8.0" dependencies = [ + "assert_matches", "async-trait", "ic-base-types", "ic-icos-sev-interfaces", @@ -13607,6 +13608,7 @@ dependencies = [ "ic-http-endpoints-metrics", "ic-http-utils", "ic-ic00-types", + "ic-icos-sev", "ic-image-upgrader", "ic-interfaces", "ic-interfaces-registry", @@ -16229,15 +16231,6 @@ dependencies = [ "uuid 1.3.0", ] -[[package]] -name = "sevctl" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap 3.2.23", - "sev", -] - [[package]] name = "sha1" version = "0.10.5" @@ -16516,6 +16509,15 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "snptool" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap 3.2.23", + "sev", +] + [[package]] name = "sns_tests" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index 59d53c920b1..25053f742a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,7 +129,7 @@ members = [ "rs/ic_os/setupos-disable-checks", "rs/ic_os/sev_interfaces", "rs/ic_os/sev", - "rs/ic_os/sevctl", + "rs/ic_os/snptool", "rs/ic_os/vsock/guest", "rs/ic_os/vsock/host", "rs/ic_os/vsock/vsock_lib", diff --git a/bazel/external_crates.bzl b/bazel/external_crates.bzl index 7709986e9f2..8fd49aa5153 100644 --- a/bazel/external_crates.bzl +++ b/bazel/external_crates.bzl @@ -1006,7 +1006,7 @@ def external_crates_repository(name, static_openssl, cargo_lockfile, lockfile, s version = "^0.8.0", ), "sev": crate.spec( - version = "^1.2.0", + version = "^1.2.1", features = [ "openssl", ], diff --git a/ic-os/guestos/defs.bzl b/ic-os/guestos/defs.bzl index d8d69473733..aa261a8112b 100644 --- a/ic-os/guestos/defs.bzl +++ b/ic-os/guestos/defs.bzl @@ -40,7 +40,7 @@ def image_deps(mode, malicious = False): "//publish/binaries:orchestrator": "/opt/ic/bin/orchestrator:0755", ("//publish/malicious:replica" if malicious else "//publish/binaries:replica"): "/opt/ic/bin/replica:0755", # Install the malicious replica if set "//publish/binaries:sandbox_launcher": "/opt/ic/bin/sandbox_launcher:0755", - "//publish/binaries:sevctl": "/opt/ic/bin/sevctl:0755", + "//publish/binaries:snptool": "/opt/ic/bin/snptool:0755", "@sevtool": "/opt/ic/bin/sevtool:0755", "//publish/binaries:state-tool": "/opt/ic/bin/state-tool:0755", "//publish/binaries:vsock_guest": "/opt/ic/bin/vsock_guest:0755", diff --git a/ic-os/guestos/rootfs/etc/initramfs-tools/modules b/ic-os/guestos/rootfs/etc/initramfs-tools/modules index badf49b7475..89203db7e89 100644 --- a/ic-os/guestos/rootfs/etc/initramfs-tools/modules +++ b/ic-os/guestos/rootfs/etc/initramfs-tools/modules @@ -1,2 +1,3 @@ virtio_blk dm_verity +sev_guest diff --git a/ic-os/guestos/rootfs/opt/ic/bin/setup-sev-certs.sh b/ic-os/guestos/rootfs/opt/ic/bin/setup-sev-certs.sh index fb867238a37..183a4cbbc6c 100755 --- a/ic-os/guestos/rootfs/opt/ic/bin/setup-sev-certs.sh +++ b/ic-os/guestos/rootfs/opt/ic/bin/setup-sev-certs.sh @@ -3,6 +3,9 @@ set -e if [[ -e "/dev/sev-guest" ]]; then + # Set permissions for sev-guest device + # TODO: This should move to guest_launch tool + chmod 777 /dev/sev-guest if [[ -f "/boot/config/vcek.pem" ]]; then # For prod we expect that the host will generate the ask and vcek certs and pass in via the config. if ! cmp -s "/boot/config/ark.pem" "/opt/ic/share/ark.pem"; then @@ -18,7 +21,7 @@ if [[ -e "/dev/sev-guest" ]]; then # config may be generated on a machine other than the host. ( cd /run/ic-node/config - /opt/ic/bin/sevctl get-certs + /opt/ic/bin/snptool get-certs ) if [[ -f "/run/ic-node/config/ask.cert" && -f "/run/ic-node/config/vcek.cert" ]]; then # Always use our hard coded ask.pem as the root of trust. diff --git a/publish/binaries/BUILD.bazel b/publish/binaries/BUILD.bazel index 2c560c6d079..3061ee223ab 100644 --- a/publish/binaries/BUILD.bazel +++ b/publish/binaries/BUILD.bazel @@ -3,7 +3,7 @@ load("//gitlab-ci/src/artifacts:upload.bzl", "upload_artifacts") load("//publish:defs.bzl", "release_nostrip_binary", "release_strip_binary") LINUX_ONLY = [ - "sevctl", + "snptool", "vsock_guest", "vsock_host", "guestos_tool", @@ -52,7 +52,7 @@ BINARIES = { "orchestrator": "//rs/orchestrator", "prometheus-config-updater": "//rs/observability/prometheus_config_updater:prometheus_config_updater", "sandbox_launcher": "//rs/canister_sandbox/sandbox_launcher", - "sevctl": "//rs/ic_os/sevctl:sevctl", + "snptool": "//rs/ic_os/snptool:snptool", "sns": "//rs/sns/cli:sns", "state-tool": "//rs/state_tool:state-tool", "systemd-journal-gatewayd-shim": "//rs/boundary_node/systemd_journal_gatewayd_shim:systemd-journal-gatewayd-shim", diff --git a/rs/ic_os/launch-single-vm/src/main.rs b/rs/ic_os/launch-single-vm/src/main.rs index 83206ad841e..d89f9688b06 100644 --- a/rs/ic_os/launch-single-vm/src/main.rs +++ b/rs/ic_os/launch-single-vm/src/main.rs @@ -128,7 +128,7 @@ fn main() { p2p_addr: SocketAddr::new(ipv6_addr, 4100), node_operator_principal_id: None, secret_key_store: None, - chip_id: vec![], + chip_id: None, }, )]); diff --git a/rs/ic_os/sev/BUILD.bazel b/rs/ic_os/sev/BUILD.bazel index 419801a65ea..2640d8e874a 100644 --- a/rs/ic_os/sev/BUILD.bazel +++ b/rs/ic_os/sev/BUILD.bazel @@ -37,5 +37,8 @@ rust_test( proc_macro_deps = [ "@crate_index//:async-trait", ], - deps = [":sev"], + deps = [ + ":sev", + "@crate_index//:assert_matches", + ], ) diff --git a/rs/ic_os/sev/Cargo.toml b/rs/ic_os/sev/Cargo.toml index 7466150d6a0..9d6d1fadb85 100644 --- a/rs/ic_os/sev/Cargo.toml +++ b/rs/ic_os/sev/Cargo.toml @@ -19,3 +19,6 @@ tokio = { workspace = true } openssl = "0.10.55" [target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies] sev = { version = "1.2.0", features = ["openssl"] } + +[dev-dependencies] +assert_matches = "1.5.0" diff --git a/rs/ic_os/sev/src/lib.rs b/rs/ic_os/sev/src/lib.rs index e11d8c6cff4..3f992b360df 100644 --- a/rs/ic_os/sev/src/lib.rs +++ b/rs/ic_os/sev/src/lib.rs @@ -5,5 +5,20 @@ mod linux_amd64; pub use linux_amd64::*; #[cfg(not(all(target_os = "linux", target_arch = "x86_64")))] mod other; +use core::fmt; #[cfg(not(all(target_os = "linux", target_arch = "x86_64")))] pub use other::*; +use std::fmt::{Display, Formatter}; + +#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)] +pub enum SnpError { + SnpNotEnabled { description: String }, + FirmwareError { description: String }, + ReportError { description: String }, +} + +impl Display for SnpError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} diff --git a/rs/ic_os/sev/src/linux_amd64.rs b/rs/ic_os/sev/src/linux_amd64.rs index 238d57b221d..3118e1856a6 100644 --- a/rs/ic_os/sev/src/linux_amd64.rs +++ b/rs/ic_os/sev/src/linux_amd64.rs @@ -2,9 +2,6 @@ References: https://github.com/virtee/sev - https://github.com/virtee/sevctl - https://github.com/AMDESE/sev-tool - https://github.com/AMDESE/sev-guest Convert: openssl::x509::X509::from_pem(pem_bytes) @@ -13,6 +10,7 @@ References: x509.to_pem() */ +use crate::SnpError; use async_trait::async_trait; use ic_base_types::{NodeId, RegistryVersion}; use ic_icos_sev_interfaces::{ValidateAttestationError, ValidateAttestedStream}; @@ -24,6 +22,7 @@ use serde::{Deserialize, Serialize}; use sev::firmware::guest::AttestationReport; use sha2::Digest; use std::fs; +use std::path::Path; use std::sync::Arc; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; @@ -132,7 +131,7 @@ where }); } let chip_id = transport_info.chip_id; - if chip_id.is_empty() { + if chip_id.is_none() { return Err(ValidateAttestationError::HandshakeError { description: "missing chip_id".into(), }); @@ -234,9 +233,10 @@ where description: "attestation report invalid".to_string(), }); } - if chip_id != peer_package.report.chip_id { + if chip_id != Some(peer_package.report.chip_id.to_vec()) { return Err(ValidateAttestationError::HandshakeError { - description: "chip_id mismatch".to_string(), + description: "Peer package chip_id does not match chip_id from registry" + .to_string(), }); } let peer_tls_cert_hash = peer_package.report.report_data; @@ -337,9 +337,33 @@ async fn read_into_buffer( } } +pub fn get_chip_id() -> Result, SnpError> { + // Check if /dev/sev-guest exists + let sev_guest_device = Path::new("/dev/sev-guest"); + if !sev_guest_device.exists() { + return Err(SnpError::SnpNotEnabled { + description: "/dev/sev-guest does not exist. Snp is not enabled on this Guest".into(), + }); + } + + let mut guest_firmware = + sev::firmware::guest::Firmware::open().map_err(|error| SnpError::FirmwareError { + description: format!("unable to open sev guest firmware: {}", error), + })?; + + let report = guest_firmware + .get_report(None, None, Some(0)) + .map_err(|error| SnpError::ReportError { + description: format!("unable to fetch snp report: {}", error), + })?; + + Ok(report.chip_id.to_vec()) +} + #[cfg(test)] mod test { use super::*; + use assert_matches::assert_matches; static ARK_PEM: &[u8] = include_bytes!("data/ark.pem"); static ASK_PEM: &[u8] = include_bytes!("data/ask_milan.pem"); @@ -377,4 +401,10 @@ mod test { let attestation_report = AttestationReport::default(); assert!(!is_report_valid(&attestation_report, &vcek)); } + + #[test] + fn test_get_chip_id_snp_not_enabled_fails() { + assert_matches!(get_chip_id(), Err(SnpError::SnpNotEnabled { description }) + if description.contains("Snp is not enabled on this Guest")); + } } diff --git a/rs/ic_os/sev/src/other.rs b/rs/ic_os/sev/src/other.rs index 699d57a8743..e64ef96ca11 100644 --- a/rs/ic_os/sev/src/other.rs +++ b/rs/ic_os/sev/src/other.rs @@ -1,3 +1,4 @@ +use crate::SnpError; use async_trait::async_trait; use ic_base_types::{NodeId, RegistryVersion}; use ic_icos_sev_interfaces::{ValidateAttestationError, ValidateAttestedStream}; @@ -27,3 +28,10 @@ where Ok(stream) } } + +/// For non linux version of guest, return None as +pub fn get_chip_id() -> Result, SnpError> { + Err(SnpError::SnpNotEnabled { + description: "Sev-snp is only available on linux".into(), + }) +} diff --git a/rs/ic_os/sevctl/BUILD.bazel b/rs/ic_os/snptool/BUILD.bazel similarity index 90% rename from rs/ic_os/sevctl/BUILD.bazel rename to rs/ic_os/snptool/BUILD.bazel index 2e0c20d7fe9..efe7563e180 100644 --- a/rs/ic_os/sevctl/BUILD.bazel +++ b/rs/ic_os/snptool/BUILD.bazel @@ -13,10 +13,10 @@ MACRO_DEPENDENCIES = [] ALIASES = {} rust_binary( - name = "sevctl", + name = "snptool", srcs = glob(["src/**/*.rs"]), aliases = ALIASES, - crate_name = "sevctl", + crate_name = "snptool", edition = "2021", proc_macro_deps = MACRO_DEPENDENCIES, target_compatible_with = [ diff --git a/rs/ic_os/sevctl/Cargo.toml b/rs/ic_os/snptool/Cargo.toml similarity index 81% rename from rs/ic_os/sevctl/Cargo.toml rename to rs/ic_os/snptool/Cargo.toml index 6584d04cb0c..95628117811 100644 --- a/rs/ic_os/sevctl/Cargo.toml +++ b/rs/ic_os/snptool/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sevctl" +name = "snptool" version = "0.1.0" authors = ["DFINITY"] edition = "2021" @@ -8,11 +8,11 @@ keywords = ["amd", "sev"] exclude = [ ".gitignore", ".github/*" ] [[bin]] -name = "sevctl" +name = "snptool" path = "src/main.rs" [dependencies] anyhow = "1.0.57" clap = { version = "3.1.18", features = ["derive", "cargo"] } [target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies] -sev = { version = "1.2.0", features = ["openssl"] } +sev = { version = "1.2.1", features = ["openssl"] } diff --git a/rs/ic_os/sevctl/src/main.rs b/rs/ic_os/snptool/src/main.rs similarity index 97% rename from rs/ic_os/sevctl/src/main.rs rename to rs/ic_os/snptool/src/main.rs index 979088a0ddc..4b4805646ec 100644 --- a/rs/ic_os/sevctl/src/main.rs +++ b/rs/ic_os/snptool/src/main.rs @@ -102,7 +102,7 @@ mod linux { guest_firmware()? .get_ext_report(None, None, Some(0)) .map_err(|e| anyhow::anyhow!(format!("{:?}", e))) - .context("unable to fetch snp report") + .context("unable to fetch extended snp report") } fn snp_get_ext_config() -> Result { @@ -120,5 +120,5 @@ fn main() -> anyhow::Result<()> { #[cfg(not(target_os = "linux"))] fn main() { - panic!("sevctl works only on Linux"); + panic!("sev-snp works only on Linux"); } diff --git a/rs/nns/test_utils/src/registry.rs b/rs/nns/test_utils/src/registry.rs index 2b3ab0ad393..54f57e9cb9d 100644 --- a/rs/nns/test_utils/src/registry.rs +++ b/rs/nns/test_utils/src/registry.rs @@ -115,7 +115,7 @@ pub async fn get_value(registry: &Canister<'_>, key: &[u8] } /// Gets the latest value for the given key and decode it, assuming it -/// represents a serialized T. +/// represents a serialized T. /// /// Panics if there is no T pub async fn get_value_or_panic(registry: &Canister<'_>, key: &[u8]) -> T { @@ -701,6 +701,7 @@ pub fn prepare_add_node_payload(mutation_id: u8) -> (AddNodePayload, ValidNodePu http_endpoint: format!("128.0.{mutation_id}.1:4321"), p2p_flow_endpoints: vec![], prometheus_metrics_endpoint: "".to_string(), + chip_id: None, }; (payload, node_public_keys) diff --git a/rs/orchestrator/BUILD.bazel b/rs/orchestrator/BUILD.bazel index e0033f9bd1a..d259e5618af 100644 --- a/rs/orchestrator/BUILD.bazel +++ b/rs/orchestrator/BUILD.bazel @@ -25,6 +25,7 @@ rust_library( "//rs/crypto/tls_interfaces", "//rs/http_endpoints/metrics", "//rs/http_utils", + "//rs/ic_os/sev", "//rs/interfaces", "//rs/interfaces/registry", "//rs/monitoring/logger", diff --git a/rs/orchestrator/Cargo.toml b/rs/orchestrator/Cargo.toml index f3efb6fe94a..41422f7ba73 100644 --- a/rs/orchestrator/Cargo.toml +++ b/rs/orchestrator/Cargo.toml @@ -20,6 +20,7 @@ ic-crypto-tls-interfaces = { path = "../crypto/tls_interfaces" } ic-dashboard = { path = "./dashboard" } ic-http-utils = { path = "../http_utils" } ic-ic00-types = { path = "../types/ic00_types" } +ic-icos-sev = { path = "../ic_os/sev"} ic-image-upgrader = { path = "./image_upgrader" } ic-interfaces = { path = "../interfaces" } ic-interfaces-registry = { path = "../interfaces/registry" } diff --git a/rs/orchestrator/src/error.rs b/rs/orchestrator/src/error.rs index 5b058a02795..3b5b39f7b25 100644 --- a/rs/orchestrator/src/error.rs +++ b/rs/orchestrator/src/error.rs @@ -54,6 +54,9 @@ pub enum OrchestratorError { /// Generic error while monitoring key changes ThresholdKeyMonitoringError(String), + + /// SNP error while registering a SEV-SNP node + SnpError(String), } impl OrchestratorError { @@ -68,6 +71,10 @@ impl OrchestratorError { pub(crate) fn key_monitoring_error(msg: impl ToString) -> Self { OrchestratorError::ThresholdKeyMonitoringError(msg.to_string()) } + + pub(crate) fn snp_error(msg: impl ToString) -> Self { + OrchestratorError::SnpError(msg.to_string()) + } } impl fmt::Display for OrchestratorError { @@ -122,6 +129,7 @@ impl fmt::Display for OrchestratorError { subnet_id, registry_version, ), OrchestratorError::UpgradeError(msg) => write!(f, "Failed to upgrade: {}", msg), + OrchestratorError::SnpError(msg) => write!(f, "SEV-SNP Error: {}", msg), } } } diff --git a/rs/orchestrator/src/registration.rs b/rs/orchestrator/src/registration.rs index 51a406de684..8ef11d437e8 100644 --- a/rs/orchestrator/src/registration.rs +++ b/rs/orchestrator/src/registration.rs @@ -14,6 +14,7 @@ use ic_config::{ Config, }; use ic_crypto::CryptoComponentForNonReplicaProcess; +use ic_icos_sev::{get_chip_id, SnpError}; use ic_interfaces::crypto::IDkgKeyRotationResult; use ic_interfaces_registry::RegistryClient; use ic_logger::{info, warn, ReplicaLogger}; @@ -194,6 +195,7 @@ impl NodeRegistration { http_endpoint: http_config_to_endpoint(&self.log, &self.node_config.http_handler) .expect("Invalid endpoints in http handler config."), p2p_flow_endpoints: vec![], + chip_id: get_snp_chip_id().expect("Failed to retrieve chip_id from snp firmware"), prometheus_metrics_endpoint: "".to_string(), } } @@ -628,6 +630,27 @@ fn generate_nonce() -> Vec { .to_vec() } +/// Get a chip_id from SNP guest firmware by calling the snptool. +/// If snptool returns the error "unable to open /dev/sev-guest", +/// it could be that the guest is not SEV-SNP enabled. Return an empty chip_id in that case. +fn get_snp_chip_id() -> OrchestratorResult>> { + match get_chip_id() { + // Chip_id returned successfully + Ok(chip_id) => Ok(Some(chip_id)), + // Snp is not enabled on the Guest, return None + Err(SnpError::SnpNotEnabled { .. }) => Ok(None), + // Propagate any other error + Err(error) => { + let snp_error = format!( + "Failed to retrieve chip_id from snp firmware, error: {}", + error + ); + UtilityCommand::notify_host(&snp_error, 1); + Err(OrchestratorError::snp_error(snp_error)) + } + } +} + fn protobuf_to_vec(entry: M) -> Vec { let mut buf: Vec = Vec::new(); entry.encode(&mut buf).expect("This must not fail"); diff --git a/rs/prep/src/bin/prep.rs b/rs/prep/src/bin/prep.rs index 2190f40e3fc..d3776ddf873 100644 --- a/rs/prep/src/bin/prep.rs +++ b/rs/prep/src/bin/prep.rs @@ -502,7 +502,7 @@ mod test_flag_node_parser { p2p_addr: "1.2.3.4:80".parse().unwrap(), node_operator_principal_id: None, secret_key_store: None, - chip_id: vec![], + chip_id: None, }, }; diff --git a/rs/prep/src/node.rs b/rs/prep/src/node.rs index d360c7e864d..9b51339e0b4 100644 --- a/rs/prep/src/node.rs +++ b/rs/prep/src/node.rs @@ -248,8 +248,8 @@ pub struct NodeConfiguration { pub secret_key_store: Option, /// The SEV-SNP chip_identifier for this node. - #[serde(skip_serializing_if = "Vec::is_empty", default)] - pub chip_id: Vec, + #[serde(skip_serializing_if = "Option::is_none", default)] + pub chip_id: Option>, } impl From for pbNodeRecord { @@ -395,7 +395,7 @@ mod node_configuration { p2p_addr: SocketAddr::from_str("1.2.3.4:1234").unwrap(), node_operator_principal_id: None, secret_key_store: None, - chip_id: vec![], + chip_id: None, }; let got = pbNodeRecord::try_from(node_configuration).unwrap(); @@ -416,8 +416,8 @@ mod node_configuration { ip_addr: "1.2.3.4".to_string(), port: 8080, }), - chip_id: vec![], hostos_version_id: None, + chip_id: None, }; assert_eq!(got, want); diff --git a/rs/prep/src/prep_state_directory.rs b/rs/prep/src/prep_state_directory.rs index fd8a9b1621f..1b5fe9d58f8 100755 --- a/rs/prep/src/prep_state_directory.rs +++ b/rs/prep/src/prep_state_directory.rs @@ -128,7 +128,7 @@ mod tests { p2p_addr: SocketAddr::from_str("1.2.3.4:1234").unwrap(), node_operator_principal_id: None, secret_key_store: None, - chip_id: vec![], + chip_id: None, }, ); diff --git a/rs/protobuf/def/registry/node/v1/node.proto b/rs/protobuf/def/registry/node/v1/node.proto index f91d9928a7d..4a3731c65bf 100644 --- a/rs/protobuf/def/registry/node/v1/node.proto +++ b/rs/protobuf/def/registry/node/v1/node.proto @@ -58,7 +58,7 @@ message NodeRecord { bytes node_operator_id = 15; // The SEV-SNP chip_identifier for this node. - bytes chip_id = 16; + optional bytes chip_id = 16; // ID of the HostOS version to run. optional string hostos_version_id = 17; diff --git a/rs/protobuf/src/gen/registry/registry.node.v1.rs b/rs/protobuf/src/gen/registry/registry.node.v1.rs index ba3767183f6..ac179f260a2 100644 --- a/rs/protobuf/src/gen/registry/registry.node.v1.rs +++ b/rs/protobuf/src/gen/registry/registry.node.v1.rs @@ -41,8 +41,8 @@ pub struct NodeRecord { #[prost(bytes = "vec", tag = "15")] pub node_operator_id: ::prost::alloc::vec::Vec, /// The SEV-SNP chip_identifier for this node. - #[prost(bytes = "vec", tag = "16")] - pub chip_id: ::prost::alloc::vec::Vec, + #[prost(bytes = "vec", optional, tag = "16")] + pub chip_id: ::core::option::Option<::prost::alloc::vec::Vec>, /// ID of the HostOS version to run. #[prost(string, optional, tag = "17")] pub hostos_version_id: ::core::option::Option<::prost::alloc::string::String>, diff --git a/rs/registry/canister/canister/registry.did b/rs/registry/canister/canister/registry.did index 92d7751ab65..ba3d0e9b851 100644 --- a/rs/registry/canister/canister/registry.did +++ b/rs/registry/canister/canister/registry.did @@ -22,6 +22,7 @@ type AddNodePayload = record { http_endpoint : text; idkg_dealing_encryption_pk : opt vec nat8; xnet_endpoint : text; + chip_id : opt vec nat8; committee_signing_pk : vec nat8; node_signing_pk : vec nat8; transport_tls_cert : vec nat8; diff --git a/rs/registry/canister/src/invariants/endpoint.rs b/rs/registry/canister/src/invariants/endpoint.rs index 82fe8682ece..291ba8d8c16 100644 --- a/rs/registry/canister/src/invariants/endpoint.rs +++ b/rs/registry/canister/src/invariants/endpoint.rs @@ -423,8 +423,8 @@ mod tests { ip_addr: "200.1.1.3".to_string(), port: 9001, }), - chip_id: vec![], hostos_version_id: None, + chip_id: None, }), ); @@ -451,8 +451,8 @@ mod tests { ip_addr: "200.1.1.1".to_string(), port: 9001, }), - chip_id: vec![], hostos_version_id: None, + chip_id: None, }), ); // TODO: change to `assert!(check_endpoint_invariants(&snapshot, true).is_err());` after NNS1-2228 is closed. @@ -481,8 +481,8 @@ mod tests { ip_addr: "200.1.1.2".to_string(), port: 9001, }), - chip_id: vec![], hostos_version_id: None, + chip_id: None, }), ); check_endpoint_invariants(&snapshot, true).unwrap(); diff --git a/rs/registry/canister/src/invariants/firewall.rs b/rs/registry/canister/src/invariants/firewall.rs index 1e87a220c1e..3029acef761 100644 --- a/rs/registry/canister/src/invariants/firewall.rs +++ b/rs/registry/canister/src/invariants/firewall.rs @@ -326,8 +326,8 @@ mod tests { xnet: None, http: None, p2p_flow_endpoints: vec![], - chip_id: vec![], hostos_version_id: None, + chip_id: None, } } diff --git a/rs/registry/canister/src/mutations/node_management/do_add_node.rs b/rs/registry/canister/src/mutations/node_management/do_add_node.rs index 5e25ab89fac..d798a587548 100644 --- a/rs/registry/canister/src/mutations/node_management/do_add_node.rs +++ b/rs/registry/canister/src/mutations/node_management/do_add_node.rs @@ -87,8 +87,8 @@ impl Registry { endpoint: Some(p2p_endpoint), }], node_operator_id: caller.into_vec(), - chip_id: vec![], hostos_version_id: None, + chip_id: payload.chip_id.clone(), }; // 6. Insert node, public keys, and crypto keys @@ -127,6 +127,7 @@ pub struct AddNodePayload { pub xnet_endpoint: String, pub http_endpoint: String, + pub chip_id: Option>, // TODO(NNS1-2444): The fields below are deprecated and they are not read anywhere. pub p2p_flow_endpoints: Vec, pub prometheus_metrics_endpoint: String, @@ -298,6 +299,7 @@ mod tests { http_endpoint: "127.0.0.1:8123".to_string(), p2p_flow_endpoints: vec![], prometheus_metrics_endpoint: "".to_string(), + chip_id: None, }; } diff --git a/rs/registry/helpers/src/firewall.rs b/rs/registry/helpers/src/firewall.rs index 54f5fdf5d91..4a3f315823b 100644 --- a/rs/registry/helpers/src/firewall.rs +++ b/rs/registry/helpers/src/firewall.rs @@ -162,8 +162,8 @@ mod tests { port: 2457, }), node_operator_id: vec![], - chip_id: vec![], hostos_version_id: None, + chip_id: None, }, ) }) diff --git a/rs/registry/regedit/src/tests.rs b/rs/registry/regedit/src/tests.rs index c85d0859642..79ff2e8263f 100644 --- a/rs/registry/regedit/src/tests.rs +++ b/rs/registry/regedit/src/tests.rs @@ -134,7 +134,7 @@ pub fn run_ic_prep() -> (TempDir, IcPrepStateDir) { p2p_addr: SocketAddr::from_str("0.0.0.0:0").unwrap(), node_operator_principal_id: None, secret_key_store: None, - chip_id: vec![], + chip_id: None, }, ); diff --git a/rs/replica_tests/src/lib.rs b/rs/replica_tests/src/lib.rs index bf2e7d77615..b72f708adbc 100644 --- a/rs/replica_tests/src/lib.rs +++ b/rs/replica_tests/src/lib.rs @@ -223,7 +223,7 @@ pub fn get_ic_config() -> IcConfig { p2p_addr: SocketAddr::from_str("128.0.0.1:100").expect("can't fail"), node_operator_principal_id: None, secret_key_store: Some(node_sks), - chip_id: vec![], + chip_id: None, }, ); diff --git a/rs/starter/src/main.rs b/rs/starter/src/main.rs index 6bc680e39a6..6782fc30098 100644 --- a/rs/starter/src/main.rs +++ b/rs/starter/src/main.rs @@ -95,7 +95,7 @@ fn main() -> Result<()> { p2p_addr: SocketAddr::from_str("0.0.0.0:0").unwrap(), node_operator_principal_id: None, secret_key_store: None, - chip_id: vec![], + chip_id: None, }, ); diff --git a/rs/state_machine_tests/src/lib.rs b/rs/state_machine_tests/src/lib.rs index 4dba58e4043..a4a9d827a28 100644 --- a/rs/state_machine_tests/src/lib.rs +++ b/rs/state_machine_tests/src/lib.rs @@ -205,8 +205,8 @@ fn make_nodes_registry( port: 1234, }), p2p_flow_endpoints: vec![], - chip_id: vec![], hostos_version_id: None, + chip_id: None, }; data_provider .add( diff --git a/rs/tests/src/driver/bootstrap.rs b/rs/tests/src/driver/bootstrap.rs index 413fc25b6ec..03cac3b11dd 100644 --- a/rs/tests/src/driver/bootstrap.rs +++ b/rs/tests/src/driver/bootstrap.rs @@ -407,6 +407,6 @@ fn node_to_config(node: &Node) -> NodeConfiguration { // this value will be overridden by IcConfig::with_node_operator() node_operator_principal_id: None, secret_key_store: node.secret_key_store.clone(), - chip_id: vec![], + chip_id: None, } }