1
0
mirror of https://github.com/kata-containers/kata-containers.git synced 2025-05-10 01:16:42 +00:00

Merge pull request from Sumynwa/sumsharma/genpolicy_test

genpolicy: Refactor tests to allow different request types in a testcases json.
This commit is contained in:
Saul Paredes 2025-03-25 12:38:19 -07:00 committed by GitHub
commit ae5c587efc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 72 additions and 19 deletions
src/tools/genpolicy/tests
main.rs
testdata
copyfile
createcontainer
generate_name
network_namespace
sysctls
createsandbox
updateinterface
updateroutes

View File

@ -6,7 +6,7 @@
#[cfg(test)]
mod tests {
use base64::prelude::*;
use std::any;
use std::fmt::{self, Display};
use std::fs::{self, File};
use std::path;
use std::str;
@ -15,16 +15,39 @@ mod tests {
CopyFileRequest, CreateContainerRequest, CreateSandboxRequest, UpdateInterfaceRequest,
UpdateRoutesRequest,
};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use kata_agent_policy::policy::AgentPolicy;
// Translate each test case in testcases.json
// to one request type.
#[derive(Clone, Debug, Deserialize, Serialize)]
struct TestCase<T> {
#[serde(tag = "type")]
enum TestRequest {
CopyFile(CopyFileRequest),
CreateContainer(CreateContainerRequest),
CreateSandbox(CreateSandboxRequest),
UpdateInterface(UpdateInterfaceRequest),
UpdateRoutes(UpdateRoutesRequest),
}
impl Display for TestRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TestRequest::CopyFile(_) => write!(f, "CopyFileRequest"),
TestRequest::CreateContainer(_) => write!(f, "CreateContainerRequest"),
TestRequest::CreateSandbox(_) => write!(f, "CreateSandboxRequest"),
TestRequest::UpdateInterface(_) => write!(f, "UpdateInterfaceRequest"),
TestRequest::UpdateRoutes(_) => write!(f, "UpdateRoutesRequest"),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
struct TestCase {
description: String,
allowed: bool,
request: T,
request: TestRequest,
}
/// Run tests from the given directory.
@ -32,11 +55,9 @@ mod tests {
/// 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<T>(test_case_dir: &str)
where
T: DeserializeOwned + Serialize,
{
/// a JSON list of [TestCase] instances. Each instance will be of type enum TestRequest,
/// with the tag `type` listing the exact type of request.
async fn runtests(test_case_dir: &str) {
// Prepare temp dir for running genpolicy.
let workdir = path::PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(test_case_dir);
fs::create_dir_all(&workdir)
@ -102,7 +123,7 @@ mod tests {
let case_file =
File::open(testdata_dir.join("testcases.json")).expect("test case file should open");
let test_cases: Vec<TestCase<T>> =
let test_cases: Vec<TestCase> =
serde_json::from_reader(case_file).expect("test case file should parse");
for test_case in test_cases {
@ -112,7 +133,7 @@ mod tests {
let results = pol
.allow_request(
any::type_name::<T>().split("::").last().unwrap(),
&test_case.request.to_string(),
&serde_json::to_string(&v).unwrap(),
)
.await;
@ -130,36 +151,36 @@ mod tests {
#[tokio::test]
async fn test_copyfile() {
runtests::<CopyFileRequest>("copyfile").await;
runtests("copyfile").await;
}
#[tokio::test]
async fn test_create_sandbox() {
runtests::<CreateSandboxRequest>("createsandbox").await;
runtests("createsandbox").await;
}
#[tokio::test]
async fn test_update_routes() {
runtests::<UpdateRoutesRequest>("updateroutes").await;
runtests("updateroutes").await;
}
#[tokio::test]
async fn test_update_interface() {
runtests::<UpdateInterfaceRequest>("updateinterface").await;
runtests("updateinterface").await;
}
#[tokio::test]
async fn test_create_container_network_namespace() {
runtests::<CreateContainerRequest>("createcontainer/network_namespace").await;
runtests("createcontainer/network_namespace").await;
}
#[tokio::test]
async fn test_create_container_sysctls() {
runtests::<CreateContainerRequest>("createcontainer/sysctls").await;
runtests("createcontainer/sysctls").await;
}
#[tokio::test]
async fn test_create_container_generate_name() {
runtests::<CreateContainerRequest>("createcontainer/generate_name").await;
runtests("createcontainer/generate_name").await;
}
}

View File

@ -3,6 +3,7 @@
"description": "copy initiated by k8s mount",
"allowed": true,
"request": {
"type": "CopyFile",
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-resolv.conf"
}
},
@ -10,6 +11,7 @@
"description": "a dirname can have trailing dots",
"allowed": true,
"request": {
"type": "CopyFile",
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo../bar"
}
},
@ -17,6 +19,7 @@
"description": "attempt to copy outside of container root",
"allowed": false,
"request": {
"type": "CopyFile",
"path": "/etc/ssl/cert.pem"
}
},
@ -24,6 +27,7 @@
"description": "attempt to write into container root",
"allowed": false,
"request": {
"type": "CopyFile",
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc/rootfs/bin/sh"
}
},
@ -31,6 +35,7 @@
"description": "attempt to write into container root - guest pull",
"allowed": false,
"request": {
"type": "CopyFile",
"path": "/run/kata-containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc/rootfs/bin/sh"
}
},
@ -38,6 +43,7 @@
"description": "attempted directory traversal",
"allowed": false,
"request": {
"type": "CopyFile",
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/../../../../../etc/ssl/cert.pem"
}
},
@ -45,6 +51,7 @@
"description": "attempted directory traversal - parent directory",
"allowed": false,
"request": {
"type": "CopyFile",
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/.."
}
},
@ -52,6 +59,7 @@
"description": "relative path",
"allowed": false,
"request": {
"type": "CopyFile",
"path": "etc/ssl/cert.pem"
}
},
@ -59,6 +67,7 @@
"description": "relative path - parent directory",
"allowed": false,
"request": {
"type": "CopyFile",
"path": ".."
}
}

