diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index e87c24e308..e80742b740 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -3020,6 +3020,7 @@ dependencies = [ "image-rs", "ipnetwork", "json-patch", + "kata-agent-policy", "kata-sys-util", "kata-types", "lazy_static", @@ -3069,6 +3070,23 @@ dependencies = [ "which", ] +[[package]] +name = "kata-agent-policy" +version = "0.1.0" +dependencies = [ + "anyhow", + "json-patch", + "logging", + "regorus", + "serde", + "serde_json", + "slog", + "slog-scope", + "slog-term", + "tokio", + "tokio-vsock 0.3.4", +] + [[package]] name = "kata-sys-util" version = "0.1.0" diff --git a/src/agent/Cargo.toml b/src/agent/Cargo.toml index 20737f60c6..d06c52b105 100644 --- a/src/agent/Cargo.toml +++ b/src/agent/Cargo.toml @@ -88,6 +88,7 @@ regorus = { version = "0.2.6", default-features = false, features = [ ], optional = true } cdi = { git = "https://github.com/cncf-tags/container-device-interface-rs", rev = "fba5677a8e7cc962fc6e495fcec98d7d765e332a" } json-patch = "2.0.0" +kata-agent-policy = { path = "policy" } [dev-dependencies] tempfile = "3.1.0" @@ -97,7 +98,7 @@ rstest = "0.18.0" async-std = { version = "1.12.0", features = ["attributes"] } [workspace] -members = ["rustjail"] +members = ["rustjail", "policy"] [profile.release] lto = true diff --git a/src/agent/policy/Cargo.toml b/src/agent/policy/Cargo.toml new file mode 100644 index 0000000000..4bf98fb192 --- /dev/null +++ b/src/agent/policy/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "kata-agent-policy" +version = "0.1.0" +authors = ["The Kata Containers community "] +edition = "2018" +license = "Apache-2.0" + +[dependencies] +# Async runtime +tokio = { version = "1.39.0", features = ["full"] } +tokio-vsock = "0.3.4" + +anyhow = "1" + +# Configuration +serde = { version = "1.0.129", features = ["derive"] } +serde_json = "1.0.39" + +# Agent Policy +regorus = { version = "0.2.8", default-features = false, features = [ + "arc", + "regex", + "std", +] } +json-patch = "2.0.0" + + +# Note: this crate sets the slog 'max_*' features which allows the log level +# to be modified at runtime. +logging = { path = "../../libs/logging" } +slog = "2.5.2" +slog-scope = "4.1.2" +slog-term = "2.9.0" diff --git a/src/agent/policy/src/lib.rs b/src/agent/policy/src/lib.rs new file mode 100644 index 0000000000..994f67969e --- /dev/null +++ b/src/agent/policy/src/lib.rs @@ -0,0 +1,6 @@ +// Copyright (c) 2024 Edgeless Systems GmbH +// +// SPDX-License-Identifier: Apache-2.0 +// + +pub mod policy; diff --git a/src/agent/policy/src/policy.rs b/src/agent/policy/src/policy.rs new file mode 100644 index 0000000000..34f1073853 --- /dev/null +++ b/src/agent/policy/src/policy.rs @@ -0,0 +1,243 @@ +// Copyright (c) 2023 Microsoft Corporation +// Copyright (c) 2024 Edgeless Systems GmbH +// +// SPDX-License-Identifier: Apache-2.0 +// + +//! Policy evaluation for the kata-agent. + +use anyhow::{bail, Result}; +use slog::{debug, error, info, warn}; +use tokio::io::AsyncWriteExt; + +static POLICY_LOG_FILE: &str = "/tmp/policy.txt"; +static POLICY_DEFAULT_FILE: &str = "/etc/kata-opa/default-policy.rego"; + +/// Convenience macro to obtain the scope logger +macro_rules! sl { + () => { + slog_scope::logger() + }; +} + +/// Singleton policy object. +#[derive(Debug, Default)] +pub struct AgentPolicy { + /// When true policy errors are ignored, for debug purposes. + allow_failures: bool, + + /// "/tmp/policy.txt" log file for policy activity. + log_file: Option, + + /// Regorus engine + engine: regorus::Engine, +} + +#[derive(serde::Deserialize, Debug)] +struct MetadataResponse { + allowed: bool, + ops: Option, +} + +impl AgentPolicy { + /// Create AgentPolicy object. + pub fn new() -> Self { + Self { + allow_failures: false, + engine: Self::new_engine(), + ..Default::default() + } + } + + fn new_engine() -> regorus::Engine { + let mut engine = regorus::Engine::new(); + engine.set_strict_builtin_errors(false); + engine.set_gather_prints(true); + // assign a slice of the engine data "pstate" to be used as policy state + engine + .add_data( + regorus::Value::from_json_str( + r#"{ + "pstate": {} + }"#, + ) + .unwrap(), + ) + .unwrap(); + engine + } + + /// Initialize regorus. + pub async fn initialize( + &mut self, + log_level: usize, + default_policy_file: String, + log_file: Option, + ) -> Result<()> { + // log file path + let log_file_path = match log_file { + Some(path) => path, + None => POLICY_LOG_FILE.to_string(), + }; + let log_file_path = log_file_path.as_str(); + + if log_level >= slog::Level::Debug.as_usize() { + self.log_file = Some( + tokio::fs::OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(&log_file_path) + .await?, + ); + debug!(sl!(), "policy: log file: {}", log_file_path); + } + + // Check if policy file has been set via AgentConfig + // If empty, use default file. + let mut default_policy_file = default_policy_file; + if default_policy_file.is_empty() { + default_policy_file = POLICY_DEFAULT_FILE.to_string(); + } + info!(sl!(), "default policy: {default_policy_file}"); + + self.engine.add_policy_from_file(default_policy_file)?; + self.update_allow_failures_flag().await?; + Ok(()) + } + + async fn apply_patch_to_state(&mut self, patch: json_patch::Patch) -> Result<()> { + // Convert the current engine data to a JSON value + let mut state = serde_json::to_value(self.engine.get_data())?; + + // Apply the patch to the state + json_patch::patch(&mut state, &patch)?; + + // Clear the existing data in the engine + self.engine.clear_data(); + + // Add the patched state back to the engine + self.engine + .add_data(regorus::Value::from_json_str(&state.to_string())?)?; + + Ok(()) + } + + /// Ask regorus if an API call should be allowed or not. + pub async fn allow_request(&mut self, ep: &str, ep_input: &str) -> Result<(bool, String)> { + debug!(sl!(), "policy check: {ep}"); + self.log_eval_input(ep, ep_input).await; + + let query = format!("data.agent_policy.{ep}"); + self.engine.set_input_json(ep_input)?; + + let results = self.engine.eval_query(query, false)?; + + let prints = match self.engine.take_prints() { + Ok(p) => p.join(" "), + Err(e) => format!("Failed to get policy log: {e}"), + }; + + if results.result.len() != 1 { + // Results are empty when AllowRequestsFailingPolicy is used to allow a Request that hasn't been defined in the policy + if self.allow_failures { + return Ok((true, prints)); + } + bail!( + "policy check: unexpected eval_query result len {:?}", + results + ); + } + + if results.result[0].expressions.len() != 1 { + bail!( + "policy check: unexpected eval_query result expressions {:?}", + results + ); + } + + let mut allow = match &results.result[0].expressions[0].value { + regorus::Value::Bool(b) => *b, + + // Match against a specific variant that could be interpreted as MetadataResponse + regorus::Value::Object(obj) => { + let json_str = serde_json::to_string(obj)?; + + self.log_eval_input(ep, &json_str).await; + + let metadata_response: MetadataResponse = serde_json::from_str(&json_str)?; + + if metadata_response.allowed { + if let Some(ops) = metadata_response.ops { + self.apply_patch_to_state(ops).await?; + } + } + metadata_response.allowed + } + + _ => { + error!(sl!(), "allow_request: unexpected eval_query result type"); + bail!( + "policy check: unexpected eval_query result type {:?}", + results + ); + } + }; + + if !allow && self.allow_failures { + warn!(sl!(), "policy: ignoring error for {ep}"); + allow = true; + } + + Ok((allow, prints)) + } + + /// Replace the Policy in regorus. + pub async fn set_policy(&mut self, policy: &str) -> Result<()> { + self.engine = Self::new_engine(); + self.engine + .add_policy("agent_policy".to_string(), policy.to_string())?; + self.update_allow_failures_flag().await?; + Ok(()) + } + + async fn log_eval_input(&mut self, ep: &str, input: &str) { + if let Some(log_file) = &mut self.log_file { + match ep { + "StatsContainerRequest" | "ReadStreamRequest" | "SetPolicyRequest" => { + // - StatsContainerRequest and ReadStreamRequest are called + // relatively often, so we're not logging them, to avoid + // growing this log file too much. + // - Confidential Containers Policy documents are relatively + // large, so we're not logging them here, for SetPolicyRequest. + // The Policy text can be obtained directly from the pod YAML. + } + _ => { + let log_entry = format!("[\"ep\":\"{ep}\",{input}],\n\n"); + + if let Err(e) = log_file.write_all(log_entry.as_bytes()).await { + warn!(sl!(), "policy: log_eval_input: write_all failed: {}", e); + } else if let Err(e) = log_file.flush().await { + warn!(sl!(), "policy: log_eval_input: flush failed: {}", e); + } + } + } + } + } + + async fn update_allow_failures_flag(&mut self) -> Result<()> { + self.allow_failures = match self.allow_request("AllowRequestsFailingPolicy", "{}").await { + Ok((allowed, _prints)) => { + if allowed { + warn!( + sl!(), + "policy: AllowRequestsFailingPolicy is enabled - will ignore errors" + ); + } + allowed + } + Err(_) => false, + }; + Ok(()) + } +} diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index f8a1a24da2..2e7698706c 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -134,7 +134,7 @@ lazy_static! { #[cfg(feature = "agent-policy")] lazy_static! { - static ref AGENT_POLICY: Mutex = Mutex::new(AgentPolicy::new()); + static ref AGENT_POLICY: Mutex = Mutex::new(AgentPolicy::new()); } #[derive(Parser)] @@ -633,7 +633,15 @@ fn init_agent_as_init(logger: &Logger, unified_cgroup_hierarchy: bool) -> Result #[cfg(feature = "agent-policy")] async fn initialize_policy() -> Result<()> { - AGENT_POLICY.lock().await.initialize().await + AGENT_POLICY + .lock() + .await + .initialize( + AGENT_CONFIG.log_level.as_usize(), + AGENT_CONFIG.policy_file.clone(), + None, + ) + .await } // The Rust standard library had suppressed the default SIGPIPE behavior, @@ -651,7 +659,7 @@ use crate::config::AgentConfig; use std::os::unix::io::{FromRawFd, RawFd}; #[cfg(feature = "agent-policy")] -use crate::policy::AgentPolicy; +use kata_agent_policy::policy::AgentPolicy; #[cfg(test)] mod tests { diff --git a/src/agent/src/policy.rs b/src/agent/src/policy.rs index 08587a6d03..1b8f391c0b 100644 --- a/src/agent/src/policy.rs +++ b/src/agent/src/policy.rs @@ -3,22 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 // -use anyhow::{bail, Result}; use protobuf::MessageDyn; -use tokio::io::AsyncWriteExt; use crate::rpc::ttrpc_error; -use crate::{AGENT_CONFIG, AGENT_POLICY}; - -static POLICY_LOG_FILE: &str = "/tmp/policy.txt"; -static POLICY_DEFAULT_FILE: &str = "/etc/kata-opa/default-policy.rego"; - -/// Convenience macro to obtain the scope logger -macro_rules! sl { - () => { - slog_scope::logger() - }; -} +use crate::AGENT_POLICY; +use kata_agent_policy::policy::AgentPolicy; async fn allow_request(policy: &mut AgentPolicy, ep: &str, request: &str) -> ttrpc::Result<()> { match policy.allow_request(ep, request).await { @@ -54,213 +43,3 @@ pub async fn do_set_policy(req: &protocols::agent::SetPolicyRequest) -> ttrpc::R .await .map_err(|e| ttrpc_error(ttrpc::Code::INVALID_ARGUMENT, e)) } - -/// Singleton policy object. -#[derive(Debug, Default)] -pub struct AgentPolicy { - /// When true policy errors are ignored, for debug purposes. - allow_failures: bool, - - /// "/tmp/policy.txt" log file for policy activity. - log_file: Option, - - /// Regorus engine - engine: regorus::Engine, -} - -#[derive(serde::Deserialize, Debug)] -struct MetadataResponse { - allowed: bool, - ops: Option, -} - -impl AgentPolicy { - /// Create AgentPolicy object. - pub fn new() -> Self { - Self { - allow_failures: false, - engine: Self::new_engine(), - ..Default::default() - } - } - - fn new_engine() -> regorus::Engine { - let mut engine = regorus::Engine::new(); - engine.set_strict_builtin_errors(false); - engine.set_gather_prints(true); - // assign a slice of the engine data "pstate" to be used as policy state - engine - .add_data( - regorus::Value::from_json_str( - r#"{ - "pstate": {} - }"#, - ) - .unwrap(), - ) - .unwrap(); - engine - } - - /// Initialize regorus. - pub async fn initialize(&mut self) -> Result<()> { - if AGENT_CONFIG.log_level.as_usize() >= slog::Level::Debug.as_usize() { - self.log_file = Some( - tokio::fs::OpenOptions::new() - .write(true) - .truncate(true) - .create(true) - .open(POLICY_LOG_FILE) - .await?, - ); - debug!(sl!(), "policy: log file: {}", POLICY_LOG_FILE); - } - - // Check if policy file has been set via AgentConfig - // If empty, use default file. - let mut default_policy_file = AGENT_CONFIG.policy_file.clone(); - if default_policy_file.is_empty() { - default_policy_file = POLICY_DEFAULT_FILE.to_string(); - } - info!(sl!(), "default policy: {default_policy_file}"); - - self.engine.add_policy_from_file(default_policy_file)?; - self.update_allow_failures_flag().await?; - Ok(()) - } - - async fn apply_patch_to_state(&mut self, patch: json_patch::Patch) -> Result<()> { - // Convert the current engine data to a JSON value - let mut state = serde_json::to_value(self.engine.get_data())?; - - // Apply the patch to the state - json_patch::patch(&mut state, &patch)?; - - // Clear the existing data in the engine - self.engine.clear_data(); - - // Add the patched state back to the engine - self.engine - .add_data(regorus::Value::from_json_str(&state.to_string())?)?; - - Ok(()) - } - - /// Ask regorus if an API call should be allowed or not. - async fn allow_request(&mut self, ep: &str, ep_input: &str) -> Result<(bool, String)> { - debug!(sl!(), "policy check: {ep}"); - self.log_eval_input(ep, ep_input).await; - - let query = format!("data.agent_policy.{ep}"); - self.engine.set_input_json(ep_input)?; - - let results = self.engine.eval_query(query, false)?; - - let prints = match self.engine.take_prints() { - Ok(p) => p.join(" "), - Err(e) => format!("Failed to get policy log: {e}"), - }; - - if results.result.len() != 1 { - // Results are empty when AllowRequestsFailingPolicy is used to allow a Request that hasn't been defined in the policy - if self.allow_failures { - return Ok((true, prints)); - } - bail!( - "policy check: unexpected eval_query result len {:?}", - results - ); - } - - if results.result[0].expressions.len() != 1 { - bail!( - "policy check: unexpected eval_query result expressions {:?}", - results - ); - } - - let mut allow = match &results.result[0].expressions[0].value { - regorus::Value::Bool(b) => *b, - - // Match against a specific variant that could be interpreted as MetadataResponse - regorus::Value::Object(obj) => { - let json_str = serde_json::to_string(obj)?; - - self.log_eval_input(ep, &json_str).await; - - let metadata_response: MetadataResponse = serde_json::from_str(&json_str)?; - - if metadata_response.allowed { - if let Some(ops) = metadata_response.ops { - self.apply_patch_to_state(ops).await?; - } - } - metadata_response.allowed - } - - _ => { - error!(sl!(), "allow_request: unexpected eval_query result type"); - bail!( - "policy check: unexpected eval_query result type {:?}", - results - ); - } - }; - - if !allow && self.allow_failures { - warn!(sl!(), "policy: ignoring error for {ep}"); - allow = true; - } - - Ok((allow, prints)) - } - - /// Replace the Policy in regorus. - pub async fn set_policy(&mut self, policy: &str) -> Result<()> { - self.engine = Self::new_engine(); - self.engine - .add_policy("agent_policy".to_string(), policy.to_string())?; - self.update_allow_failures_flag().await?; - Ok(()) - } - - async fn log_eval_input(&mut self, ep: &str, input: &str) { - if let Some(log_file) = &mut self.log_file { - match ep { - "StatsContainerRequest" | "ReadStreamRequest" | "SetPolicyRequest" => { - // - StatsContainerRequest and ReadStreamRequest are called - // relatively often, so we're not logging them, to avoid - // growing this log file too much. - // - Confidential Containers Policy documents are relatively - // large, so we're not logging them here, for SetPolicyRequest. - // The Policy text can be obtained directly from the pod YAML. - } - _ => { - let log_entry = format!("[\"ep\":\"{ep}\",{input}],\n\n"); - - if let Err(e) = log_file.write_all(log_entry.as_bytes()).await { - warn!(sl!(), "policy: log_eval_input: write_all failed: {}", e); - } else if let Err(e) = log_file.flush().await { - warn!(sl!(), "policy: log_eval_input: flush failed: {}", e); - } - } - } - } - } - - async fn update_allow_failures_flag(&mut self) -> Result<()> { - self.allow_failures = match self.allow_request("AllowRequestsFailingPolicy", "{}").await { - Ok((allowed, _prints)) => { - if allowed { - warn!( - sl!(), - "policy: AllowRequestsFailingPolicy is enabled - will ignore errors" - ); - } - allowed - } - Err(_) => false, - }; - Ok(()) - } -} diff --git a/src/tools/genpolicy/Cargo.lock b/src/tools/genpolicy/Cargo.lock index 3f903a7898..b5973efd91 100644 --- a/src/tools/genpolicy/Cargo.lock +++ b/src/tools/genpolicy/Cargo.lock @@ -47,6 +47,12 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + [[package]] name = "async-trait" version = "0.1.68" @@ -73,7 +79,7 @@ dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", - "bytes", + "bytes 1.1.0", "futures-util", "http", "http-body", @@ -99,7 +105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes", + "bytes 1.1.0", "futures-util", "http", "http-body", @@ -169,6 +175,16 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "1.1.0" @@ -397,6 +413,15 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive-new" version = "0.5.9" @@ -450,6 +475,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "docker_credential" version = "1.3.1" @@ -570,6 +616,15 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "fnv" version = "1.0.7" @@ -611,6 +666,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -618,6 +688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -626,6 +697,17 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.28" @@ -661,6 +743,7 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -697,6 +780,7 @@ dependencies = [ "fs2", "generic-array", "k8s-cri", + "kata-agent-policy", "libz-ng-sys", "log", "oci-distribution", @@ -704,13 +788,13 @@ dependencies = [ "openssl", "protobuf 3.3.0", "protocols", - "regorus", "serde", "serde-transcode", "serde_ignored", "serde_json", "serde_yaml", "sha2", + "slog", "tar", "tarindex", "tempfile", @@ -755,7 +839,7 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" dependencies = [ - "bytes", + "bytes 1.1.0", "fnv", "futures-core", "futures-sink", @@ -801,15 +885,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.1" @@ -840,7 +915,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes", + "bytes 1.1.0", "fnv", "itoa", ] @@ -860,7 +935,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes", + "bytes 1.1.0", "http", "pin-project-lite", ] @@ -889,7 +964,7 @@ version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ - "bytes", + "bytes 1.1.0", "futures-channel", "futures-core", "futures-util", @@ -925,7 +1000,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes", + "bytes 1.1.0", "hyper", "native-tls", "tokio", @@ -1011,6 +1086,15 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "ipnet" version = "2.7.1" @@ -1023,7 +1107,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "io-lifetimes", "rustix 0.36.8", "windows-sys 0.45.0", @@ -1038,15 +1122,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.6" @@ -1062,6 +1137,29 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-patch" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonptr" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6e529149475ca0b2820835d3dce8fcc41c6b943ca608d32f35b449255e4627" +dependencies = [ + "fluent-uri", + "serde", + "serde_json", +] + [[package]] name = "jwt" version = "0.16.0" @@ -1089,6 +1187,23 @@ dependencies = [ "tonic-build 0.8.4", ] +[[package]] +name = "kata-agent-policy" +version = "0.1.0" +dependencies = [ + "anyhow", + "json-patch", + "logging", + "regorus", + "serde", + "serde_json", + "slog", + "slog-scope", + "slog-term", + "tokio", + "tokio-vsock", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1097,9 +1212,19 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.4.1", + "libc", +] [[package]] name = "libz-ng-sys" @@ -1135,12 +1260,36 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "logging" +version = "0.1.0" +dependencies = [ + "arc-swap", + "lazy_static", + "serde_json", + "slog", + "slog-async", + "slog-json", + "slog-scope", + "slog-term", +] + [[package]] name = "matches" version = "0.1.10" @@ -1159,6 +1308,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.7.1" @@ -1185,13 +1343,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1218,6 +1376,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + [[package]] name = "nix" version = "0.26.4" @@ -1227,73 +1398,15 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset", + "memoffset 0.7.1", "pin-utils", ] [[package]] -name = "num" -version = "0.4.3" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" @@ -1304,16 +1417,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - [[package]] name = "object" version = "0.32.1" @@ -1329,7 +1432,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a635cabf7a6eb4e5f13e9e82bd9503b7c2461bf277132e38638a935ebd684b4" dependencies = [ - "bytes", + "bytes 1.1.0", "chrono", "futures-util", "http", @@ -1442,6 +1545,29 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.8", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1506,6 +1632,12 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1561,7 +1693,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" dependencies = [ - "bytes", + "bytes 1.1.0", "prost-derive 0.8.0", ] @@ -1571,7 +1703,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes", + "bytes 1.1.0", "prost-derive 0.11.9", ] @@ -1581,9 +1713,9 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" dependencies = [ - "bytes", + "bytes 1.1.0", "heck 0.3.3", - "itertools 0.10.5", + "itertools", "log", "multimap", "petgraph 0.5.1", @@ -1599,9 +1731,9 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ - "bytes", + "bytes 1.1.0", "heck 0.4.1", - "itertools 0.10.5", + "itertools", "lazy_static", "log", "multimap", @@ -1622,7 +1754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools", "proc-macro2", "quote", "syn 1.0.109", @@ -1635,7 +1767,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools", "proc-macro2", "quote", "syn 1.0.109", @@ -1647,7 +1779,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" dependencies = [ - "bytes", + "bytes 1.1.0", "prost 0.8.0", ] @@ -1795,6 +1927,26 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.4.1", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.5" @@ -1826,14 +1978,12 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "regorus" -version = "0.1.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77dd872918e5c172bd42ac49716f89a15e35be513bba3d902e355a531529a87f" +checksum = "843c3d97f07e3b5ac0955d53ad0af4c91fe4a4f8525843ece5bf014f27829b73" dependencies = [ "anyhow", - "itertools 0.12.1", "lazy_static", - "num", "rand", "regex", "scientific", @@ -1848,7 +1998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "base64 0.21.7", - "bytes", + "bytes 1.1.0", "encoding_rs", "futures-core", "futures-util", @@ -1968,6 +2118,12 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "security-framework" version = "2.8.2" @@ -1993,9 +2149,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.159" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -2011,9 +2167,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -2031,11 +2187,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -2075,6 +2232,15 @@ dependencies = [ "digest", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.8" @@ -2084,6 +2250,66 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slog" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" + +[[package]] +name = "slog-async" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c8038f898a2c79507940990f05386455b3a317d8f18d4caea7cbc3d5096b84" +dependencies = [ + "crossbeam-channel", + "slog", + "take_mut", + "thread_local", +] + +[[package]] +name = "slog-json" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1e53f61af1e3c8b852eef0a9dee29008f55d6dd63794f3f12cef786cf0f219" +dependencies = [ + "serde", + "serde_json", + "slog", + "time", +] + +[[package]] +name = "slog-scope" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f95a4b4c3274cd2869549da82b57ccc930859bdbf5bcea0424bc5f140b3c786" +dependencies = [ + "arc-swap", + "lazy_static", + "slog", +] + +[[package]] +name = "slog-term" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6e022d0b998abfe5c3782c1f03551a596269450ccd677ea51c56f8b214610e8" +dependencies = [ + "is-terminal", + "slog", + "term", + "thread_local", + "time", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "socket2" version = "0.4.9" @@ -2169,6 +2395,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tar" version = "0.4.41" @@ -2211,6 +2443,17 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -2240,6 +2483,47 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2257,19 +2541,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", - "bytes", + "bytes 1.1.0", "libc", "mio", - "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2 0.5.5", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2284,9 +2569,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -2320,7 +2605,7 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ - "bytes", + "bytes 1.1.0", "futures-core", "futures-sink", "pin-project-lite", @@ -2328,6 +2613,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "tokio-vsock" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b33556828911d16e24d8b5d336446b0bf6b4b9bfda52cbdc2fa35b7a2862ebc" +dependencies = [ + "bytes 0.4.12", + "futures", + "libc", + "tokio", + "vsock", +] + [[package]] name = "tonic" version = "0.9.2" @@ -2337,7 +2635,7 @@ dependencies = [ "async-trait", "axum", "base64 0.21.7", - "bytes", + "bytes 1.1.0", "futures-core", "futures-util", "h2", @@ -2464,7 +2762,7 @@ dependencies = [ "home", "libc", "log", - "nix", + "nix 0.26.4", "protobuf 3.3.0", "protobuf-codegen 3.3.0", "thiserror", @@ -2563,6 +2861,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vsock" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32675ee2b3ce5df274c0ab52d19b28789632406277ca26bffee79a8e27dc133" +dependencies = [ + "libc", + "nix 0.23.2", +] + [[package]] name = "want" version = "0.3.0" diff --git a/src/tools/genpolicy/Cargo.toml b/src/tools/genpolicy/Cargo.toml index f146435032..4330b0a4a2 100644 --- a/src/tools/genpolicy/Cargo.toml +++ b/src/tools/genpolicy/Cargo.toml @@ -73,4 +73,5 @@ containerd-client = "0.4.0" tar = "0.4.41" [dev-dependencies] -regorus = { version = "0.1.4", default-features = false, features = ["arc", "regex"]} +kata-agent-policy = { path = "../../agent/policy" } +slog = "2.5.2" diff --git a/src/tools/genpolicy/rules.rego b/src/tools/genpolicy/rules.rego index 6caba44357..1acfca19c8 100644 --- a/src/tools/genpolicy/rules.rego +++ b/src/tools/genpolicy/rules.rego @@ -86,7 +86,7 @@ CreateContainerRequest:= {"ops": ops, "allowed": true} { i_namespace := i_oci.Annotations[S_NAMESPACE_KEY] print ("CreateContainerRequest: p_namespace =", p_namespace, "i_namespace =", i_namespace) add_namespace_to_state := allow_namespace(p_namespace, i_namespace) - ops := concat_op_if_not_null(ops_builder1, add_namespace_to_state) + ops_builder2 := concat_op_if_not_null(ops_builder1, add_namespace_to_state) print("CreateContainerRequest: p Version =", p_oci.Version, "i Version =", i_oci.Version) p_oci.Version == i_oci.Version @@ -102,7 +102,10 @@ CreateContainerRequest:= {"ops": ops, "allowed": true} { p_devices := p_container.devices allow_devices(p_devices, i_devices) - allow_linux(p_oci, i_oci) + ret := allow_linux(ops_builder2, p_oci, i_oci) + ret.allowed + + ops := ret.ops print("CreateContainerRequest: true") } @@ -150,11 +153,12 @@ allow_namespace(p_namespace, i_namespace) = add_namespace { add_namespace := state_allows("namespace", i_namespace) } -# value hasn't been seen before, save it to state +# key hasn't been seen before, save key, value pair to state state_allows(key, value) = action { state := get_state() + print("state_allows 1: state[key] =", state[key], "value =", value) not state[key] - print("state_allows: saving to state key =", key, "value =", value) + print("state_allows 1: saving to state key =", key, "value =", value) path := get_state_path(key) action := { "op": "add", @@ -165,9 +169,11 @@ state_allows(key, value) = action { # value matches what's in state, allow it state_allows(key, value) = action { + print("state_allows 2: start") state := get_state() + print("state_allows 2: state[key] =", state[key], "value =", value) value == state[key] - print("state_allows: found key =", key, "value =", value, " in state") + print("state_allows 2: found key =", key, "value =", value, " in state") action := null } @@ -181,7 +187,7 @@ get_state_path(key) = path { path := concat("/", ["/pstate", key]) } -# Helper functions to conditionally concatenate if op is not null +# Helper functions to conditionally concatenate op is not null concat_op_if_not_null(ops, op) = result { op == null result := ops @@ -439,22 +445,74 @@ allow_devices(p_devices, i_devices) { print("allow_devices: true") } -allow_linux(p_oci, i_oci) { +allow_linux(state_ops, p_oci, i_oci) := {"ops": ops, "allowed": true} { p_namespaces := p_oci.Linux.Namespaces print("allow_linux: p namespaces =", p_namespaces) i_namespaces := i_oci.Linux.Namespaces print("allow_linux: i namespaces =", i_namespaces) - p_namespaces == i_namespaces + i_namespace_without_network := [obj | obj := i_namespaces[_]; obj.Type != "network"] + + print("allow_linux: i_namespace_without_network =", i_namespace_without_network) + + p_namespaces == i_namespace_without_network allow_masked_paths(p_oci, i_oci) allow_readonly_paths(p_oci, i_oci) allow_linux_devices(p_oci.Linux.Devices, i_oci.Linux.Devices) + ret := allow_network_namespace_start(state_ops, p_oci, i_oci) + ret.allowed + + ops := ret.ops print("allow_linux: true") } +# Retrieve the "network" namespace from the input data and pass it on for the +# network namespace policy checks. +allow_network_namespace_start(state_ops, p_oci, i_oci) := {"ops": ops, "allowed": true} { + print("allow_network_namespace start: start") + + p_namespaces := p_oci.Linux.Namespaces + print("allow_network_namespace start: p namespaces =", p_namespaces) + + i_namespaces := i_oci.Linux.Namespaces + print("allow_network_namespace start: i namespaces =", i_namespaces) + + # Return path of the "network" namespace + network_ns := [obj | obj := i_namespaces[_]; obj.Type == "network"] + + print("allow_network_namespace start: network_ns =", network_ns) + + ret := allow_network_namespace(state_ops, network_ns) + ret.allowed + + ops := ret.ops +} + +# This rule is when there's no network namespace in the input data. +allow_network_namespace(state_ops, network_ns) := {"ops": ops, "allowed": true} { + count(network_ns) == 0 + + network_ns_path = "" + + add_network_namespace_to_state := state_allows("network_namespace", network_ns_path) + ops := concat_op_if_not_null(state_ops, add_network_namespace_to_state) + + print("allow_network_namespace 1: true") +} + +# This rule is when there's exactly one network namespace in the input data. +allow_network_namespace(state_ops, network_ns) := {"ops": ops, "allowed": true} { + count(network_ns) == 1 + + add_network_namespace_to_state := state_allows("network_namespace", network_ns[0].Path) + ops := concat_op_if_not_null(state_ops, add_network_namespace_to_state) + + print("allow_network_namespace 2: true") +} + allow_masked_paths(p_oci, i_oci) { p_paths := p_oci.Linux.MaskedPaths print("allow_masked_paths 1: p_paths =", p_paths) diff --git a/src/tools/genpolicy/src/lib.rs b/src/tools/genpolicy/src/lib.rs new file mode 100644 index 0000000000..e6bb2100ba --- /dev/null +++ b/src/tools/genpolicy/src/lib.rs @@ -0,0 +1,30 @@ +// Copyright (c) 2024 Edgeless Systems GmbH +// +// SPDX-License-Identifier: Apache-2.0 +// + +pub mod config_map; +pub mod containerd; +pub mod cronjob; +pub mod daemon_set; +pub mod deployment; +pub mod job; +pub mod list; +pub mod mount_and_storage; +pub mod no_policy; +pub mod obj_meta; +pub mod persistent_volume_claim; +pub mod pod; +pub mod pod_template; +pub mod policy; +pub mod registry; +pub mod registry_containerd; +pub mod replica_set; +pub mod replication_controller; +pub mod secret; +pub mod settings; +pub mod stateful_set; +pub mod utils; +pub mod verity; +pub mod volume; +pub mod yaml; diff --git a/src/tools/genpolicy/src/policy.rs b/src/tools/genpolicy/src/policy.rs index 656e410668..4879260b29 100644 --- a/src/tools/genpolicy/src/policy.rs +++ b/src/tools/genpolicy/src/policy.rs @@ -33,7 +33,7 @@ use std::io::Write; /// Intermediary format of policy data. pub struct AgentPolicy { /// K8s resources described by the input YAML file. - resources: Vec>, + pub resources: Vec>, /// K8s ConfigMap resources described by an additional input YAML file /// or by the "main" input YAML file, containing additional pod settings. diff --git a/src/tools/genpolicy/src/utils.rs b/src/tools/genpolicy/src/utils.rs index 002eafaf17..6696338cdb 100644 --- a/src/tools/genpolicy/src/utils.rs +++ b/src/tools/genpolicy/src/utils.rs @@ -161,3 +161,9 @@ impl Config { } } } + +impl Default for Config { + fn default() -> Self { + Self::new() + } +} diff --git a/src/tools/genpolicy/tests/main.rs b/src/tools/genpolicy/tests/main.rs index 565b3e2a0b..1c4119bdf4 100644 --- a/src/tools/genpolicy/tests/main.rs +++ b/src/tools/genpolicy/tests/main.rs @@ -3,99 +3,140 @@ // SPDX-License-Identifier: Apache-2.0 // -use std::any; -use std::fs::{self, File}; -use std::path; -use std::process::Command; -use std::str; +#[cfg(test)] +mod tests { + use base64::prelude::*; + use std::any; + use std::fs::{self, File}; + use std::path; + use std::str; -use protocols::agent::{CopyFileRequest, CreateSandboxRequest}; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; + use protocols::agent::{CopyFileRequest, CreateContainerRequest, CreateSandboxRequest}; + use serde::de::DeserializeOwned; + use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Deserialize, Serialize)] -struct TestCase { - description: String, - allowed: bool, - request: T, -} + use kata_agent_policy::policy::AgentPolicy; -/// Run tests from the given directory. -/// The directory is searched under `src/tools/genpolicy/tests/testdata`, and -/// it must contain a `resources.yaml` file as well as a `testcases.json` file. -/// The resources must produce a policy when fed into genpolicy, so there -/// should be exactly one entry with a PodSpec. The test case file must contain -/// a JSON list of [TestCase] instances appropriate for `T`. -fn runtests(test_case_dir: &str) -where - T: DeserializeOwned + Serialize, -{ - // Prepare temp dir for running genpolicy. + #[derive(Clone, Debug, Deserialize, Serialize)] + struct TestCase { + description: String, + allowed: bool, + request: T, + } - let workdir = path::PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(test_case_dir); - fs::create_dir_all(&workdir) - .expect("should be able to create directories under CARGO_TARGET_TMPDIR"); + /// Run tests from the given directory. + /// The directory is searched under `src/tools/genpolicy/tests/testdata`, and + /// it must contain a `resources.yaml` file as well as a `testcases.json` file. + /// The resources must produce a policy when fed into genpolicy, so there + /// should be exactly one entry with a PodSpec. The test case file must contain + /// a JSON list of [TestCase] instances appropriate for `T`. + async fn runtests(test_case_dir: &str) + where + T: DeserializeOwned + Serialize, + { + // Prepare temp dir for running genpolicy. + let workdir = path::PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(test_case_dir); + fs::create_dir_all(&workdir) + .expect("should be able to create directories under CARGO_TARGET_TMPDIR"); - let genpolicy_dir = path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); - - for base in ["rules.rego", "genpolicy-settings.json"] { - fs::copy(genpolicy_dir.join(base), workdir.join(base)) + let testdata_dir = path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("tests/testdata") + .join(test_case_dir); + fs::copy(testdata_dir.join("pod.yaml"), workdir.join("pod.yaml")) .expect("copying files around should not fail"); + + let genpolicy_dir = + path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../tools/genpolicy"); + + for base in ["rules.rego", "genpolicy-settings.json"] { + fs::copy(genpolicy_dir.join(base), workdir.join(base)) + .expect("copying files around should not fail"); + } + + // Run the command and return the generated policy. + + let config = genpolicy::utils::Config { + base64_out: false, + config_map_files: None, + containerd_socket_path: None, // Some(String::from("/var/run/containerd/containerd.sock")), + insecure_registries: Vec::new(), + layers_cache_file_path: None, + raw_out: false, + rego_rules_path: workdir.join("rules.rego").to_str().unwrap().to_string(), + runtime_class_names: Vec::new(), + settings: genpolicy::settings::Settings::new( + workdir.join("genpolicy-settings.json").to_str().unwrap(), + ), + silent_unsupported_fields: false, + use_cache: false, + version: false, + yaml_file: workdir.join("pod.yaml").to_str().map(|s| s.to_string()), + }; + + let policy = genpolicy::policy::AgentPolicy::from_files(&config) + .await + .unwrap(); + assert_eq!(policy.resources.len(), 1); + let policy = policy.resources[0].generate_policy(&policy); + let policy = BASE64_STANDARD.decode(&policy).unwrap(); + + // write policy to a file + fs::write(workdir.join("policy.rego"), &policy).unwrap(); + + // Write policy back to a file + + // Re-implement needed parts of AgentPolicy::initialize() + let mut pol = AgentPolicy::new(); + pol.initialize( + slog::Level::Debug.as_usize(), + workdir.join("policy.rego").to_str().unwrap().to_string(), + workdir.join("policy.log").to_str().map(|s| s.to_string()), + ) + .await + .unwrap(); + + // Run through the test cases and evaluate the canned requests. + + let case_file = + File::open(testdata_dir.join("testcases.json")).expect("test case file should open"); + let test_cases: Vec> = + serde_json::from_reader(case_file).expect("test case file should parse"); + + for test_case in test_cases { + println!("\n== case: {} ==\n", test_case.description); + + let v = serde_json::to_value(&test_case.request).unwrap(); + + let results = pol + .allow_request( + any::type_name::().split("::").last().unwrap(), + &serde_json::to_string(&v).unwrap(), + ) + .await; + + let logs = fs::read_to_string(workdir.join("policy.log")).unwrap(); + let results = results.unwrap(); + + assert_eq!( + test_case.allowed, results.0, + "logs: {}\npolicy: {}", + logs, results.1 + ); + } } - let test_data = genpolicy_dir.join("tests/testdata").join(test_case_dir); - fs::copy(test_data.join("pod.yaml"), workdir.join("pod.yaml")) - .expect("copying files around should not fail"); + #[tokio::test] + async fn test_copyfile() { + runtests::("copyfile").await; + } - // Run the command and return the generated policy. + #[tokio::test] + async fn test_create_sandbox() { + runtests::("createsandbox").await; + } - let output = Command::new(env!("CARGO_BIN_EXE_genpolicy")) - .current_dir(workdir) - .args(["-u", "-r", "-y", "pod.yaml"]) - .output() - .expect("executing the genpolicy command should not fail"); - - assert_eq!( - output.status.code(), - Some(0), - "genpolicy failed: {}", - str::from_utf8(output.stderr.as_slice()).expect("genpolicy should return status code 0") - ); - let policy = str::from_utf8(output.stdout.as_slice()) - .unwrap() - .to_string(); - - // Set up the policy engine. - - let mut pol = regorus::Engine::new(); - pol.add_policy("policy.rego".to_string(), policy).unwrap(); - - // Run through the test cases and evaluate the canned requests. - - let case_file = - File::open(test_data.join("testcases.json")).expect("test case file should open"); - let test_cases: Vec> = - serde_json::from_reader(case_file).expect("test case file should parse"); - - for test_case in test_cases { - println!("\n== case: {} ==\n", test_case.description); - - let v = serde_json::to_value(&test_case.request).unwrap(); - pol.set_input(v.into()); - let query = format!( - "data.agent_policy.{}", - any::type_name::().split("::").last().unwrap() - ); - assert_eq!(test_case.allowed, pol.eval_deny_query(query, true)); + #[tokio::test] + async fn test_create_container_network_namespace() { + runtests::("createcontainer/network_namespace").await; } } - -#[test] -fn test_copyfile() { - runtests::("copyfile"); -} - -#[test] -fn test_create_sandbox() { - runtests::("createsandbox"); -} diff --git a/src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/pod.yaml b/src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/pod.yaml new file mode 100644 index 0000000000..7ac6554ed9 --- /dev/null +++ b/src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/pod.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dummy +spec: + runtimeClassName: kata-cc-isolation + containers: + - name: dummy + image: registry.k8s.io/pause:3.6@sha256:3d380ca8864549e74af4b29c10f9cb0956236dfb01c40ca076fb6c37253234db diff --git a/src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/testcases.json b/src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/testcases.json new file mode 100644 index 0000000000..5de73c5fcc --- /dev/null +++ b/src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/testcases.json @@ -0,0 +1,522 @@ +[ + { + "description": "one network namespace", + "allowed": true, + "request": { + "OCI": { + "Version": "1.1.0", + "Annotations": { + "io.kubernetes.cri.sandbox-name": "dummy", + "io.kubernetes.cri.sandbox-namespace": "default", + "io.kubernetes.cri.container-type": "sandbox", + "io.katacontainers.pkg.oci.container_type": "pod_sandbox", + "nerdctl/network-namespace": "/var/run/netns/cni-00000000-0000-0000-0000-000000000000", + "io.kubernetes.cri.sandbox-log-directory": "/var/log/pods/default_dummy_00000000-0000-0000-0000-000000000000", + "io.katacontainers.pkg.oci.bundle_path": "/run/containerd/io.containerd.runtime.v2.task/k8s.io/bundle-id", + "io.kubernetes.cri.sandbox-id": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "Linux": { + "GIDMappings": [], + "MountLabel": "", + "Resources": { + "Devices": [] + }, + "RootfsPropagation": "", + "Namespaces": [ + { + "Path": "", + "Type": "ipc" + }, + { + "Path": "", + "Type": "uts" + }, + { + "Path": "", + "Type": "mount" + }, + { + "Path": "/run/netns/podns", + "Type": "network" + } + ], + "MaskedPaths": [ + "/proc/acpi", + "/proc/asound", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/sys/firmware", + "/proc/scsi" + ], + "ReadonlyPaths": [ + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ] + }, + "Process": { + "SelinuxLabel": "", + "User": { + "Username": "", + "UID": 65535 + }, + "Args": [ + "/pause" + ], + "Cwd": "/", + "NoNewPrivileges": true, + "Capabilities": { + "Ambient": [], + "Bounding": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Effective": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Permitted": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ] + } + }, + "Root": { + "Readonly": true, + "Path": "/run/kata-containers/shared/containers/bundle-id/rootfs" + } + } + } + }, + { + "description": "same network namespace", + "allowed": true, + "request": { + "OCI": { + "Version": "1.1.0", + "Annotations": { + "io.kubernetes.cri.sandbox-name": "dummy", + "io.kubernetes.cri.sandbox-namespace": "default", + "io.kubernetes.cri.container-type": "sandbox", + "io.katacontainers.pkg.oci.container_type": "pod_sandbox", + "nerdctl/network-namespace": "/var/run/netns/cni-00000000-0000-0000-0000-000000000000", + "io.kubernetes.cri.sandbox-log-directory": "/var/log/pods/default_dummy_00000000-0000-0000-0000-000000000000", + "io.katacontainers.pkg.oci.bundle_path": "/run/containerd/io.containerd.runtime.v2.task/k8s.io/bundle-id", + "io.kubernetes.cri.sandbox-id": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "Linux": { + "GIDMappings": [], + "MountLabel": "", + "Resources": { + "Devices": [] + }, + "RootfsPropagation": "", + "Namespaces": [ + { + "Path": "", + "Type": "ipc" + }, + { + "Path": "", + "Type": "uts" + }, + { + "Path": "", + "Type": "mount" + }, + { + "Path": "/run/netns/podns", + "Type": "network" + } + ], + "MaskedPaths": [ + "/proc/acpi", + "/proc/asound", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/sys/firmware", + "/proc/scsi" + ], + "ReadonlyPaths": [ + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ] + }, + "Process": { + "SelinuxLabel": "", + "User": { + "Username": "", + "UID": 65535 + }, + "Args": [ + "/pause" + ], + "Cwd": "/", + "NoNewPrivileges": true, + "Capabilities": { + "Ambient": [], + "Bounding": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Effective": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Permitted": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ] + } + }, + "Root": { + "Readonly": true, + "Path": "/run/kata-containers/shared/containers/bundle-id/rootfs" + } + } + } + }, + { + "description": "no network namespace", + "allowed": false, + "request": { + "OCI": { + "Version": "1.1.0", + "Annotations": { + "io.kubernetes.cri.sandbox-name": "dummy", + "io.kubernetes.cri.sandbox-namespace": "default", + "io.kubernetes.cri.container-type": "sandbox", + "io.katacontainers.pkg.oci.container_type": "pod_sandbox", + "nerdctl/network-namespace": "/var/run/netns/cni-00000000-0000-0000-0000-000000000000", + "io.kubernetes.cri.sandbox-log-directory": "/var/log/pods/default_dummy_00000000-0000-0000-0000-000000000000", + "io.katacontainers.pkg.oci.bundle_path": "/run/containerd/io.containerd.runtime.v2.task/k8s.io/bundle-id", + "io.kubernetes.cri.sandbox-id": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "Linux": { + "GIDMappings": [], + "MountLabel": "", + "Resources": { + "Devices": [] + }, + "RootfsPropagation": "", + "Namespaces": [ + { + "Path": "", + "Type": "ipc" + }, + { + "Path": "", + "Type": "uts" + }, + { + "Path": "", + "Type": "mount" + } + ], + "MaskedPaths": [ + "/proc/acpi", + "/proc/asound", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/sys/firmware", + "/proc/scsi" + ], + "ReadonlyPaths": [ + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ] + }, + "Process": { + "SelinuxLabel": "", + "User": { + "Username": "", + "UID": 65535 + }, + "Args": [ + "/pause" + ], + "Cwd": "/", + "NoNewPrivileges": true, + "Capabilities": { + "Ambient": [], + "Bounding": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Effective": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Permitted": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ] + } + }, + "Root": { + "Readonly": true, + "Path": "/run/kata-containers/shared/containers/bundle-id/rootfs" + } + } + } + }, + { + "description": "different network namespace", + "allowed": false, + "request": { + "OCI": { + "Version": "1.1.0", + "Annotations": { + "io.kubernetes.cri.sandbox-name": "dummy", + "io.kubernetes.cri.sandbox-namespace": "default", + "io.kubernetes.cri.container-type": "sandbox", + "io.katacontainers.pkg.oci.container_type": "pod_sandbox", + "nerdctl/network-namespace": "/var/run/netns/cni-00000000-0000-0000-0000-000000000000", + "io.kubernetes.cri.sandbox-log-directory": "/var/log/pods/default_dummy_00000000-0000-0000-0000-000000000000", + "io.katacontainers.pkg.oci.bundle_path": "/run/containerd/io.containerd.runtime.v2.task/k8s.io/bundle-id", + "io.kubernetes.cri.sandbox-id": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "Linux": { + "GIDMappings": [], + "MountLabel": "", + "Resources": { + "Devices": [] + }, + "RootfsPropagation": "", + "Namespaces": [ + { + "Path": "", + "Type": "ipc" + }, + { + "Path": "", + "Type": "uts" + }, + { + "Path": "", + "Type": "mount" + }, + { + "Path": "/run/netns/podns-diff", + "Type": "network" + } + ], + "MaskedPaths": [ + "/proc/acpi", + "/proc/asound", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/sys/firmware", + "/proc/scsi" + ], + "ReadonlyPaths": [ + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ] + }, + "Process": { + "SelinuxLabel": "", + "User": { + "Username": "", + "UID": 65535 + }, + "Args": [ + "/pause" + ], + "Cwd": "/", + "NoNewPrivileges": true, + "Capabilities": { + "Ambient": [], + "Bounding": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Effective": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ], + "Permitted": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ] + } + }, + "Root": { + "Readonly": true, + "Path": "/run/kata-containers/shared/containers/bundle-id/rootfs" + } + } + } + } +] \ No newline at end of file