genpolicy: Introduce UpdateRoutesRequest rules in genpolicy-settings

Introduce rule to block routes from source addresses which are the
loopback. Block routes added to the lo device.

Signed-off-by: Cameron Baird <cameronbaird@microsoft.com>
This commit is contained in:
Cameron Baird 2025-03-10 17:28:56 +00:00
parent 014ff8476a
commit cf129f3744
6 changed files with 180 additions and 2 deletions

View File

@ -342,6 +342,15 @@
"allowed_commands": [],
"regex": []
},
"UpdateRoutesRequest": {
"forbidden_device_names": [
"lo"
],
"forbidden_source_regex": [
"^(?:0{0,4}:){0,7}0{0,3}1$",
"^127\\.(?:[0-9]{1,3}\\.){2}[0-9]{1,3}$"
]
},
"CloseStdinRequest": false,
"ReadStreamRequest": false,
"UpdateEphemeralMountsRequest": false,

View File

@ -39,7 +39,7 @@ default TtyWinResizeRequest := true
default UpdateContainerRequest := false
default UpdateEphemeralMountsRequest := false
default UpdateInterfaceRequest := true
default UpdateRoutesRequest := true
default UpdateRoutesRequest := false
default WaitProcessRequest := true
default WriteStreamRequest := false
@ -1319,6 +1319,28 @@ ExecProcessRequest {
print("ExecProcessRequest 3: true")
}
UpdateRoutesRequest {
print("UpdateRoutesRequest: input =", input)
print("UpdateRoutesRequest: policy =", policy_data.request_defaults.UpdateRoutesRequest)
i_routes := input.routes.Routes
p_source_regex = policy_data.request_defaults.UpdateRoutesRequest.forbidden_source_regex
p_names = policy_data.request_defaults.UpdateRoutesRequest.forbidden_device_names
every i_route in i_routes {
print("i_route.source =", i_route.source)
every p_regex in p_source_regex {
print("p_regex =", p_regex)
not regex.match(p_regex, i_route.source)
}
print("i_route.device =", i_route.device)
not i_route.device in p_names
}
print("UpdateRoutesRequest: true")
}
CloseStdinRequest {
policy_data.request_defaults.CloseStdinRequest == true
}

View File

@ -334,6 +334,16 @@ pub struct ExecProcessRequestDefaults {
regex: Vec<String>,
}
/// UpdateRoutesRequest settings from genpolicy-settings.json.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct UpdateRoutesRequestDefaults {
/// Forbid adding routes to devices of these names.
forbidden_device_names: Vec<String>,
/// Forbid adding routes originating from these addresses.
forbidden_source_regex: Vec<String>,
}
/// Settings specific to each kata agent endpoint, loaded from
/// genpolicy-settings.json.
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -347,6 +357,9 @@ pub struct RequestDefaults {
/// Commands allowed to be executed by the Host in all Guest containers.
pub ExecProcessRequest: ExecProcessRequestDefaults,
/// Allow the host to update routes for devices other than the loopback.
pub UpdateRoutesRequest: UpdateRoutesRequestDefaults,
/// Allow the Host to close stdin for a container. Typically used with WriteStreamRequest.
pub CloseStdinRequest: bool,

View File

@ -11,7 +11,9 @@ mod tests {
use std::path;
use std::str;
use protocols::agent::{CopyFileRequest, CreateContainerRequest, CreateSandboxRequest};
use protocols::agent::{
CopyFileRequest, CreateContainerRequest, CreateSandboxRequest, UpdateRoutesRequest,
};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
@ -135,6 +137,11 @@ mod tests {
runtests::<CreateSandboxRequest>("createsandbox").await;
}
#[tokio::test]
async fn test_update_routes() {
runtests::<UpdateRoutesRequest>("updateroutes").await;
}
#[tokio::test]
async fn test_create_container_network_namespace() {
runtests::<CreateContainerRequest>("createcontainer/network_namespace").await;

View File

@ -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

View File

@ -0,0 +1,118 @@
[
{
"description": "compliant routes",
"allowed": true,
"request": {
"routes": {
"Routes": [
{
"dest": "",
"gateway": "10.244.0.1",
"device": "eth0",
"source": "",
"scope": 0,
"family": 0
}
]
}
}
},
{
"description": "forbidden device",
"allowed": false,
"request": {
"routes": {
"Routes": [
{
"dest": "",
"gateway": "10.244.0.1",
"device": "lo",
"source": "",
"scope": 0,
"family": 0
}
]
}
}
},
{
"description": "one compliant route, one noncompliant",
"allowed": false,
"request": {
"routes": {
"Routes": [
{
"dest": "",
"gateway": "10.244.0.1",
"device": "eth0",
"source": "",
"scope": 0,
"family": 0
},
{
"dest": "",
"gateway": "10.244.0.1",
"device": "eth0",
"source": "::1",
"scope": 0,
"family": 0
}
]
}
}
},
{
"description": "noncompliant routes",
"allowed": false,
"request": {
"routes": {
"Routes": [
{
"dest": "",
"gateway": "10.244.0.1",
"device": "eth0",
"source": "127.0.0.1",
"scope": 0,
"family": 0
}
]
}
}
},
{
"description": "noncompliant routes ipv6 1",
"allowed": false,
"request": {
"routes": {
"Routes": [
{
"dest": "",
"gateway": "10.244.0.1",
"device": "eth0",
"source": "::1",
"scope": 0,
"family": 0
}
]
}
}
},
{
"description": "noncompliant routes ipv6 2",
"allowed": false,
"request": {
"routes": {
"Routes": [
{
"dest": "",
"gateway": "10.244.0.1",
"device": "eth0",
"source": "00::001",
"scope": 0,
"family": 0
}
]
}
}
}
]