View File

@ -3,6 +3,7 @@
"description": "generated name with valid prefix (dummyxyz)",
"allowed": true,
"request": {
"type": "CreateContainer",
"OCI": {
"Version": "1.1.0",
"Annotations": {
@ -134,6 +135,7 @@
"description": "generated name with invalid prefix (xyzdummy)",
"allowed": false,
"request": {
"type": "CreateContainer",
"OCI": {
"Version": "1.1.0",
"Annotations": {

View File

@ -3,6 +3,7 @@
"description": "one network namespace",
"allowed": true,
"request": {
"type": "CreateContainer",
"OCI": {
"Version": "1.1.0",
"Annotations": {
@ -134,6 +135,7 @@
"description": "same network namespace",
"allowed": true,
"request": {
"type": "CreateContainer",
"OCI": {
"Version": "1.1.0",
"Annotations": {
@ -265,6 +267,7 @@
"description": "no network namespace",
"allowed": false,
"request": {
"type": "CreateContainer",
"OCI": {
"Version": "1.1.0",
"Annotations": {
@ -392,6 +395,7 @@
"description": "different network namespace",
"allowed": false,
"request": {
"type": "CreateContainer",
"OCI": {
"Version": "1.1.0",
"Annotations": {
@ -519,4 +523,4 @@
}
}
}
]
]

View File

@ -4,6 +4,7 @@
"allowed": true,
"state": {"sandbox_name": "policy-redis-deployment-6674f9448-xjrzf"},
"request": {
"type": "CreateContainer",
"OCI": {
"Annotations": {
"io.katacontainers.pkg.oci.bundle_path": "/run/containerd/io.containerd.runtime.v2.task/k8s.io/4bae4a8e74302a8edfe17424aff0b632cae893687f4d9ad2f2115666899f9a12",
@ -279,6 +280,7 @@
"allowed": false,
"state": {"sandbox_name": "policy-redis-deployment-6674f9448-xjrzf"},
"request": {
"type": "CreateContainer",
"OCI": {
"Annotations": {
"io.katacontainers.pkg.oci.bundle_path": "/run/containerd/io.containerd.runtime.v2.task/k8s.io/4bae4a8e74302a8edfe17424aff0b632cae893687f4d9ad2f2115666899f9a12",

View File

@ -3,6 +3,7 @@
"description": "no pidns",
"allowed": true,
"request": {
"type": "CreateSandbox",
"sandbox_pidns": false
}
},
@ -10,6 +11,7 @@
"description": "pidns",
"allowed": false,
"request": {
"type": "CreateSandbox",
"sandbox_pidns": true
}
},
@ -17,6 +19,7 @@
"description": "kernel modules",
"allowed": false,
"request": {
"type": "CreateSandbox",
"sandbox_pidns": false,
"kernel_modules": [{"name": "evil.ko"}]
}
@ -25,6 +28,7 @@
"description": "guest hooks",
"allowed": false,
"request": {
"type": "CreateSandbox",
"sandbox_pidns": false,
"guest_hook_path": "/attacker/controlled/path"
}

View File

@ -3,6 +3,7 @@
"description": "no flags",
"allowed": true,
"request": {
"type": "UpdateInterface",
"interface": {
"device": "eth0",
"name": "eth0",
@ -22,6 +23,7 @@
"description": "allowed arp flag",
"allowed": true,
"request": {
"type": "UpdateInterface",
"interface": {
"device": "eth0",
"name": "eth0",
@ -41,6 +43,7 @@
"description": "forbidden flag",
"allowed": false,
"request": {
"type": "UpdateInterface",
"interface": {
"device": "eth0",
"name": "eth0",
@ -60,6 +63,7 @@
"description": "forbidden name",
"allowed": false,
"request": {
"type": "UpdateInterface",
"interface": {
"device": "eth0",
"name": "lo",
@ -79,6 +83,7 @@
"description": "forbidden hwAddr",
"allowed": false,
"request": {
"type": "UpdateInterface",
"interface": {
"device": "eth0",
"name": "eth0",

View File

@ -3,6 +3,7 @@
"description": "compliant routes",
"allowed": true,
"request": {
"type": "UpdateRoutes",
"routes": {
"Routes": [
{
@ -21,6 +22,7 @@
"description": "forbidden device",
"allowed": false,
"request": {
"type": "UpdateRoutes",
"routes": {
"Routes": [
{
@ -39,6 +41,7 @@
"description": "one compliant route, one noncompliant",
"allowed": false,
"request": {
"type": "UpdateRoutes",
"routes": {
"Routes": [
{
@ -65,6 +68,7 @@
"description": "noncompliant routes",
"allowed": false,
"request": {
"type": "UpdateRoutes",
"routes": {
"Routes": [
{
@ -83,6 +87,7 @@
"description": "noncompliant routes ipv6 1",
"allowed": false,
"request": {
"type": "UpdateRoutes",
"routes": {
"Routes": [
{
@ -101,6 +106,7 @@
"description": "noncompliant routes ipv6 2",
"allowed": false,
"request": {
"type": "UpdateRoutes",
"routes": {
"Routes": [
{