diff --git a/hipcheck/build.rs b/hipcheck/build.rs index 0391c0e..38e64f3 100644 --- a/hipcheck/build.rs +++ b/hipcheck/build.rs @@ -5,8 +5,18 @@ use pathbuf::pathbuf; use tonic_build::compile_protos; fn main() -> Result<()> { + // Compile the Hipcheck gRPC protocol spec to an .rs file let root = env!("CARGO_MANIFEST_DIR"); let path = pathbuf![root, "proto", "hipcheck", "v1", "hipcheck.proto"]; compile_protos(path)?; + + // Make the target available as a compile-time env var for plugin arch + // resolution + println!( + "cargo:rustc-env=TARGET={}", + std::env::var("TARGET").unwrap() + ); + println!("cargo:rerun-if-changed-env=TARGET"); + Ok(()) } diff --git a/hipcheck/src/engine.rs b/hipcheck/src/engine.rs index 1e5a95e..8a73038 100644 --- a/hipcheck/src/engine.rs +++ b/hipcheck/src/engine.rs @@ -5,8 +5,8 @@ use crate::{ cache::plugin::HcPluginCache, hc_error, plugin::{ - get_plugin_key, retrieve_plugins, try_get_current_arch, Plugin, PluginManifest, - PluginResponse, QueryResult, + get_current_arch, get_plugin_key, retrieve_plugins, Plugin, PluginManifest, PluginResponse, + QueryResult, }, policy::PolicyFile, util::fs::{find_file_by_name, read_string}, @@ -230,7 +230,7 @@ pub fn start_plugins( /* jitter_percent */ 10, )?; - let current_arch = try_get_current_arch()?; + let current_arch = get_current_arch(); println!("CURRENT ARCH: {}", current_arch); // retrieve, verify and extract all required plugins diff --git a/hipcheck/src/plugin/arch.rs b/hipcheck/src/plugin/arch.rs index 1ef8836..a86d85d 100644 --- a/hipcheck/src/plugin/arch.rs +++ b/hipcheck/src/plugin/arch.rs @@ -28,6 +28,8 @@ pub enum Arch { Unknown(String), } +pub const DETECTED_ARCH_STR: &str = env!("TARGET"); + pub const DETECTED_ARCH: Option = { if cfg!(target_arch = "x86_64") { if cfg!(target_os = "macos") { @@ -57,23 +59,13 @@ pub static USER_PROVIDED_ARCH: OnceLock = OnceLock::new(); /// Get the target architecture for plugins. If the user provided a target, /// return that. Otherwise, if the `hc` binary was compiled for a supported /// architecture, return that. Otherwise return None. -pub fn get_current_arch() -> Option { +pub fn get_current_arch() -> Arch { if let Some(arch) = USER_PROVIDED_ARCH.get() { - Some(arch.clone()) + arch.clone() } else if let Some(known_arch) = DETECTED_ARCH { - Some(Arch::Known(known_arch)) - } else { - None - } -} - -/// Like `get_current_arch()`, but returns an error message suggesting the -/// user specifies a target on the CLI -pub fn try_get_current_arch() -> Result { - if let Some(arch) = get_current_arch() { - Ok(arch) + Arch::Known(known_arch) } else { - Err(hc_error!("Could not resolve the current machine to one of the Hipcheck known architectures. Please specify --arch on the commandline.")) + Arch::Unknown(DETECTED_ARCH_STR.to_owned()) } } diff --git a/hipcheck/src/plugin/download_manifest.rs b/hipcheck/src/plugin/download_manifest.rs index f4aee4e..f5d210c 100644 --- a/hipcheck/src/plugin/download_manifest.rs +++ b/hipcheck/src/plugin/download_manifest.rs @@ -6,9 +6,9 @@ use crate::{ error::Error, hc_error, plugin::{ + arch::Arch, + get_current_arch, retrieval::{download_plugin, extract_plugin}, - arch::KnownArch, - try_get_current_arch, }, util::kdl::{extract_data, ParseKdlNode}, util::{ @@ -21,6 +21,9 @@ use kdl::{KdlDocument, KdlNode, KdlValue}; use std::{collections::HashSet, fmt::Display, io::Read, str::FromStr}; use url::Url; +#[cfg(test)] +use crate::plugin::arch::KnownArch; + // NOTE: the implementation in this crate was largely derived from RFD #0004 impl ParseKdlNode for url::Url { @@ -225,7 +228,7 @@ pub struct DownloadManifestEntry { /// but only a specific concrete version pub version: PluginVersion, /// The target architecture for a plugin - pub arch: KnownArch, + pub arch: Arch, /// The URL of the archive file to download containing the plugin executable artifact and /// plugin manifest. pub url: url::Url, @@ -251,7 +254,7 @@ impl ParseKdlNode for DownloadManifestEntry { // Per RFD #0004, version is of type String let version = PluginVersion(node.get("version")?.value().as_string()?.to_string()); // Per RFD #0004, arch is of type String - let arch = KnownArch::from_str(node.get("arch")?.value().as_string()?).ok()?; + let arch = Arch::from_str(node.get("arch")?.value().as_string()?).ok()?; // there should be one child for each plugin and it should contain the url, hash, compress // and size information @@ -288,7 +291,7 @@ impl DownloadManifestEntry { version: &PluginVersion, downloaded_plugins: &'a mut HashSet, ) -> Result<&'a HashSet, Error> { - let current_arch = try_get_current_arch()?; + let current_arch = get_current_arch(); let plugin_id = PluginId::new(publisher.clone(), name.clone(), version.clone()); @@ -564,7 +567,7 @@ mod test { let expected_entry = DownloadManifestEntry { version: PluginVersion(version.to_string()), - arch: KnownArch::from_str(arch).unwrap(), + arch: Arch::Known(KnownArch::from_str(arch).unwrap()), url: Url::parse(url).unwrap(), hash: HashWithDigest::new( HashAlgorithm::try_from(hash_alg).unwrap(), @@ -605,7 +608,7 @@ plugin version="0.1.0" arch="x86_64-apple-darwin" { assert_eq!( &DownloadManifestEntry { version: PluginVersion("0.1.0".to_owned()), - arch: KnownArch::Aarch64AppleDarwin, + arch: Arch::Known(KnownArch::Aarch64AppleDarwin), url: Url::parse("https://github.com/mitre/hipcheck/releases/download/hipcheck-v3.4.0/hipcheck-aarch64-apple-darwin.tar.xz").unwrap(), hash: HashWithDigest::new(HashAlgorithm::Sha256, "b8e111e7817c4a1eb40ed50712d04e15b369546c4748be1aa8893b553f4e756b".to_owned()), compress: Compress::new(ArchiveFormat::TarXz), @@ -618,7 +621,7 @@ plugin version="0.1.0" arch="x86_64-apple-darwin" { assert_eq!( &DownloadManifestEntry { version: PluginVersion("0.1.0".to_owned()), - arch: KnownArch::X86_64AppleDarwin, + arch: Arch::Known(KnownArch::X86_64AppleDarwin), url: Url::parse("https://github.com/mitre/hipcheck/releases/download/hipcheck-v3.4.0/hipcheck-x86_64-apple-darwin.tar.xz").unwrap(), hash: HashWithDigest::new(HashAlgorithm::Sha256, "ddb8c6d26dd9a91e11c99b3bd7ee2b9585aedac6e6df614190f1ba2bfe86dc19".to_owned()), compress: Compress::new(ArchiveFormat::TarXz), diff --git a/hipcheck/src/plugin/mod.rs b/hipcheck/src/plugin/mod.rs index 8538046..c17e20b 100644 --- a/hipcheck/src/plugin/mod.rs +++ b/hipcheck/src/plugin/mod.rs @@ -1,21 +1,21 @@ // SPDX-License-Identifier: Apache-2.0 +mod arch; mod download_manifest; mod manager; mod plugin_id; mod plugin_manifest; mod retrieval; -mod arch; mod types; use crate::error::Result; pub use crate::plugin::{get_plugin_key, manager::*, plugin_id::PluginId, types::*}; +pub use arch::{get_current_arch, try_set_arch, Arch}; pub use download_manifest::{ArchiveFormat, DownloadManifest, HashAlgorithm, HashWithDigest}; pub use plugin_manifest::{PluginManifest, PluginName, PluginPublisher, PluginVersion}; pub use retrieval::retrieve_plugins; use serde_json::Value; use std::collections::HashMap; -pub use arch::{try_get_current_arch, try_set_arch, Arch}; use tokio::sync::Mutex; pub async fn initialize_plugins(