mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-01 07:47:15 +00:00
Merge pull request #9706 from burgerdev/burgerdev/genpolicy-devices
genpolicy: add support for devices
This commit is contained in:
commit
56423cbbfe
@ -54,6 +54,7 @@ default AllowRequestsFailingPolicy := false
|
||||
CreateContainerRequest {
|
||||
i_oci := input.OCI
|
||||
i_storages := input.storages
|
||||
i_devices := input.devices
|
||||
|
||||
some p_container in policy_data.containers
|
||||
print("======== CreateContainerRequest: trying next policy container")
|
||||
@ -76,6 +77,9 @@ CreateContainerRequest {
|
||||
p_storages := p_container.storages
|
||||
allow_by_anno(p_oci, i_oci, p_storages, i_storages)
|
||||
|
||||
p_devices := p_container.devices
|
||||
allow_devices(p_devices, i_devices)
|
||||
|
||||
allow_linux(p_oci, i_oci)
|
||||
|
||||
print("CreateContainerRequest: true")
|
||||
@ -327,6 +331,16 @@ allow_log_directory(p_oci, i_oci) {
|
||||
print("allow_log_directory: true")
|
||||
}
|
||||
|
||||
allow_devices(p_devices, i_devices) {
|
||||
print("allow_devices: start")
|
||||
every i_device in i_devices {
|
||||
print("allow_devices: i_device =", i_device)
|
||||
some p_device in p_devices
|
||||
p_device.container_path == i_device.container_path
|
||||
}
|
||||
print("allow_devices: true")
|
||||
}
|
||||
|
||||
allow_linux(p_oci, i_oci) {
|
||||
p_namespaces := p_oci.Linux.Namespaces
|
||||
print("allow_linux: p namespaces =", p_namespaces)
|
||||
@ -338,6 +352,7 @@ allow_linux(p_oci, i_oci) {
|
||||
|
||||
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)
|
||||
|
||||
print("allow_linux: true")
|
||||
}
|
||||
@ -426,6 +441,16 @@ allow_readonly_path(p_elem, i_array, masked_paths) {
|
||||
print("allow_readonly_path 2: true")
|
||||
}
|
||||
|
||||
allow_linux_devices(p_devices, i_devices) {
|
||||
print("allow_linux_devices: start")
|
||||
every i_device in i_devices {
|
||||
print("allow_linux_devices: i_device =", i_device)
|
||||
some p_device in p_devices
|
||||
i_device.Path == p_device.Path
|
||||
}
|
||||
print("allow_linux_devices: true")
|
||||
}
|
||||
|
||||
# Check the consistency of the input "io.katacontainers.pkg.oci.bundle_path"
|
||||
# and io.kubernetes.cri.sandbox-id" values with other fields.
|
||||
allow_by_bundle_or_sandbox_id(p_oci, i_oci, p_storages, i_storages) {
|
||||
|
@ -152,12 +152,14 @@ pub fn get_linux(privileged_container: bool) -> policy::KataLinux {
|
||||
"/proc/sys".to_string(),
|
||||
"/proc/sysrq-trigger".to_string(),
|
||||
],
|
||||
Devices: vec![],
|
||||
}
|
||||
} else {
|
||||
policy::KataLinux {
|
||||
Namespaces: vec![],
|
||||
MaskedPaths: vec![],
|
||||
ReadonlyPaths: vec![],
|
||||
Devices: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ struct PersistentVolumeClaimSpec {
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
storageClassName: Option<String>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
volumeMode: Option<String>,
|
||||
// TODO: additional fields.
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,9 @@ pub struct Container {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub volumeMounts: Option<Vec<VolumeMount>>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub volumeDevices: Option<Vec<VolumeDevice>>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
env: Option<Vec<EnvVar>>,
|
||||
|
||||
@ -422,6 +425,13 @@ pub struct VolumeMount {
|
||||
// TODO: additional fields.
|
||||
}
|
||||
|
||||
/// See Reference / Kubernetes API / Workload Resources / Pod.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct VolumeDevice {
|
||||
pub devicePath: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// See Reference / Kubernetes API / Workload Resources / Pod.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
struct ResourceRequirements {
|
||||
|
@ -180,6 +180,10 @@ pub struct KataLinux {
|
||||
|
||||
/// ReadonlyPaths sets the provided paths as RO inside the container.
|
||||
pub ReadonlyPaths: Vec<String>,
|
||||
|
||||
/// Devices contains devices to be created inside the container.
|
||||
#[serde(default)]
|
||||
pub Devices: Vec<KataLinuxDevice>,
|
||||
}
|
||||
|
||||
/// OCI container LinuxNamespace struct. This struct is similar to the LinuxNamespace
|
||||
@ -195,6 +199,18 @@ pub struct KataLinuxNamespace {
|
||||
pub Path: String,
|
||||
}
|
||||
|
||||
/// OCI container LinuxDevice struct. This struct is similar to the LinuxDevice
|
||||
/// struct generated from oci.proto, but includes just the fields that are currently
|
||||
/// relevant for automatic generation of policy.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||
pub struct KataLinuxDevice {
|
||||
/// Type is the type of device.
|
||||
pub Type: String,
|
||||
|
||||
/// Path is the path where the device should be created.
|
||||
pub Path: String,
|
||||
}
|
||||
|
||||
/// OCI container LinuxCapabilities struct. This struct is very similar to the
|
||||
/// LinuxCapabilities struct generated from oci.proto. The main difference is
|
||||
/// that it preserves the upper case field names from oci.proto, for consistency
|
||||
@ -246,6 +262,9 @@ pub struct ContainerPolicy {
|
||||
/// Data compared with req.storages for CreateContainerRequest calls.
|
||||
storages: Vec<agent::Storage>,
|
||||
|
||||
/// Data compared with req.devices for CreateContainerRequest calls.
|
||||
devices: Vec<agent::Device>,
|
||||
|
||||
/// Data compared with req.sandbox_pidns for CreateContainerRequest calls.
|
||||
sandbox_pidns: bool,
|
||||
|
||||
@ -556,6 +575,23 @@ impl AgentPolicy {
|
||||
};
|
||||
let exec_commands = yaml_container.get_exec_commands();
|
||||
|
||||
let mut devices: Vec<agent::Device> = vec![];
|
||||
if let Some(volumeDevices) = &yaml_container.volumeDevices {
|
||||
for volumeDevice in volumeDevices {
|
||||
let mut device = agent::Device::new();
|
||||
device.set_container_path(volumeDevice.devicePath.clone());
|
||||
devices.push(device);
|
||||
|
||||
linux.Devices.push(KataLinuxDevice {
|
||||
Type: "".to_string(),
|
||||
Path: volumeDevice.devicePath.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
for default_device in &c_settings.Linux.Devices {
|
||||
linux.Devices.push(default_device.clone())
|
||||
}
|
||||
|
||||
ContainerPolicy {
|
||||
OCI: KataSpec {
|
||||
Version: self.config.settings.kata_config.oci_version.clone(),
|
||||
@ -567,6 +603,7 @@ impl AgentPolicy {
|
||||
Linux: linux,
|
||||
},
|
||||
storages,
|
||||
devices,
|
||||
sandbox_pidns,
|
||||
exec_commands,
|
||||
}
|
||||
|
66
tests/integration/kubernetes/k8s-policy-pvc.bats
Normal file
66
tests/integration/kubernetes/k8s-policy-pvc.bats
Normal file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env bats
|
||||
#
|
||||
# Copyright (c) 2024 Edgeless Systems GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
load "${BATS_TEST_DIRNAME}/../../common.bash"
|
||||
load "${BATS_TEST_DIRNAME}/tests_common.sh"
|
||||
|
||||
setup() {
|
||||
auto_generate_policy_enabled || skip "Auto-generated policy tests are disabled."
|
||||
|
||||
pod_name="policy-pod-pvc"
|
||||
pvc_name="policy-dev"
|
||||
|
||||
get_pod_config_dir
|
||||
|
||||
correct_pod_yaml="${pod_config_dir}/k8s-policy-pod-pvc.yaml"
|
||||
incorrect_pod_yaml="${pod_config_dir}/k8s-policy-pod-pvc-incorrect.yaml"
|
||||
pvc_yaml="${pod_config_dir}/k8s-policy-pvc.yaml"
|
||||
|
||||
# Save some time by executing genpolicy a single time.
|
||||
if [ "${BATS_TEST_NUMBER}" == "1" ]; then
|
||||
# Add policy to the correct pod yaml file
|
||||
auto_generate_policy "${pod_config_dir}" "${correct_pod_yaml}"
|
||||
fi
|
||||
|
||||
# Start each test case with a copy of the correct yaml files.
|
||||
cp "${correct_pod_yaml}" "${incorrect_pod_yaml}"
|
||||
}
|
||||
|
||||
@test "Successful pod with auto-generated policy" {
|
||||
kubectl create -f "${correct_pod_yaml}"
|
||||
kubectl create -f "${pvc_yaml}"
|
||||
kubectl wait --for=condition=Ready "--timeout=${timeout}" pod "${pod_name}"
|
||||
}
|
||||
|
||||
# Common function for several test cases from this bats script.
|
||||
test_pod_policy_error() {
|
||||
kubectl create -f "${incorrect_pod_yaml}"
|
||||
kubectl create -f "${pvc_yaml}"
|
||||
wait_for_blocked_request "CreateContainerRequest" "${pod_name}"
|
||||
}
|
||||
|
||||
@test "Policy failure: unexpected device mount" {
|
||||
# Changing the location of a mounted device after policy generation should fail the policy check.
|
||||
yq write -i \
|
||||
"${incorrect_pod_yaml}" \
|
||||
"spec.containers[0].volumeDevices.[0].devicePath" \
|
||||
"/dev/unexpected"
|
||||
|
||||
test_pod_policy_error
|
||||
}
|
||||
|
||||
teardown() {
|
||||
auto_generate_policy_enabled || skip "Auto-generated policy tests are disabled."
|
||||
|
||||
# Debugging information. Don't print the "Message:" line because it contains a truncated policy log.
|
||||
kubectl describe pod "${pod_name}" | grep -v "Message:"
|
||||
|
||||
# Clean-up
|
||||
kubectl delete -f "${correct_pod_yaml}"
|
||||
kubectl delete -f "${pvc_yaml}"
|
||||
rm -f "${incorrect_pod_yaml}"
|
||||
}
|
@ -55,6 +55,7 @@ else
|
||||
"k8s-pod-quota.bats" \
|
||||
"k8s-policy-job.bats" \
|
||||
"k8s-policy-pod.bats" \
|
||||
"k8s-policy-pvc.bats" \
|
||||
"k8s-policy-rc.bats" \
|
||||
"k8s-port-forward.bats" \
|
||||
"k8s-projected-volume.bats" \
|
||||
|
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2024 Edgeless Systems GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: policy-pod-pvc
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 0
|
||||
runtimeClassName: kata
|
||||
containers:
|
||||
- name: busybox
|
||||
image: "quay.io/prometheus/busybox:latest"
|
||||
volumeDevices:
|
||||
- name: dev
|
||||
devicePath: /dev/csi0
|
||||
volumes:
|
||||
- name: dev
|
||||
persistentVolumeClaim:
|
||||
claimName: policy-dev
|
@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2024 Edgeless Systems GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: policy-dev
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
volumeMode: Block
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Mi
|
Loading…
Reference in New Issue
Block a user