diff --git a/src/tools/genpolicy/genpolicy-settings.json b/src/tools/genpolicy/genpolicy-settings.json index 77ec299946..cc8c9f0067 100644 --- a/src/tools/genpolicy/genpolicy-settings.json +++ b/src/tools/genpolicy/genpolicy-settings.json @@ -155,7 +155,7 @@ "emptyDir": { "mount_type": "local", "mount_source": "^$(cpath)/$(sandbox-id)/rootfs/local/", - "mount_point": "^$(cpath)/$(sandbox-id)/local/", + "mount_point": "^$(cpath)/$(sandbox-id)/rootfs/local/", "driver": "local", "source": "local", "fstype": "local", @@ -315,7 +315,8 @@ "CAP_PERFMON", "CAP_BPF", "CAP_CHECKPOINT_RESTORE" - ] + ], + "image_layer_verification" : "none" }, "kata_config": { "confidential_guest": false, diff --git a/src/tools/genpolicy/rules.rego b/src/tools/genpolicy/rules.rego index 5db3cc629c..1b09e89e6e 100644 --- a/src/tools/genpolicy/rules.rego +++ b/src/tools/genpolicy/rules.rego @@ -671,8 +671,7 @@ allow_by_bundle_or_sandbox_id(p_oci, i_oci, p_storages, i_storages) if { count(p_matches) == count(input.OCI.Mounts) - # TODO: enable allow_storages() after fixing https://github.com/kata-containers/kata-containers/issues/8833 - # allow_storages(p_storages, i_storages, bundle_id, sandbox_id) + allow_storages(p_storages, i_storages, bundle_id, sandbox_id) print("allow_by_bundle_or_sandbox_id: true") } @@ -1038,17 +1037,9 @@ allow_storages(p_storages, i_storages, bundle_id, sandbox_id) if { p_count == i_count - # Get the container image layer IDs and verity root hashes, from the "overlayfs" storage. - some overlay_storage in p_storages - overlay_storage.driver == "overlayfs" - print("allow_storages: overlay_storage =", overlay_storage) - count(overlay_storage.options) == 2 - - layer_ids := split(overlay_storage.options[0], ":") - print("allow_storages: layer_ids =", layer_ids) - - root_hashes := split(overlay_storage.options[1], ":") - print("allow_storages: root_hashes =", root_hashes) + image_info := allow_container_image_storage(p_storages) + layer_ids := image_info.layer_ids + root_hashes := image_info.root_hashes every i_storage in i_storages { allow_storage(p_storages, i_storage, bundle_id, sandbox_id, layer_ids, root_hashes) @@ -1057,6 +1048,23 @@ allow_storages(p_storages, i_storages, bundle_id, sandbox_id) if { print("allow_storages: true") } +# Currently, Image Layer Integrity Verification through Policy is only required for Guest VMs +# that use container image layers provided as dm-verity-protected block device images created on the Host. +allow_container_image_storage(p_storages) = { "layer_ids": [], "root_hashes": [] } { + policy_data.common.image_layer_verification != "host-tarfs-dm-verity" +} + +allow_container_image_storage(p_storages) = { "layer_ids": layer_ids, "root_hashes": root_hashes } { + policy_data.common.image_layer_verification == "host-tarfs-dm-verity" + + some overlay_storage in p_storages + overlay_storage.driver == "overlayfs" + count(overlay_storage.options) == 2 + + layer_ids := split(overlay_storage.options[0], ":") + root_hashes := split(overlay_storage.options[1], ":") +} + allow_storage(p_storages, i_storage, bundle_id, sandbox_id, layer_ids, root_hashes) if { some p_storage in p_storages @@ -1066,15 +1074,44 @@ allow_storage(p_storages, i_storage, bundle_id, sandbox_id, layer_ids, root_hash p_storage.driver == i_storage.driver p_storage.driver_options == i_storage.driver_options p_storage.fs_group == i_storage.fs_group + p_storage.fstype == i_storage.fstype + allow_storage_source(p_storage, i_storage, bundle_id) allow_storage_options(p_storage, i_storage, layer_ids, root_hashes) allow_mount_point(p_storage, i_storage, bundle_id, sandbox_id, layer_ids) - # TODO: validate the source field too. - print("allow_storage: true") } +allow_storage_source(p_storage, i_storage, bundle_id) { + print("allow_storage_source 1: start") + + p_storage.source == i_storage.source + + print("allow_storage_source 1: true") +} +allow_storage_source(p_storage, i_storage, bundle_id) { + print("allow_storage_source 2: start") + + source1 := p_storage.source + source2 := replace(source1, "$(sfprefix)", policy_data.common.sfprefix) + source3 := replace(source2, "$(cpath)", policy_data.common.cpath) + source4 := replace(source3, "$(bundle-id)", bundle_id) + + print("allow_storage_source 2: source =", source4) + regex.match(source4, i_storage.source) + + print("allow_storage_source 2: true") +} +allow_storage_source(p_storage, i_storage, bundle_id) { + print("allow_storage_source 3: start") + + p_storage.driver == "overlayfs" + i_storage.source == "none" + + print("allow_storage_source 3: true") +} + allow_storage_options(p_storage, i_storage, layer_ids, root_hashes) if { print("allow_storage_options 1: start") diff --git a/src/tools/genpolicy/src/mount_and_storage.rs b/src/tools/genpolicy/src/mount_and_storage.rs index 394c066585..f12714ec44 100644 --- a/src/tools/genpolicy/src/mount_and_storage.rs +++ b/src/tools/genpolicy/src/mount_and_storage.rs @@ -375,7 +375,6 @@ fn get_downward_api_mount(yaml_mount: &pod::VolumeMount, p_mounts: &mut Vec, - storages: &mut Vec, destination: &str, ) { // https://github.com/kubernetes/examples/blob/master/cassandra/image/Dockerfile @@ -404,17 +403,6 @@ pub fn get_image_mount_and_storage( settings_image ); - storages.push(agent::Storage { - driver: settings_image.driver.clone(), - driver_options: Vec::new(), - source: settings_image.source.clone(), - fstype: settings_image.fstype.clone(), - options: settings_image.options.clone(), - mount_point: destination_string.clone(), - fs_group: protobuf::MessageField::none(), - special_fields: ::protobuf::SpecialFields::new(), - }); - let file_name = Path::new(&destination_string).file_name().unwrap(); let name = OsString::from(file_name).into_string().unwrap(); let source = format!("{}{name}$", &settings_image.mount_source); diff --git a/src/tools/genpolicy/src/policy.rs b/src/tools/genpolicy/src/policy.rs index ae6fdea828..d28f23df25 100644 --- a/src/tools/genpolicy/src/policy.rs +++ b/src/tools/genpolicy/src/policy.rs @@ -418,6 +418,9 @@ pub struct CommonData { /// Default capabilities for a privileged container. pub privileged_caps: Vec, + + /// Parse Container image as a storage object + pub image_layer_verification: String, } /// Configuration from "kubectl config". @@ -615,7 +618,10 @@ impl AgentPolicy { let image_layers = yaml_container.registry.get_image_layers(); let mut storages = Default::default(); - get_image_layer_storages(&mut storages, &image_layers, &root); + const HOST_TARFS_DM_VERITY: &str = "host-tarfs-dm-verity"; + if self.config.settings.common.image_layer_verification == HOST_TARFS_DM_VERITY { + get_image_layer_storages(&mut storages, &image_layers, &root); + } resource.get_container_mounts_and_storages( &mut mounts, &mut storages, diff --git a/src/tools/genpolicy/src/yaml.rs b/src/tools/genpolicy/src/yaml.rs index edc2ff9adb..131d2ce0b4 100644 --- a/src/tools/genpolicy/src/yaml.rs +++ b/src/tools/genpolicy/src/yaml.rs @@ -313,12 +313,7 @@ pub fn get_container_mounts_and_storages( for volume in volumes { debug!("get_container_mounts_and_storages: {:?}", &volume); - mount_and_storage::get_image_mount_and_storage( - settings, - policy_mounts, - storages, - volume.0, - ); + mount_and_storage::get_image_mount_and_storage(settings, policy_mounts, volume.0); } } }