mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-28 16:27:50 +00:00
genpolicy: add ability to filter for runtimeClassName
Add the CLI flag --runtime-class-names, which is used during policy generation. For resources that can define a runtimeClassName (e.g., Pods, Deployments, ReplicaSets,...) the value must have any of the --runtime-class-names as prefix, otherwise the resource is ignored. This allows to run genpolicy on larger yaml files defining many different resources and only generating a policy for resources which will be deployed in a confidential context. Signed-off-by: Leonard Cohnen <lc@edgeless.systems>
This commit is contained in:
parent
2f686b1179
commit
1d1690e2a4
@ -140,4 +140,13 @@ impl yaml::K8sResource for DaemonSet {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_runtime_class_name(&self) -> Option<String> {
|
||||||
|
self.spec
|
||||||
|
.template
|
||||||
|
.spec
|
||||||
|
.runtimeClassName
|
||||||
|
.clone()
|
||||||
|
.or_else(|| Some(String::new()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,4 +138,13 @@ impl yaml::K8sResource for Deployment {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_runtime_class_name(&self) -> Option<String> {
|
||||||
|
self.spec
|
||||||
|
.template
|
||||||
|
.spec
|
||||||
|
.runtimeClassName
|
||||||
|
.clone()
|
||||||
|
.or_else(|| Some(String::new()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ pub struct PodSpec {
|
|||||||
restartPolicy: Option<String>,
|
restartPolicy: Option<String>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
runtimeClassName: Option<String>,
|
pub runtimeClassName: Option<String>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub initContainers: Option<Vec<Container>>,
|
pub initContainers: Option<Vec<Container>>,
|
||||||
@ -755,6 +755,13 @@ impl yaml::K8sResource for Pod {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_runtime_class_name(&self) -> Option<String> {
|
||||||
|
self.spec
|
||||||
|
.runtimeClassName
|
||||||
|
.clone()
|
||||||
|
.or_else(|| Some(String::new()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Container {
|
impl Container {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
use crate::config_map;
|
use crate::config_map;
|
||||||
use crate::containerd;
|
use crate::containerd;
|
||||||
use crate::mount_and_storage;
|
use crate::mount_and_storage;
|
||||||
|
use crate::no_policy;
|
||||||
use crate::pod;
|
use crate::pod;
|
||||||
use crate::policy;
|
use crate::policy;
|
||||||
use crate::registry;
|
use crate::registry;
|
||||||
@ -380,6 +381,22 @@ impl AgentPolicy {
|
|||||||
let yaml_string = serde_yaml::to_string(&doc_mapping)?;
|
let yaml_string = serde_yaml::to_string(&doc_mapping)?;
|
||||||
let silent = config.silent_unsupported_fields;
|
let silent = config.silent_unsupported_fields;
|
||||||
let (mut resource, kind) = yaml::new_k8s_resource(&yaml_string, silent)?;
|
let (mut resource, kind) = yaml::new_k8s_resource(&yaml_string, silent)?;
|
||||||
|
|
||||||
|
// Filter out resources that don't match the runtime class name.
|
||||||
|
if let Some(resource_runtime_name) = resource.get_runtime_class_name() {
|
||||||
|
if !config.runtime_class_names.is_empty()
|
||||||
|
&& !config
|
||||||
|
.runtime_class_names
|
||||||
|
.iter()
|
||||||
|
.any(|prefix| resource_runtime_name.starts_with(prefix))
|
||||||
|
{
|
||||||
|
resource =
|
||||||
|
boxed::Box::new(no_policy::NoPolicyResource { yaml: yaml_string });
|
||||||
|
resources.push(resource);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resource.init(config, &doc_mapping, silent).await;
|
resource.init(config, &doc_mapping, silent).await;
|
||||||
|
|
||||||
// ConfigMap and Secret documents contain additional input for policy generation.
|
// ConfigMap and Secret documents contain additional input for policy generation.
|
||||||
|
@ -185,6 +185,15 @@ impl yaml::K8sResource for StatefulSet {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_runtime_class_name(&self) -> Option<String> {
|
||||||
|
self.spec
|
||||||
|
.template
|
||||||
|
.spec
|
||||||
|
.runtimeClassName
|
||||||
|
.clone()
|
||||||
|
.or_else(|| Some(String::new()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatefulSet {
|
impl StatefulSet {
|
||||||
|
@ -82,6 +82,12 @@ struct CommandLineOptions {
|
|||||||
help = "Registry that uses plain HTTP. Can be passed more than once to configure multiple insecure registries."
|
help = "Registry that uses plain HTTP. Can be passed more than once to configure multiple insecure registries."
|
||||||
)]
|
)]
|
||||||
insecure_registry: Vec<String>,
|
insecure_registry: Vec<String>,
|
||||||
|
|
||||||
|
#[clap(
|
||||||
|
long,
|
||||||
|
help = "If specified, resources that have a runtimeClassName field defined will only receive a policy if the parameter is a prefix one of the given runtime class names."
|
||||||
|
)]
|
||||||
|
runtime_class_names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Application configuration, derived from on command line parameters.
|
/// Application configuration, derived from on command line parameters.
|
||||||
@ -89,6 +95,7 @@ struct CommandLineOptions {
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub use_cache: bool,
|
pub use_cache: bool,
|
||||||
pub insecure_registries: Vec<String>,
|
pub insecure_registries: Vec<String>,
|
||||||
|
pub runtime_class_names: Vec<String>,
|
||||||
|
|
||||||
pub yaml_file: Option<String>,
|
pub yaml_file: Option<String>,
|
||||||
pub rego_rules_path: String,
|
pub rego_rules_path: String,
|
||||||
@ -121,6 +128,7 @@ impl Config {
|
|||||||
Self {
|
Self {
|
||||||
use_cache: args.use_cached_files,
|
use_cache: args.use_cached_files,
|
||||||
insecure_registries: args.insecure_registry,
|
insecure_registries: args.insecure_registry,
|
||||||
|
runtime_class_names: args.runtime_class_names,
|
||||||
yaml_file: args.yaml_file,
|
yaml_file: args.yaml_file,
|
||||||
rego_rules_path: args.rego_rules_path,
|
rego_rules_path: args.rego_rules_path,
|
||||||
settings,
|
settings,
|
||||||
|
@ -90,6 +90,10 @@ pub trait K8sResource {
|
|||||||
fn use_sandbox_pidns(&self) -> bool {
|
fn use_sandbox_pidns(&self) -> bool {
|
||||||
panic!("Unsupported");
|
panic!("Unsupported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_runtime_class_name(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See Reference / Kubernetes API / Common Definitions / LabelSelector.
|
/// See Reference / Kubernetes API / Common Definitions / LabelSelector.
|
||||||
|
@ -17,13 +17,22 @@ setup() {
|
|||||||
get_pod_config_dir
|
get_pod_config_dir
|
||||||
|
|
||||||
correct_configmap_yaml="${pod_config_dir}/k8s-policy-configmap.yaml"
|
correct_configmap_yaml="${pod_config_dir}/k8s-policy-configmap.yaml"
|
||||||
|
pre_generate_configmap_yaml="${pod_config_dir}/k8s-policy-configmap-pre-generation.yaml"
|
||||||
incorrect_configmap_yaml="${pod_config_dir}/k8s-policy-configmap-incorrect.yaml"
|
incorrect_configmap_yaml="${pod_config_dir}/k8s-policy-configmap-incorrect.yaml"
|
||||||
|
testcase_pre_generate_configmap_yaml="${pod_config_dir}/k8s-policy-configmap-testcase-pre-generation.yaml"
|
||||||
|
|
||||||
correct_pod_yaml="${pod_config_dir}/k8s-policy-pod.yaml"
|
correct_pod_yaml="${pod_config_dir}/k8s-policy-pod.yaml"
|
||||||
|
pre_generate_pod_yaml="${pod_config_dir}/k8s-policy-pod-pre-generation.yaml"
|
||||||
incorrect_pod_yaml="${pod_config_dir}/k8s-policy-pod-incorrect.yaml"
|
incorrect_pod_yaml="${pod_config_dir}/k8s-policy-pod-incorrect.yaml"
|
||||||
|
testcase_pre_generate_pod_yaml="${pod_config_dir}/k8s-policy-pod-testcase-pre-generation.yaml"
|
||||||
|
|
||||||
|
|
||||||
# Save some time by executing genpolicy a single time.
|
# Save some time by executing genpolicy a single time.
|
||||||
if [ "${BATS_TEST_NUMBER}" == "1" ]; then
|
if [ "${BATS_TEST_NUMBER}" == "1" ]; then
|
||||||
|
# Save pre-generated yaml files
|
||||||
|
cp "${correct_configmap_yaml}" "${pre_generate_configmap_yaml}"
|
||||||
|
cp "${correct_pod_yaml}" "${pre_generate_pod_yaml}"
|
||||||
|
|
||||||
# Add policy to the correct pod yaml file
|
# Add policy to the correct pod yaml file
|
||||||
auto_generate_policy "${pod_config_dir}" "${correct_pod_yaml}" "${correct_configmap_yaml}"
|
auto_generate_policy "${pod_config_dir}" "${correct_pod_yaml}" "${correct_configmap_yaml}"
|
||||||
fi
|
fi
|
||||||
@ -31,6 +40,10 @@ setup() {
|
|||||||
# Start each test case with a copy of the correct yaml files.
|
# Start each test case with a copy of the correct yaml files.
|
||||||
cp "${correct_configmap_yaml}" "${incorrect_configmap_yaml}"
|
cp "${correct_configmap_yaml}" "${incorrect_configmap_yaml}"
|
||||||
cp "${correct_pod_yaml}" "${incorrect_pod_yaml}"
|
cp "${correct_pod_yaml}" "${incorrect_pod_yaml}"
|
||||||
|
|
||||||
|
# Also give each testcase a copy of the pre-generated yaml files.
|
||||||
|
cp "${pre_generate_configmap_yaml}" "${testcase_pre_generate_configmap_yaml}"
|
||||||
|
cp "${pre_generate_pod_yaml}" "${testcase_pre_generate_pod_yaml}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "Successful pod with auto-generated policy" {
|
@test "Successful pod with auto-generated policy" {
|
||||||
@ -39,6 +52,17 @@ setup() {
|
|||||||
kubectl wait --for=condition=Ready "--timeout=${timeout}" pod "${pod_name}"
|
kubectl wait --for=condition=Ready "--timeout=${timeout}" pod "${pod_name}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "Successful pod with auto-generated policy and runtimeClassName filter" {
|
||||||
|
runtime_class_name=$(yq read "${testcase_pre_generate_pod_yaml}" "spec.runtimeClassName")
|
||||||
|
|
||||||
|
auto_generate_policy "${pod_config_dir}" "${testcase_pre_generate_pod_yaml}" "${testcase_pre_generate_configmap_yaml}" \
|
||||||
|
"--runtime-class-names=other-runtime-class-name --runtime-class-names=${runtime_class_name}"
|
||||||
|
|
||||||
|
kubectl create -f "${testcase_pre_generate_configmap_yaml}"
|
||||||
|
kubectl create -f "${testcase_pre_generate_pod_yaml}"
|
||||||
|
kubectl wait --for=condition=Ready "--timeout=${timeout}" pod "${pod_name}"
|
||||||
|
}
|
||||||
|
|
||||||
# Common function for several test cases from this bats script.
|
# Common function for several test cases from this bats script.
|
||||||
test_pod_policy_error() {
|
test_pod_policy_error() {
|
||||||
kubectl create -f "${correct_configmap_yaml}"
|
kubectl create -f "${correct_configmap_yaml}"
|
||||||
@ -143,6 +167,17 @@ test_pod_policy_error() {
|
|||||||
waitForProcess "${wait_time}" "$sleep_time" "${command}" | grep -v "Message:"
|
waitForProcess "${wait_time}" "$sleep_time" "${command}" | grep -v "Message:"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "RuntimeClassName filter: no policy" {
|
||||||
|
# The policy should not be generated because the pod spec does not have a runtimeClassName.
|
||||||
|
runtime_class_name=$(yq read "${testcase_pre_generate_pod_yaml}" "spec.runtimeClassName")
|
||||||
|
|
||||||
|
auto_generate_policy "${pod_config_dir}" "${testcase_pre_generate_pod_yaml}" "${testcase_pre_generate_configmap_yaml}" \
|
||||||
|
"--runtime-class-names=other-${runtime_class_name}"
|
||||||
|
|
||||||
|
# Check that the pod yaml does not contain a policy annotation.
|
||||||
|
run ! grep -q "io.katacontainers.config.agent.policy" "${testcase_pre_generate_pod_yaml}"
|
||||||
|
}
|
||||||
|
|
||||||
teardown() {
|
teardown() {
|
||||||
auto_generate_policy_enabled || skip "Auto-generated policy tests are disabled."
|
auto_generate_policy_enabled || skip "Auto-generated policy tests are disabled."
|
||||||
|
|
||||||
@ -154,4 +189,6 @@ teardown() {
|
|||||||
kubectl delete configmap "${configmap_name}"
|
kubectl delete configmap "${configmap_name}"
|
||||||
rm -f "${incorrect_pod_yaml}"
|
rm -f "${incorrect_pod_yaml}"
|
||||||
rm -f "${incorrect_configmap_yaml}"
|
rm -f "${incorrect_configmap_yaml}"
|
||||||
|
rm -f "${testcase_pre_generate_pod_yaml}"
|
||||||
|
rm -f "${testcase_pre_generate_configmap_yaml}"
|
||||||
}
|
}
|
||||||
|
@ -171,6 +171,7 @@ auto_generate_policy() {
|
|||||||
declare -r settings_dir="$1"
|
declare -r settings_dir="$1"
|
||||||
declare -r yaml_file="$2"
|
declare -r yaml_file="$2"
|
||||||
declare -r config_map_yaml_file="$3"
|
declare -r config_map_yaml_file="$3"
|
||||||
|
declare -r additional_flags="$4"
|
||||||
|
|
||||||
auto_generate_policy_enabled || return 0
|
auto_generate_policy_enabled || return 0
|
||||||
local genpolicy_command="RUST_LOG=info /opt/kata/bin/genpolicy -u -y ${yaml_file}"
|
local genpolicy_command="RUST_LOG=info /opt/kata/bin/genpolicy -u -y ${yaml_file}"
|
||||||
@ -185,6 +186,8 @@ auto_generate_policy() {
|
|||||||
genpolicy_command+=" -d"
|
genpolicy_command+=" -d"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
genpolicy_command+=" ${additional_flags}"
|
||||||
|
|
||||||
info "Executing: ${genpolicy_command}"
|
info "Executing: ${genpolicy_command}"
|
||||||
eval "${genpolicy_command}"
|
eval "${genpolicy_command}"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user