From cf54a1b0e1d868e63c2844c23d4e1ed850e3f578 Mon Sep 17 00:00:00 2001 From: Leonard Cohnen Date: Tue, 3 Dec 2024 20:52:24 +0100 Subject: [PATCH 1/4] agent: move policy module into separate crate The policy module augments the policy generated with genpolicy by keeping and providing state to each invocation. Therefore, it is not sufficient anymore to test the passing of requests in the genpolicy crate. Since in Rust, integration tests cannot call functions that are not exposed publicly, this commit factors out the policy module of the agent into its own crate and exposes the necessary functions to be consumed by the agent and an integration tests. The integration test itself is implemented in the following commits. Signed-off-by: Leonard Cohnen --- src/agent/Cargo.lock | 18 +++ src/agent/Cargo.toml | 3 +- src/agent/policy/Cargo.toml | 33 +++++ src/agent/policy/src/lib.rs | 6 + src/agent/policy/src/policy.rs | 243 +++++++++++++++++++++++++++++++++ src/agent/src/main.rs | 14 +- src/agent/src/policy.rs | 225 +----------------------------- 7 files changed, 315 insertions(+), 227 deletions(-) create mode 100644 src/agent/policy/Cargo.toml create mode 100644 src/agent/policy/src/lib.rs create mode 100644 src/agent/policy/src/policy.rs 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(()) - } -} From d03738a7571b55b1e22475af002b7ab8afd926e0 Mon Sep 17 00:00:00 2001 From: Leonard Cohnen Date: Tue, 3 Dec 2024 20:56:05 +0100 Subject: [PATCH 2/4] genpolicy: expose create as library This commit allows to programmatically invoke genpolicy. This allows for other rust tools that don't want to consume genpolicy as binary to generate policies. One such use-case is the policy integration test implemented in the following commits. Signed-off-by: Leonard Cohnen --- src/tools/genpolicy/src/lib.rs | 30 ++++++++++++++++++++++++++++++ src/tools/genpolicy/src/policy.rs | 2 +- src/tools/genpolicy/src/utils.rs | 6 ++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/tools/genpolicy/src/lib.rs 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() + } +} From 7aca7a6671b8360c6215253e861c219f11c24f13 Mon Sep 17 00:00:00 2001 From: Leonard Cohnen Date: Tue, 3 Dec 2024 23:28:19 +0100 Subject: [PATCH 3/4] policy: use agent policy crate in genpolicy test The generated rego policies for `CreateContainerRequest` are stateful and that state is handled in the policy crate. We use this policy crate in the genpolicy integration test to be able to test if those state changes are handled correctly without spinning up an agent or even a cluster. This also allows to easily test on a e.g., CreateContainerRequest level instead of relying on changing the yaml that is applied to a cluster. Signed-off-by: Leonard Cohnen --- src/tools/genpolicy/Cargo.lock | 578 +++++++++++++++++++++++------- src/tools/genpolicy/Cargo.toml | 3 +- src/tools/genpolicy/tests/main.rs | 206 ++++++----- 3 files changed, 566 insertions(+), 221 deletions(-) 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/tests/main.rs b/src/tools/genpolicy/tests/main.rs index 565b3e2a0b..40247c287a 100644 --- a/src/tools/genpolicy/tests/main.rs +++ b/src/tools/genpolicy/tests/main.rs @@ -3,99 +3,135 @@ // 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. - - 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_sandbox() { + runtests::("createsandbox").await; } } - -#[test] -fn test_copyfile() { - runtests::("copyfile"); -} - -#[test] -fn test_create_sandbox() { - runtests::("createsandbox"); -} From ec0af6fbda4860968c5c122cd52d6d4c04df958c Mon Sep 17 00:00:00 2001 From: Leonard Cohnen Date: Tue, 3 Dec 2024 23:33:01 +0100 Subject: [PATCH 4/4] policy: check the linux network namespace Peer pods have a linux namespace of type network. We want to make sure that all container in the same pod use the same namespace. Therefore, we add the first namespace path to the state and check all other requests against that. This commit also adds the corresponding integration test in the policy crate showcasing the benefit of having rust integration tests for the policy. Signed-off-by: Leonard Cohnen --- src/tools/genpolicy/rules.rego | 74 ++- src/tools/genpolicy/tests/main.rs | 5 + .../network_namespace/pod.yaml | 9 + .../network_namespace/testcases.json | 522 ++++++++++++++++++ 4 files changed, 602 insertions(+), 8 deletions(-) create mode 100644 src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/pod.yaml create mode 100644 src/tools/genpolicy/tests/testdata/createcontainer/network_namespace/testcases.json 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/tests/main.rs b/src/tools/genpolicy/tests/main.rs index 40247c287a..1c4119bdf4 100644 --- a/src/tools/genpolicy/tests/main.rs +++ b/src/tools/genpolicy/tests/main.rs @@ -134,4 +134,9 @@ mod tests { async fn test_create_sandbox() { runtests::("createsandbox").await; } + + #[tokio::test] + async fn test_create_container_network_namespace() { + runtests::("createcontainer/network_namespace").await; + } } 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