mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-06 12:06:49 +00:00
Merge pull request #10986 from 3u13r/euler/feat/genpolicy/env-from-secret
genpolicy: support secrets to be referenced for pod envs
This commit is contained in:
commit
835f59df2f
88
src/tools/genpolicy/Cargo.lock
generated
88
src/tools/genpolicy/Cargo.lock
generated
@ -41,6 +41,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.69"
|
version = "1.0.69"
|
||||||
@ -53,6 +59,22 @@ version = "1.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "assert_cmd"
|
||||||
|
version = "2.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"bstr",
|
||||||
|
"doc-comment",
|
||||||
|
"libc",
|
||||||
|
"predicates",
|
||||||
|
"predicates-core",
|
||||||
|
"predicates-tree",
|
||||||
|
"wait-timeout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.68"
|
version = "0.1.68"
|
||||||
@ -169,6 +191,17 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.12.0"
|
version = "3.12.0"
|
||||||
@ -451,6 +484,12 @@ dependencies = [
|
|||||||
"syn 2.0.58",
|
"syn 2.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "difflib"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
@ -462,6 +501,12 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "doc-comment"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "docker_credential"
|
name = "docker_credential"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
@ -699,6 +744,7 @@ name = "genpolicy"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"assert_cmd",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1580,6 +1626,33 @@ version = "0.2.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates"
|
||||||
|
version = "3.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"difflib",
|
||||||
|
"predicates-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-core"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-tree"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c"
|
||||||
|
dependencies = [
|
||||||
|
"predicates-core",
|
||||||
|
"termtree",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettyplease"
|
name = "prettyplease"
|
||||||
version = "0.1.25"
|
version = "0.1.25"
|
||||||
@ -2351,6 +2424,12 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termtree"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
@ -2695,6 +2774,15 @@ version = "0.9.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wait-timeout"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -40,14 +40,16 @@ serde_yaml = "0.8"
|
|||||||
anyhow = "1.0.32"
|
anyhow = "1.0.32"
|
||||||
async-trait = "0.1.68"
|
async-trait = "0.1.68"
|
||||||
docker_credential = "1.3.1"
|
docker_credential = "1.3.1"
|
||||||
flate2 = { version = "1.0.26", features = ["zlib-ng"], default-features = false }
|
flate2 = { version = "1.0.26", features = [
|
||||||
|
"zlib-ng",
|
||||||
|
], default-features = false }
|
||||||
libz-ng-sys = "1.1.15" # force newer version that compiles on ppc64le
|
libz-ng-sys = "1.1.15" # force newer version that compiles on ppc64le
|
||||||
oci-client = { version = "0.12.0" }
|
oci-client = { version = "0.12.0" }
|
||||||
openssl = { version = "0.10.72", features = ["vendored"] }
|
openssl = { version = "0.10.72", features = ["vendored"] }
|
||||||
serde_ignored = "0.1.7"
|
serde_ignored = "0.1.7"
|
||||||
serde_json = "1.0.39"
|
serde_json = "1.0.39"
|
||||||
serde-transcode = "1.1.1"
|
serde-transcode = "1.1.1"
|
||||||
tokio = {version = "1.38.0", features = ["rt-multi-thread"]}
|
tokio = { version = "1.38.0", features = ["rt-multi-thread"] }
|
||||||
|
|
||||||
# OCI container specs.
|
# OCI container specs.
|
||||||
oci-spec = { version = "0.6.8", features = ["runtime"] }
|
oci-spec = { version = "0.6.8", features = ["runtime"] }
|
||||||
@ -76,3 +78,4 @@ tar = "0.4.41"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
kata-agent-policy = { path = "../../agent/policy" }
|
kata-agent-policy = { path = "../../agent/policy" }
|
||||||
slog = "2.5.2"
|
slog = "2.5.2"
|
||||||
|
assert_cmd = "2.0.14"
|
||||||
|
@ -13,10 +13,8 @@ use crate::utils::Config;
|
|||||||
use crate::yaml;
|
use crate::yaml;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::debug;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fs::File;
|
|
||||||
|
|
||||||
/// See Reference / Kubernetes API / Config and Storage Resources / ConfigMap.
|
/// See Reference / Kubernetes API / Config and Storage Resources / ConfigMap.
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
@ -41,14 +39,6 @@ pub struct ConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigMap {
|
impl ConfigMap {
|
||||||
pub fn new(file: &str) -> anyhow::Result<Self> {
|
|
||||||
debug!("Reading ConfigMap...");
|
|
||||||
let config_map: ConfigMap = serde_yaml::from_reader(File::open(file)?)?;
|
|
||||||
debug!("\nRead ConfigMap => {:#?}", config_map);
|
|
||||||
|
|
||||||
Ok(config_map)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self, value_from: &pod::EnvVarSource) -> Option<String> {
|
pub fn get_value(&self, value_from: &pod::EnvVarSource) -> Option<String> {
|
||||||
if let Some(key_ref) = &value_from.configMapKeyRef {
|
if let Some(key_ref) = &value_from.configMapKeyRef {
|
||||||
if let Some(name) = &key_ref.name {
|
if let Some(name) = &key_ref.name {
|
||||||
|
@ -438,6 +438,11 @@ pub struct SandboxData {
|
|||||||
pub storages: Vec<agent::Storage>,
|
pub storages: Vec<agent::Storage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum K8sEnvFromSource {
|
||||||
|
ConfigMap(config_map::ConfigMap),
|
||||||
|
Secret(secret::Secret),
|
||||||
|
}
|
||||||
|
|
||||||
impl AgentPolicy {
|
impl AgentPolicy {
|
||||||
pub async fn from_files(config: &utils::Config) -> Result<AgentPolicy> {
|
pub async fn from_files(config: &utils::Config) -> Result<AgentPolicy> {
|
||||||
let mut config_maps = Vec::new();
|
let mut config_maps = Vec::new();
|
||||||
@ -488,9 +493,18 @@ impl AgentPolicy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(config_map_files) = &config.config_map_files {
|
if let Some(config_files) = &config.config_files {
|
||||||
for file in config_map_files {
|
for resource_file in config_files {
|
||||||
config_maps.push(config_map::ConfigMap::new(file)?);
|
for config_resource in parse_config_file(resource_file.to_string(), config).await? {
|
||||||
|
match config_resource {
|
||||||
|
K8sEnvFromSource::ConfigMap(config_map) => {
|
||||||
|
config_maps.push(config_map);
|
||||||
|
}
|
||||||
|
K8sEnvFromSource::Secret(secret) => {
|
||||||
|
secrets.push(secret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,6 +836,37 @@ fn get_image_layer_storages(
|
|||||||
storages.push(overlay_storage);
|
storages.push(overlay_storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn parse_config_file(
|
||||||
|
yaml_file: String,
|
||||||
|
config: &utils::Config,
|
||||||
|
) -> Result<Vec<K8sEnvFromSource>> {
|
||||||
|
let mut k8sRes = Vec::new();
|
||||||
|
let yaml_contents = yaml::get_input_yaml(&Some(yaml_file))?;
|
||||||
|
for document in serde_yaml::Deserializer::from_str(&yaml_contents) {
|
||||||
|
let doc_mapping = Value::deserialize(document)?;
|
||||||
|
if doc_mapping != Value::Null {
|
||||||
|
let yaml_string = serde_yaml::to_string(&doc_mapping)?;
|
||||||
|
let silent = config.silent_unsupported_fields;
|
||||||
|
let (mut resource, kind) = yaml::new_k8s_resource(&yaml_string, silent)?;
|
||||||
|
|
||||||
|
resource.init(config, &doc_mapping, silent).await;
|
||||||
|
|
||||||
|
// ConfigMap and Secret documents contain additional input for policy generation.
|
||||||
|
if kind.eq("ConfigMap") {
|
||||||
|
let config_map: config_map::ConfigMap = serde_yaml::from_str(&yaml_string)?;
|
||||||
|
debug!("{:#?}", &config_map);
|
||||||
|
k8sRes.push(K8sEnvFromSource::ConfigMap(config_map));
|
||||||
|
} else if kind.eq("Secret") {
|
||||||
|
let secret: secret::Secret = serde_yaml::from_str(&yaml_string)?;
|
||||||
|
debug!("{:#?}", &secret);
|
||||||
|
k8sRes.push(K8sEnvFromSource::Secret(secret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(k8sRes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts the given name to a string representation of its sha256 hash.
|
/// Converts the given name to a string representation of its sha256 hash.
|
||||||
fn name_to_hash(name: &str) -> String {
|
fn name_to_hash(name: &str) -> String {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
|
@ -18,10 +18,16 @@ struct CommandLineOptions {
|
|||||||
#[clap(
|
#[clap(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
help = "Optional Kubernetes config map YAML input file path"
|
help = "Optional Kubernetes config map YAML input file path. DEPRECATED: use --config-file instead"
|
||||||
)]
|
)]
|
||||||
config_map_file: Option<String>,
|
config_map_file: Option<String>,
|
||||||
|
|
||||||
|
#[clap(
|
||||||
|
long,
|
||||||
|
help = "Optional Kubernetes YAML input file path containing config resources such as ConfigMaps and Secrets"
|
||||||
|
)]
|
||||||
|
config_file: Option<Vec<String>>,
|
||||||
|
|
||||||
#[clap(
|
#[clap(
|
||||||
short = 'p',
|
short = 'p',
|
||||||
long,
|
long,
|
||||||
@ -111,7 +117,7 @@ pub struct Config {
|
|||||||
pub yaml_file: Option<String>,
|
pub yaml_file: Option<String>,
|
||||||
pub rego_rules_path: String,
|
pub rego_rules_path: String,
|
||||||
pub settings: settings::Settings,
|
pub settings: settings::Settings,
|
||||||
pub config_map_files: Option<Vec<String>>,
|
pub config_files: Option<Vec<String>>,
|
||||||
|
|
||||||
pub silent_unsupported_fields: bool,
|
pub silent_unsupported_fields: bool,
|
||||||
pub raw_out: bool,
|
pub raw_out: bool,
|
||||||
@ -125,16 +131,15 @@ impl Config {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let args = CommandLineOptions::parse();
|
let args = CommandLineOptions::parse();
|
||||||
|
|
||||||
let mut config_map_files = Vec::new();
|
// Migrate all files from the old `config_map_file` to the new `config_files` field
|
||||||
if let Some(config_map_file) = &args.config_map_file {
|
let config_files = args
|
||||||
config_map_files.push(config_map_file.clone());
|
.config_file
|
||||||
}
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.chain(args.config_map_file.iter().cloned())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let cm_files = if !config_map_files.is_empty() {
|
let config_files = (!config_files.is_empty()).then_some(config_files);
|
||||||
Some(config_map_files.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut layers_cache_file_path = args.layers_cache_file_path;
|
let mut layers_cache_file_path = args.layers_cache_file_path;
|
||||||
// preserve backwards compatibility for only using the `use_cached_files` flag
|
// preserve backwards compatibility for only using the `use_cached_files` flag
|
||||||
@ -151,7 +156,7 @@ impl Config {
|
|||||||
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,
|
||||||
config_map_files: cm_files,
|
config_files,
|
||||||
silent_unsupported_fields: args.silent_unsupported_fields,
|
silent_unsupported_fields: args.silent_unsupported_fields,
|
||||||
raw_out: args.raw_out,
|
raw_out: args.raw_out,
|
||||||
base64_out: args.base64_out,
|
base64_out: args.base64_out,
|
||||||
|
99
src/tools/genpolicy/tests/generate/main.rs
Normal file
99
src/tools/genpolicy/tests/generate/main.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright (c) 2025 Edgeless Systems GmbH
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
use assert_cmd::prelude::*;
|
||||||
|
use std::fs::{self};
|
||||||
|
use std::path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_map_in_separate_file_config_map_flag() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Prepare temp dir for running genpolicy.
|
||||||
|
let test_case_dir = "config_map_separate_file_config_map_flag";
|
||||||
|
let pod_yaml_name = "pod_with_config_map_ref.yaml";
|
||||||
|
let config_file = "config_map.yaml";
|
||||||
|
let workdir = prepare_workdir(test_case_dir, &[pod_yaml_name, config_file]);
|
||||||
|
|
||||||
|
let mut cmd = Command::cargo_bin("genpolicy")?;
|
||||||
|
cmd.arg("--yaml-file").arg(workdir.join(pod_yaml_name));
|
||||||
|
cmd.assert().failure();
|
||||||
|
|
||||||
|
let mut cmd = Command::cargo_bin("genpolicy")?;
|
||||||
|
cmd.arg("--yaml-file").arg(workdir.join(pod_yaml_name));
|
||||||
|
cmd.arg("--config-map-file").arg(workdir.join(config_file));
|
||||||
|
cmd.assert().success();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_map_in_separate_file_workdir_flag() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Prepare temp dir for running genpolicy.
|
||||||
|
let test_case_dir = "config_map_separate_file_workdir_flag";
|
||||||
|
let pod_yaml_name = "pod_with_config_map_ref.yaml";
|
||||||
|
let config_file = "config_map.yaml";
|
||||||
|
let workdir = prepare_workdir(test_case_dir, &[pod_yaml_name, config_file]);
|
||||||
|
|
||||||
|
let mut cmd = Command::cargo_bin("genpolicy")?;
|
||||||
|
cmd.arg("--yaml-file").arg(workdir.join(pod_yaml_name));
|
||||||
|
cmd.assert().failure();
|
||||||
|
|
||||||
|
let mut cmd = Command::cargo_bin("genpolicy")?;
|
||||||
|
cmd.arg("--yaml-file").arg(workdir.join(pod_yaml_name));
|
||||||
|
cmd.arg("--config-file").arg(workdir.join(config_file));
|
||||||
|
cmd.assert().success();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn secret_in_separate_file() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Prepare temp dir for running genpolicy.
|
||||||
|
let test_case_dir = "secret_separate_file";
|
||||||
|
let pod_yaml_name = "pod_with_secret_ref.yaml";
|
||||||
|
let config_file = "secret.yaml";
|
||||||
|
let workdir = prepare_workdir(test_case_dir, &[pod_yaml_name, config_file]);
|
||||||
|
|
||||||
|
let mut cmd = Command::cargo_bin("genpolicy")?;
|
||||||
|
cmd.arg("--yaml-file").arg(workdir.join(pod_yaml_name));
|
||||||
|
cmd.assert().failure();
|
||||||
|
|
||||||
|
let mut cmd = Command::cargo_bin("genpolicy")?;
|
||||||
|
cmd.arg("--yaml-file").arg(workdir.join(pod_yaml_name));
|
||||||
|
cmd.arg("--config-file").arg(workdir.join(config_file));
|
||||||
|
cmd.assert().success();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_workdir(test_case_dir: &str, files_to_copy: &[&str]) -> path::PathBuf {
|
||||||
|
// Prepare temp dir for running genpolicy.
|
||||||
|
let workdir = path::PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(test_case_dir);
|
||||||
|
fs::create_dir_all(&workdir)
|
||||||
|
.expect("should be able to create directories under CARGO_TARGET_TMPDIR");
|
||||||
|
|
||||||
|
let testdata_dir =
|
||||||
|
path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/generate/testdata");
|
||||||
|
|
||||||
|
// Make sure that workdir is empty.
|
||||||
|
for entry in fs::read_dir(&workdir).expect("should be able to read directories") {
|
||||||
|
let entry = entry.expect("should be able to read directory entries");
|
||||||
|
fs::remove_file(entry.path()).expect("should be able to remove files");
|
||||||
|
}
|
||||||
|
|
||||||
|
for file in files_to_copy {
|
||||||
|
fs::copy(testdata_dir.join(file), workdir.join(file))
|
||||||
|
.expect("copying files around should not fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
let genpolicy_dir = path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
|
||||||
|
for base in ["rules.rego", "genpolicy-settings.json"] {
|
||||||
|
fs::copy(genpolicy_dir.join(base), workdir.join(base))
|
||||||
|
.expect("copying files around should not fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
workdir
|
||||||
|
}
|
75
src/tools/genpolicy/tests/generate/testdata/config_map.yaml
vendored
Normal file
75
src/tools/genpolicy/tests/generate/testdata/config_map.yaml
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
key: YmFyCg==
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: configmap-sample
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
key: YmFyCg==
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: configmap-sample2
|
||||||
|
---
|
||||||
|
# Add some other yaml document to make sure that we can parse out
|
||||||
|
# ConfigMaps and Secrets from yaml files with multiple documents.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: one-container-config-map
|
||||||
|
labels:
|
||||||
|
run: busybox
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
runtimeClassName: kata-cc
|
||||||
|
containers:
|
||||||
|
- name: busybox
|
||||||
|
image: "quay.io/prometheus/busybox:latest"
|
||||||
|
stdin: true
|
||||||
|
env:
|
||||||
|
- name: ENV_FROM_CONFIGMAP
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: key
|
||||||
|
name: configmap-sample
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: POD_IP
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: status.podIP
|
||||||
|
- name: SERVICE_ACCOUNT
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.serviceAccountName
|
||||||
|
- name: PROXY_CONFIG
|
||||||
|
value: "{}\n"
|
||||||
|
- name: ISTIO_META_POD_PORTS
|
||||||
|
value: "[\n]"
|
||||||
|
- name: ISTIO_META_APP_CONTAINERS
|
||||||
|
value: serviceaclient
|
||||||
|
- name: ISTIO_META_CLUSTER_ID
|
||||||
|
value: Kubernetes
|
||||||
|
- name: ISTIO_META_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
args:
|
||||||
|
- "-c"
|
||||||
|
- while true; do echo $(POD_NAME); sleep 10; done
|
60
src/tools/genpolicy/tests/generate/testdata/pod_with_config_map_ref.yaml
vendored
Normal file
60
src/tools/genpolicy/tests/generate/testdata/pod_with_config_map_ref.yaml
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: one-container
|
||||||
|
labels:
|
||||||
|
run: busybox
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
runtimeClassName: kata-cc
|
||||||
|
containers:
|
||||||
|
- name: busybox
|
||||||
|
image: "quay.io/prometheus/busybox:latest"
|
||||||
|
stdin: true
|
||||||
|
env:
|
||||||
|
- name: ENV_FROM_CONFIGMAP
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: key
|
||||||
|
name: configmap-sample
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: POD_IP
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: status.podIP
|
||||||
|
- name: SERVICE_ACCOUNT
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.serviceAccountName
|
||||||
|
- name: PROXY_CONFIG
|
||||||
|
value: "{}\n"
|
||||||
|
- name: ISTIO_META_POD_PORTS
|
||||||
|
value: "[\n]"
|
||||||
|
- name: ISTIO_META_APP_CONTAINERS
|
||||||
|
value: serviceaclient
|
||||||
|
- name: ISTIO_META_CLUSTER_ID
|
||||||
|
value: Kubernetes
|
||||||
|
- name: ISTIO_META_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
args:
|
||||||
|
- "-c"
|
||||||
|
- while true; do echo $(POD_NAME); sleep 10; done
|
60
src/tools/genpolicy/tests/generate/testdata/pod_with_secret_ref.yaml
vendored
Normal file
60
src/tools/genpolicy/tests/generate/testdata/pod_with_secret_ref.yaml
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: one-container
|
||||||
|
labels:
|
||||||
|
run: busybox
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
runtimeClassName: kata-cc
|
||||||
|
containers:
|
||||||
|
- name: busybox
|
||||||
|
image: "quay.io/prometheus/busybox:latest"
|
||||||
|
stdin: true
|
||||||
|
env:
|
||||||
|
- name: ENV_FROM_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: key
|
||||||
|
name: secret-sample
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: POD_IP
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: status.podIP
|
||||||
|
- name: SERVICE_ACCOUNT
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.serviceAccountName
|
||||||
|
- name: PROXY_CONFIG
|
||||||
|
value: "{}\n"
|
||||||
|
- name: ISTIO_META_POD_PORTS
|
||||||
|
value: "[\n]"
|
||||||
|
- name: ISTIO_META_APP_CONTAINERS
|
||||||
|
value: serviceaclient
|
||||||
|
- name: ISTIO_META_CLUSTER_ID
|
||||||
|
value: Kubernetes
|
||||||
|
- name: ISTIO_META_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
args:
|
||||||
|
- "-c"
|
||||||
|
- while true; do echo $(POD_NAME); sleep 10; done
|
73
src/tools/genpolicy/tests/generate/testdata/secret.yaml
vendored
Normal file
73
src/tools/genpolicy/tests/generate/testdata/secret.yaml
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
key: YmFyCg==
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: secret-sample
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
key: YmFyCg==
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: configmap-sample3
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: one-container-secret
|
||||||
|
labels:
|
||||||
|
run: busybox
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
runtimeClassName: kata-cc
|
||||||
|
containers:
|
||||||
|
- name: busybox
|
||||||
|
image: "quay.io/prometheus/busybox:latest"
|
||||||
|
stdin: true
|
||||||
|
env:
|
||||||
|
- name: ENV_FROM_CONFIGMAP
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: key
|
||||||
|
name: configmap-sample
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: POD_IP
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: status.podIP
|
||||||
|
- name: SERVICE_ACCOUNT
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.serviceAccountName
|
||||||
|
- name: PROXY_CONFIG
|
||||||
|
value: "{}\n"
|
||||||
|
- name: ISTIO_META_POD_PORTS
|
||||||
|
value: "[\n]"
|
||||||
|
- name: ISTIO_META_APP_CONTAINERS
|
||||||
|
value: serviceaclient
|
||||||
|
- name: ISTIO_META_CLUSTER_ID
|
||||||
|
value: Kubernetes
|
||||||
|
- name: ISTIO_META_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
args:
|
||||||
|
- "-c"
|
||||||
|
- while true; do echo $(POD_NAME); sleep 10; done
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use anyhow::Context;
|
||||||
use base64::prelude::*;
|
use base64::prelude::*;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
@ -63,29 +64,13 @@ mod tests {
|
|||||||
/// with the tag `type` listing the exact type of request.
|
/// with the tag `type` listing the exact type of request.
|
||||||
async fn runtests(test_case_dir: &str) {
|
async fn runtests(test_case_dir: &str) {
|
||||||
// Prepare temp dir for running genpolicy.
|
// Prepare temp dir for running genpolicy.
|
||||||
let workdir = path::PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(test_case_dir);
|
let (workdir, testdata_dir) = prepare_workdir(test_case_dir, &["pod.yaml"]);
|
||||||
fs::create_dir_all(&workdir)
|
|
||||||
.expect("should be able to create directories under CARGO_TARGET_TMPDIR");
|
|
||||||
|
|
||||||
let testdata_dir = path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
||||||
.join("tests/testdata")
|
|
||||||
.join(test_case_dir);
|
|
||||||
fs::copy(testdata_dir.join("pod.yaml"), workdir.join("pod.yaml"))
|
|
||||||
.expect("copying files around should not fail");
|
|
||||||
|
|
||||||
let genpolicy_dir =
|
|
||||||
path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../tools/genpolicy");
|
|
||||||
|
|
||||||
for base in ["rules.rego", "genpolicy-settings.json"] {
|
|
||||||
fs::copy(genpolicy_dir.join(base), workdir.join(base))
|
|
||||||
.expect("copying files around should not fail");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the command and return the generated policy.
|
// Run the command and return the generated policy.
|
||||||
|
|
||||||
let config = genpolicy::utils::Config {
|
let config = genpolicy::utils::Config {
|
||||||
base64_out: false,
|
base64_out: false,
|
||||||
config_map_files: None,
|
config_files: None,
|
||||||
containerd_socket_path: None, // Some(String::from("/var/run/containerd/containerd.sock")),
|
containerd_socket_path: None, // Some(String::from("/var/run/containerd/containerd.sock")),
|
||||||
insecure_registries: Vec::new(),
|
insecure_registries: Vec::new(),
|
||||||
layers_cache_file_path: None,
|
layers_cache_file_path: None,
|
||||||
@ -153,6 +138,50 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_workdir(
|
||||||
|
test_case_dir: &str,
|
||||||
|
files_to_copy: &[&str],
|
||||||
|
) -> (path::PathBuf, path::PathBuf) {
|
||||||
|
// Prepare temp dir for running genpolicy.
|
||||||
|
let workdir = path::PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(test_case_dir);
|
||||||
|
fs::create_dir_all(&workdir)
|
||||||
|
.expect("should be able to create directories under CARGO_TARGET_TMPDIR");
|
||||||
|
|
||||||
|
let testdata_dir = path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
|
.join("tests/policy/testdata")
|
||||||
|
.join(test_case_dir);
|
||||||
|
|
||||||
|
// Make sure that workdir is empty.
|
||||||
|
for entry in fs::read_dir(&workdir).expect("should be able to read directories") {
|
||||||
|
let entry = entry.expect("should be able to read directory entries");
|
||||||
|
fs::remove_file(entry.path()).expect("should be able to remove files");
|
||||||
|
}
|
||||||
|
|
||||||
|
for file in files_to_copy {
|
||||||
|
fs::copy(testdata_dir.join(file), workdir.join(file))
|
||||||
|
.context(format!(
|
||||||
|
"{:?} --> {:?}",
|
||||||
|
testdata_dir.join(file),
|
||||||
|
workdir.join(file)
|
||||||
|
))
|
||||||
|
.expect("copying files around should not fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
let genpolicy_dir = path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
|
||||||
|
for base in ["rules.rego", "genpolicy-settings.json"] {
|
||||||
|
fs::copy(genpolicy_dir.join(base), workdir.join(base))
|
||||||
|
.context(format!(
|
||||||
|
"{:?} --> {:?}",
|
||||||
|
genpolicy_dir.join(base),
|
||||||
|
workdir.join(base)
|
||||||
|
))
|
||||||
|
.expect("copying files around should not fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
(workdir, testdata_dir)
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_copyfile() {
|
async fn test_copyfile() {
|
||||||
runtests("copyfile").await;
|
runtests("copyfile").await;
|
Loading…
Reference in New Issue
Block a user