From d84300f1ee47963a0b882ce3d8a9d69966968eea Mon Sep 17 00:00:00 2001 From: Dan Mihai Date: Wed, 18 Oct 2023 20:58:37 +0000 Subject: [PATCH] genpolicy: add support for List YAML input Generate policy for K8s List YAML. Signed-off-by: Dan Mihai --- src/tools/genpolicy/src/list.rs | 103 ++++++++++++++++++++++++++++++++ src/tools/genpolicy/src/main.rs | 1 + src/tools/genpolicy/src/yaml.rs | 9 +++ 3 files changed, 113 insertions(+) create mode 100644 src/tools/genpolicy/src/list.rs diff --git a/src/tools/genpolicy/src/list.rs b/src/tools/genpolicy/src/list.rs new file mode 100644 index 000000000..1722fad3f --- /dev/null +++ b/src/tools/genpolicy/src/list.rs @@ -0,0 +1,103 @@ +// Copyright (c) 2023 Microsoft Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +// Allow K8s YAML field names. +#![allow(non_snake_case)] + +use crate::pod; +use crate::policy; +use crate::settings; +use crate::yaml; + +use async_trait::async_trait; +use core::fmt::Debug; +use protocols::agent; +use serde::{Deserialize, Serialize}; +use serde_yaml::Value; +use std::boxed; +use std::collections::BTreeMap; +use std::marker::{Send, Sync}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct List { + apiVersion: String, + kind: String, + + items: Vec, + + #[serde(skip)] + resources: Vec>, +} + +impl Debug for dyn yaml::K8sResource + Send + Sync { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "K8sResource") + } +} + +#[async_trait] +impl yaml::K8sResource for List { + async fn init(&mut self, use_cache: bool, _doc_mapping: &serde_yaml::Value, silent: bool) { + // Create K8sResource objects for each item in this List. + for item in &self.items { + let yaml_string = serde_yaml::to_string(&item).unwrap(); + let (mut resource, _kind) = yaml::new_k8s_resource(&yaml_string, silent).unwrap(); + resource.init(use_cache, item, silent).await; + self.resources.push(resource); + } + } + + fn get_sandbox_name(&self) -> Option { + panic!("Unsupported"); + } + + fn get_namespace(&self) -> String { + panic!("Unsupported"); + } + + fn get_container_mounts_and_storages( + &self, + _policy_mounts: &mut Vec, + _storages: &mut Vec, + _container: &pod::Container, + _settings: &settings::Settings, + ) { + } + + fn generate_policy(&self, agent_policy: &policy::AgentPolicy) -> String { + let mut policies: Vec = Vec::new(); + for resource in &self.resources { + policies.push(resource.generate_policy(agent_policy)); + } + policies.join(":") + } + + fn serialize(&mut self, policy: &str) -> String { + let policies: Vec<&str> = policy.split(":").collect(); + let len = policies.len(); + assert!(len == self.resources.len()); + + self.items.clear(); + for i in 0..len { + let yaml = self.resources[i].serialize(policies[i]); + let document = serde_yaml::Deserializer::from_str(&yaml); + let doc_value = Value::deserialize(document).unwrap(); + self.items.push(doc_value.clone()); + } + serde_yaml::to_string(&self).unwrap() + } + + fn get_containers(&self) -> &Vec { + panic!("Unsupported"); + } + + fn get_annotations(&self) -> &Option> { + panic!("Unsupported"); + } + + fn use_host_network(&self) -> bool { + panic!("Unsupported"); + } +} diff --git a/src/tools/genpolicy/src/main.rs b/src/tools/genpolicy/src/main.rs index 9ba22588b..19ef76653 100644 --- a/src/tools/genpolicy/src/main.rs +++ b/src/tools/genpolicy/src/main.rs @@ -12,6 +12,7 @@ mod containerd; mod daemon_set; mod deployment; mod job; +mod list; mod mount_and_storage; mod no_policy; mod obj_meta; diff --git a/src/tools/genpolicy/src/yaml.rs b/src/tools/genpolicy/src/yaml.rs index 79dab42ce..5373e3bf0 100644 --- a/src/tools/genpolicy/src/yaml.rs +++ b/src/tools/genpolicy/src/yaml.rs @@ -10,6 +10,7 @@ use crate::config_map; use crate::daemon_set; use crate::deployment; use crate::job; +use crate::list; use crate::mount_and_storage; use crate::no_policy; use crate::pod; @@ -126,6 +127,14 @@ pub fn new_k8s_resource( debug!("{:#?}", &job); Ok((boxed::Box::new(job), header.kind)) } + "List" => { + let list: list::List = serde_ignored::deserialize(d, |path| { + handle_unused_field(&path.to_string(), silent_unsupported_fields); + }) + .unwrap(); + debug!("{:#?}", &list); + Ok((boxed::Box::new(list), header.kind)) + } "Pod" => { let pod: pod::Pod = serde_ignored::deserialize(d, |path| { handle_unused_field(&path.to_string(), silent_unsupported_fields);