diff --git a/src/tools/genpolicy/src/policy.rs b/src/tools/genpolicy/src/policy.rs index e55ef49513..ee0a92894f 100644 --- a/src/tools/genpolicy/src/policy.rs +++ b/src/tools/genpolicy/src/policy.rs @@ -438,6 +438,11 @@ pub struct SandboxData { pub storages: Vec, } +enum K8sEnvFromSource { + ConfigMap(config_map::ConfigMap), + Secret(secret::Secret), +} + impl AgentPolicy { pub async fn from_files(config: &utils::Config) -> Result { let mut config_maps = Vec::new(); @@ -488,9 +493,18 @@ impl AgentPolicy { } } - if let Some(config_map_files) = &config.config_map_files { - for file in config_map_files { - config_maps.push(config_map::ConfigMap::new(file)?); + if let Some(config_files) = &config.config_files { + for resource_file in config_files { + 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); } +async fn parse_config_file( + yaml_file: String, + config: &utils::Config, +) -> Result> { + 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. fn name_to_hash(name: &str) -> String { let mut hasher = Sha256::new(); diff --git a/src/tools/genpolicy/src/utils.rs b/src/tools/genpolicy/src/utils.rs index 6696338cdb..26f619825c 100644 --- a/src/tools/genpolicy/src/utils.rs +++ b/src/tools/genpolicy/src/utils.rs @@ -18,10 +18,16 @@ struct CommandLineOptions { #[clap( short, 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, + #[clap( + long, + help = "Optional Kubernetes YAML input file path containing config resources such as ConfigMaps and Secrets" + )] + config_file: Option>, + #[clap( short = 'p', long, @@ -111,7 +117,7 @@ pub struct Config { pub yaml_file: Option, pub rego_rules_path: String, pub settings: settings::Settings, - pub config_map_files: Option>, + pub config_files: Option>, pub silent_unsupported_fields: bool, pub raw_out: bool, @@ -125,16 +131,15 @@ impl Config { pub fn new() -> Self { let args = CommandLineOptions::parse(); - let mut config_map_files = Vec::new(); - if let Some(config_map_file) = &args.config_map_file { - config_map_files.push(config_map_file.clone()); - } + // Migrate all files from the old `config_map_file` to the new `config_files` field + let config_files = args + .config_file + .unwrap_or_default() + .into_iter() + .chain(args.config_map_file.iter().cloned()) + .collect::>(); - let cm_files = if !config_map_files.is_empty() { - Some(config_map_files.clone()) - } else { - None - }; + let config_files = (!config_files.is_empty()).then_some(config_files); let mut layers_cache_file_path = args.layers_cache_file_path; // preserve backwards compatibility for only using the `use_cached_files` flag @@ -151,7 +156,7 @@ impl Config { yaml_file: args.yaml_file, rego_rules_path: args.rego_rules_path, settings, - config_map_files: cm_files, + config_files, silent_unsupported_fields: args.silent_unsupported_fields, raw_out: args.raw_out, base64_out: args.base64_out, diff --git a/src/tools/genpolicy/tests/main.rs b/src/tools/genpolicy/tests/main.rs index e6a8275736..04f6f32e92 100644 --- a/src/tools/genpolicy/tests/main.rs +++ b/src/tools/genpolicy/tests/main.rs @@ -85,7 +85,7 @@ mod tests { let config = genpolicy::utils::Config { base64_out: false, - config_map_files: None, + config_files: None, containerd_socket_path: None, // Some(String::from("/var/run/containerd/containerd.sock")), insecure_registries: Vec::new(), layers_cache_file_path: None,