diff --git a/src/runtime-rs/crates/agent/src/kata/agent.rs b/src/runtime-rs/crates/agent/src/kata/agent.rs index dcd11b9e2b..b403f0f44c 100644 --- a/src/runtime-rs/crates/agent/src/kata/agent.rs +++ b/src/runtime-rs/crates/agent/src/kata/agent.rs @@ -113,5 +113,7 @@ impl_agent!( create_sandbox | crate::CreateSandboxRequest | crate::Empty | None, destroy_sandbox | crate::Empty | crate::Empty | None, copy_file | crate::CopyFileRequest | crate::Empty | None, - get_oom_event | crate::Empty | crate::OomEventResponse | Some(0) + get_oom_event | crate::Empty | crate::OomEventResponse | Some(0), + get_ip_tables | crate::GetIPTablesRequest | crate::GetIPTablesResponse | None, + set_ip_tables | crate::SetIPTablesRequest | crate::SetIPTablesResponse | None ); diff --git a/src/runtime-rs/crates/agent/src/kata/trans.rs b/src/runtime-rs/crates/agent/src/kata/trans.rs index e7fdaa9448..4ac0c45ec2 100644 --- a/src/runtime-rs/crates/agent/src/kata/trans.rs +++ b/src/runtime-rs/crates/agent/src/kata/trans.rs @@ -16,14 +16,15 @@ use crate::{ ARPNeighbor, ARPNeighbors, AddArpNeighborRequest, AgentDetails, BlkioStats, BlkioStatsEntry, CgroupStats, CheckRequest, CloseStdinRequest, ContainerID, CopyFileRequest, CpuStats, CpuUsage, CreateContainerRequest, CreateSandboxRequest, Device, - Empty, ExecProcessRequest, FSGroup, FSGroupChangePolicy, GuestDetailsResponse, - HealthCheckResponse, HugetlbStats, IPAddress, IPFamily, Interface, Interfaces, - KernelModule, MemHotplugByProbeRequest, MemoryData, MemoryStats, NetworkStats, - OnlineCPUMemRequest, PidsStats, ReadStreamRequest, ReadStreamResponse, - RemoveContainerRequest, ReseedRandomDevRequest, Route, Routes, SetGuestDateTimeRequest, - SignalProcessRequest, StatsContainerResponse, Storage, StringUser, ThrottlingData, - TtyWinResizeRequest, UpdateContainerRequest, UpdateInterfaceRequest, UpdateRoutesRequest, - VersionCheckResponse, WaitProcessRequest, WriteStreamRequest, + Empty, ExecProcessRequest, FSGroup, FSGroupChangePolicy, GetIPTablesRequest, + GetIPTablesResponse, GuestDetailsResponse, HealthCheckResponse, HugetlbStats, IPAddress, + IPFamily, Interface, Interfaces, KernelModule, MemHotplugByProbeRequest, MemoryData, + MemoryStats, NetworkStats, OnlineCPUMemRequest, PidsStats, ReadStreamRequest, + ReadStreamResponse, RemoveContainerRequest, ReseedRandomDevRequest, Route, Routes, + SetGuestDateTimeRequest, SetIPTablesRequest, SetIPTablesResponse, SignalProcessRequest, + StatsContainerResponse, Storage, StringUser, ThrottlingData, TtyWinResizeRequest, + UpdateContainerRequest, UpdateInterfaceRequest, UpdateRoutesRequest, VersionCheckResponse, + WaitProcessRequest, WriteStreamRequest, }, OomEventResponse, WaitProcessResponse, WriteStreamResponse, }; @@ -388,6 +389,41 @@ impl From for WriteStreamResponse { } } +impl From for agent::GetIPTablesRequest { + fn from(from: GetIPTablesRequest) -> Self { + Self { + is_ipv6: from.is_ipv6, + ..Default::default() + } + } +} + +impl From for GetIPTablesResponse { + fn from(from: agent::GetIPTablesResponse) -> Self { + Self { + data: from.get_data().to_vec(), + } + } +} + +impl From for agent::SetIPTablesRequest { + fn from(from: SetIPTablesRequest) -> Self { + Self { + is_ipv6: from.is_ipv6, + data: from.data, + ..Default::default() + } + } +} + +impl From for SetIPTablesResponse { + fn from(from: agent::SetIPTablesResponse) -> Self { + Self { + data: from.get_data().to_vec(), + } + } +} + impl From for agent::ExecProcessRequest { fn from(from: ExecProcessRequest) -> Self { Self { diff --git a/src/runtime-rs/crates/agent/src/lib.rs b/src/runtime-rs/crates/agent/src/lib.rs index 8c41d751f5..8ef76ebbe2 100644 --- a/src/runtime-rs/crates/agent/src/lib.rs +++ b/src/runtime-rs/crates/agent/src/lib.rs @@ -16,11 +16,12 @@ pub mod types; pub use types::{ ARPNeighbor, ARPNeighbors, AddArpNeighborRequest, BlkioStatsEntry, CheckRequest, CloseStdinRequest, ContainerID, ContainerProcessID, CopyFileRequest, CreateContainerRequest, - CreateSandboxRequest, Empty, ExecProcessRequest, GetGuestDetailsRequest, GuestDetailsResponse, - HealthCheckResponse, IPAddress, IPFamily, Interface, Interfaces, ListProcessesRequest, - MemHotplugByProbeRequest, OnlineCPUMemRequest, OomEventResponse, ReadStreamRequest, - ReadStreamResponse, RemoveContainerRequest, ReseedRandomDevRequest, Route, Routes, - SetGuestDateTimeRequest, SignalProcessRequest, StatsContainerResponse, Storage, + CreateSandboxRequest, Empty, ExecProcessRequest, GetGuestDetailsRequest, GetIPTablesRequest, + GetIPTablesResponse, GuestDetailsResponse, HealthCheckResponse, IPAddress, IPFamily, Interface, + Interfaces, ListProcessesRequest, MemHotplugByProbeRequest, OnlineCPUMemRequest, + OomEventResponse, ReadStreamRequest, ReadStreamResponse, RemoveContainerRequest, + ReseedRandomDevRequest, Route, Routes, SetGuestDateTimeRequest, SetIPTablesRequest, + SetIPTablesResponse, SignalProcessRequest, StatsContainerResponse, Storage, TtyWinResizeRequest, UpdateContainerRequest, UpdateInterfaceRequest, UpdateRoutesRequest, VersionCheckResponse, WaitProcessRequest, WaitProcessResponse, WriteStreamRequest, WriteStreamResponse, @@ -85,4 +86,6 @@ pub trait Agent: AgentManager + HealthService + Send + Sync { // utils async fn copy_file(&self, req: CopyFileRequest) -> Result; async fn get_oom_event(&self, req: Empty) -> Result; + async fn get_ip_tables(&self, req: GetIPTablesRequest) -> Result; + async fn set_ip_tables(&self, req: SetIPTablesRequest) -> Result; } diff --git a/src/runtime-rs/crates/agent/src/types.rs b/src/runtime-rs/crates/agent/src/types.rs index eb5422e165..4c71534ecf 100644 --- a/src/runtime-rs/crates/agent/src/types.rs +++ b/src/runtime-rs/crates/agent/src/types.rs @@ -205,6 +205,27 @@ pub struct UpdateContainerRequest { pub mounts: Vec, } +#[derive(PartialEq, Clone, Default, Debug)] +pub struct GetIPTablesRequest { + pub is_ipv6: bool, +} + +#[derive(PartialEq, Clone, Default, Debug)] +pub struct GetIPTablesResponse { + pub data: Vec, +} + +#[derive(PartialEq, Clone, Default, Debug)] +pub struct SetIPTablesRequest { + pub is_ipv6: bool, + pub data: Vec, +} + +#[derive(PartialEq, Clone, Default, Debug)] +pub struct SetIPTablesResponse { + pub data: Vec, +} + #[derive(PartialEq, Clone, Default)] pub struct WriteStreamRequest { pub process_id: ContainerProcessID, diff --git a/src/runtime-rs/crates/runtimes/common/src/sandbox.rs b/src/runtime-rs/crates/runtimes/common/src/sandbox.rs index 269a3586ed..5ac028ddbc 100644 --- a/src/runtime-rs/crates/runtimes/common/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/common/src/sandbox.rs @@ -16,4 +16,8 @@ pub trait Sandbox: Send + Sync { // agent function async fn agent_sock(&self) -> Result; + + // utils + async fn set_iptables(&self, is_ipv6: bool, data: Vec) -> Result>; + async fn get_iptables(&self, is_ipv6: bool) -> Result>; } diff --git a/src/runtime-rs/crates/runtimes/src/shim_mgmt/client.rs b/src/runtime-rs/crates/runtimes/src/shim_mgmt/client.rs index 267de24282..5084c9f0f9 100644 --- a/src/runtime-rs/crates/runtimes/src/shim_mgmt/client.rs +++ b/src/runtime-rs/crates/runtimes/src/shim_mgmt/client.rs @@ -12,7 +12,7 @@ use std::{path::Path, path::PathBuf, time::Duration}; use super::server::mgmt_socket_addr; use anyhow::{anyhow, Context, Result}; -use hyper::{Body, Client, Response}; +use hyper::{Body, Client, Method, Request, Response}; use hyperlocal::{UnixClientExt, UnixConnector, Uri}; /// Shim management client with timeout @@ -58,4 +58,22 @@ impl MgmtClient { None => work.await.context("failed to GET"), } } + + /// The http PUT method for client + pub async fn put(&self, uri: &str, data: Vec) -> Result> { + let url: hyper::Uri = Uri::new(&self.sock_path, uri).into(); + let request = Request::builder() + .method(Method::PUT) + .uri(url) + .body(Body::from(data)) + .unwrap(); + let work = self.client.request(request); + match self.timeout { + Some(timeout) => match tokio::time::timeout(timeout, work).await { + Ok(result) => result.map_err(|e| anyhow!(e)), + Err(_) => Err(anyhow!("TIMEOUT")), + }, + None => work.await.context("failed to PUT"), + } + } } diff --git a/src/runtime-rs/crates/runtimes/src/shim_mgmt/handlers.rs b/src/runtime-rs/crates/runtimes/src/shim_mgmt/handlers.rs index 4d98da149d..94fd682eb1 100644 --- a/src/runtime-rs/crates/runtimes/src/shim_mgmt/handlers.rs +++ b/src/runtime-rs/crates/runtimes/src/shim_mgmt/handlers.rs @@ -7,11 +7,12 @@ // This defines the handlers corresponding to the url when a request is sent to destined url, // the handler function should be invoked, and the corresponding data will be in the response +use anyhow::{anyhow, Result}; use common::Sandbox; -use hyper::{Body, Method, Request, Response, Result, StatusCode}; +use hyper::{Body, Method, Request, Response, StatusCode}; use std::sync::Arc; -use super::server::AGENT_URL; +use super::server::{AGENT_URL, IP6_TABLE_URL, IP_TABLE_URL}; // main router for response, this works as a multiplexer on // http arrival which invokes the corresponding handler function @@ -27,6 +28,12 @@ pub(crate) async fn handler_mux( ); match (req.method(), req.uri().path()) { (&Method::GET, AGENT_URL) => agent_url_handler(sandbox, req).await, + (&Method::PUT, IP_TABLE_URL) | (&Method::GET, IP_TABLE_URL) => { + ip_table_handler(sandbox, req).await + } + (&Method::PUT, IP6_TABLE_URL) | (&Method::GET, IP6_TABLE_URL) => { + ipv6_table_handler(sandbox, req).await + } _ => Ok(not_found(req).await), } } @@ -50,3 +57,49 @@ async fn agent_url_handler( .unwrap_or_else(|_| String::from("")); Ok(Response::new(Body::from(agent_sock))) } + +/// the ipv4 handler of iptable operation +async fn ip_table_handler(sandbox: Arc, req: Request) -> Result> { + generic_ip_table_handler(sandbox, req, false).await +} + +/// the ipv6 handler of iptable operation +async fn ipv6_table_handler( + sandbox: Arc, + req: Request, +) -> Result> { + generic_ip_table_handler(sandbox, req, true).await +} + +/// the generic iptable handler, for both ipv4 and ipv6 +/// this requires iptables-series binaries to be inside guest rootfs +async fn generic_ip_table_handler( + sandbox: Arc, + req: Request, + is_ipv6: bool, +) -> Result> { + info!(sl!(), "handler: iptable ipv6?: {}", is_ipv6); + match *req.method() { + Method::GET => match sandbox.get_iptables(is_ipv6).await { + Ok(data) => { + let body = Body::from(data); + Response::builder().body(body).map_err(|e| anyhow!(e)) + } + _ => { + Err(anyhow!("Failed to get iptable")) + } + }, + + Method::PUT => { + let data = hyper::body::to_bytes(req.into_body()).await?; + match sandbox.set_iptables(is_ipv6, data.to_vec()).await { + Ok(resp_data) => Response::builder() + .body(Body::from(resp_data)) + .map_err(|e| anyhow!(e)), + _ => Err(anyhow!("Failed to set iptable")), + } + } + + _ => Err(anyhow!("IP Tables only takes PUT and GET")), + } +} diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index 968c164418..067cf389ea 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -6,7 +6,9 @@ use std::sync::Arc; -use agent::{self, kata::KataAgent, types::KernelModule, Agent}; +use agent::{ + self, kata::KataAgent, types::KernelModule, Agent, GetIPTablesRequest, SetIPTablesRequest, +}; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use common::{ @@ -269,6 +271,28 @@ impl Sandbox for VirtSandbox { async fn agent_sock(&self) -> Result { self.agent.agent_sock().await } + + async fn set_iptables(&self, is_ipv6: bool, data: Vec) -> Result> { + info!(sl!(), "sb: set_iptables invoked"); + let req = SetIPTablesRequest { is_ipv6, data }; + let resp = self + .agent + .set_ip_tables(req) + .await + .context("sandbox: failed to set iptables")?; + Ok(resp.data) + } + + async fn get_iptables(&self, is_ipv6: bool) -> Result> { + info!(sl!(), "sb: get_iptables invoked"); + let req = GetIPTablesRequest { is_ipv6 }; + let resp = self + .agent + .get_ip_tables(req) + .await + .context("sandbox: failed to get iptables")?; + Ok(resp.data) + } } #[async_trait]