Skip to content

Commit

Permalink
Merge pull request kata-containers#128 from microsoft/saulparedes/add…
Browse files Browse the repository at this point in the history
…_envfrom

genpolicy: Add support for envFrom
  • Loading branch information
Redent0r committed Jan 17, 2024
2 parents 74a9b96 + f11daf7 commit 7959347
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 1 deletion.
33 changes: 33 additions & 0 deletions src/agent/samples/policy/yaml/configmap/pod-cm3.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/pod/pod-ubuntu.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/tools/genpolicy/policy_samples.json
Expand Up @@ -2,6 +2,7 @@
"default": [
"configmap/pod-cm1.yaml",
"configmap/pod-cm2.yaml",
"configmap/pod-cm3.yaml",
"deployment/deployment-azure-vote-back.yaml",
"deployment/deployment-azure-vote-front.yaml",
"deployment/deployment-busybox.yaml",
Expand Down
25 changes: 25 additions & 0 deletions src/tools/genpolicy/src/config_map.rs
Expand Up @@ -64,6 +64,19 @@ impl ConfigMap {

None
}

pub fn get_key_value_pairs(&self) -> Option<Vec<String>> {
//eg ["key1=value1", "key2=value2"]
self.data
.as_ref()?
.keys()
.map(|key| {
let value = self.data.as_ref().unwrap().get(key).unwrap();
format!("{key}={value}")
})
.collect::<Vec<String>>()
.into()
}
}

pub fn get_value(value_from: &pod::EnvVarSource, config_maps: &Vec<ConfigMap>) -> Option<String> {
Expand All @@ -76,6 +89,18 @@ pub fn get_value(value_from: &pod::EnvVarSource, config_maps: &Vec<ConfigMap>) -
None
}

pub fn get_values(config_map_name: &str, config_maps: &Vec<ConfigMap>) -> Option<Vec<String>> {
for config_map in config_maps {
if let Some(existing_configmap_name) = &config_map.metadata.name {
if config_map_name == existing_configmap_name {
return config_map.get_key_value_pairs();
}
}
}

None
}

#[async_trait]
impl yaml::K8sResource for ConfigMap {
async fn init(
Expand Down
77 changes: 77 additions & 0 deletions src/tools/genpolicy/src/pod.rs
Expand Up @@ -103,6 +103,9 @@ pub struct Container {
#[serde(skip_serializing_if = "Option::is_none")]
env: Option<Vec<EnvVar>>,

#[serde(skip_serializing_if = "Option::is_none")]
envFrom: Option<Vec<EnvFromSource>>,

#[serde(skip_serializing_if = "Option::is_none")]
resources: Option<ResourceRequirements>,

Expand Down Expand Up @@ -373,6 +376,37 @@ pub struct ConfigMapKeySelector {
optional: Option<bool>,
}

/// See Reference / Kubernetes API / Workload Resources / Pod.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EnvFromSource {
#[serde(skip_serializing_if = "Option::is_none")]
pub configMapRef: Option<ConfigMapEnvSource>,

#[serde(skip_serializing_if = "Option::is_none")]
pub secretRef: Option<SecretEnvSource>,

#[serde(skip_serializing_if = "Option::is_none")]
pub prefix: Option<String>,
}

/// See Reference / Kubernetes API / Workload Resources / Pod.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SecretEnvSource {
pub name: String,

#[serde(skip_serializing_if = "Option::is_none")]
optional: Option<bool>,
}

/// See Reference / Kubernetes API / Workload Resources / Pod.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ConfigMapEnvSource {
pub name: String,

#[serde(skip_serializing_if = "Option::is_none")]
optional: Option<bool>,
}

/// See Reference / Kubernetes API / Common Definitions / ResourceFieldSelector.
#[derive(Clone, Debug, Serialize, Deserialize)]
struct ResourceFieldSelector {
Expand Down Expand Up @@ -498,6 +532,21 @@ impl Container {
}
}
}

if let Some(env_from_sources) = &self.envFrom {
for env_from_source in env_from_sources {
let env_from_source_values = env_from_source.get_values(
config_maps,
secrets,
);

for value in env_from_source_values {
if !dest_env.contains(&value) {
dest_env.push(value.clone());
}
}
}
}
}

pub fn is_privileged(&self) -> bool {
Expand Down Expand Up @@ -588,6 +637,34 @@ impl Container {
}
}

impl EnvFromSource {
pub fn get_values(
&self,
config_maps: &Vec<config_map::ConfigMap>,
secrets: &Vec<secret::Secret>,
) -> Vec<String> {

if let Some(config_map_env_source) = &self.configMapRef {
if let Some(value) = config_map::get_values(&config_map_env_source.name, config_maps) {
return value.clone();
}
else {
panic!("Couldn't get values from configmap ref: {}", &config_map_env_source.name);
}
}

if let Some(secret_env_source) = &self.secretRef {
if let Some(value) = secret::get_values(&secret_env_source.name, secrets) {
return value.clone();
}
else {
panic!("Couldn't get values from secret ref: {}", &secret_env_source.name);
}
}
panic!("envFrom: no configmap or secret source found!");
}
}

impl EnvVar {
pub fn get_value(
&self,
Expand Down
27 changes: 27 additions & 0 deletions src/tools/genpolicy/src/secret.rs
Expand Up @@ -56,6 +56,21 @@ impl Secret {

None
}

pub fn get_key_value_pairs(&self) -> Option<Vec<String>> {
//eg ["key1=secret1", "key2=secret2"]
self.data
.as_ref()?
.keys()
.map(|key| {
let value = self.data.as_ref().unwrap().get(key).unwrap();
let value_bytes = general_purpose::STANDARD.decode(&value).unwrap();
let value_string = std::str::from_utf8(&value_bytes).unwrap();
format!("{key}={value_string}")
})
.collect::<Vec<String>>()
.into()
}
}

pub fn get_value(value_from: &pod::EnvVarSource, secrets: &Vec<Secret>) -> Option<String> {
Expand All @@ -68,6 +83,18 @@ pub fn get_value(value_from: &pod::EnvVarSource, secrets: &Vec<Secret>) -> Optio
None
}

pub fn get_values(secret_name: &str, secrets: &Vec<Secret>) -> Option<Vec<String>> {
for secret in secrets {
if let Some(existing_secret_name) = &secret.metadata.name {
if existing_secret_name == secret_name {
return secret.get_key_value_pairs();
}
}
}

None
}

#[async_trait]
impl yaml::K8sResource for Secret {
async fn init(&mut self, _use_cache: bool, doc_mapping: &serde_yaml::Value, _silent: bool) {
Expand Down

0 comments on commit 7959347

Please sign in to comment.