genpolicy: container.exec_commands args validation

Keep track of individual exec args instead of joining them in the
policy text. Verifying each arg results in a more precise policy,
because some of the args might include space characters.

This improved validation applies to commands specified in K8s YAML
files using:

- livenessProbe
- readinessProbe
- startupProbe
- lifecycle.postStart
- lifecycle.preStop

Signed-off-by: Dan Mihai <dmihai@microsoft.com>
This commit is contained in:
Dan Mihai
2024-07-15 22:59:38 +00:00
parent b23ea508d5
commit 9f4d1ffd43
4 changed files with 9 additions and 16 deletions

View File

@@ -1124,15 +1124,12 @@ ExecProcessRequest {
print("ExecProcessRequest 2: input =", input)
# TODO: match input container ID with its corresponding container.exec_commands.
i_command = concat(" ", input.process.Args)
print("ExecProcessRequest 3: i_command =", i_command)
some container in policy_data.containers
some p_command in container.exec_commands
print("ExecProcessRequest 2: p_command =", p_command)
# TODO: should other input data fields be validated as well?
p_command == i_command
p_command == input.process.Args
print("ExecProcessRequest 2: true")
}

View File

@@ -614,36 +614,36 @@ impl Container {
(yaml_has_command, yaml_has_args)
}
pub fn get_exec_commands(&self) -> Vec<String> {
pub fn get_exec_commands(&self) -> Vec<Vec<String>> {
let mut commands = Vec::new();
if let Some(probe) = &self.livenessProbe {
if let Some(exec) = &probe.exec {
commands.push(exec.command.join(" "));
commands.push(exec.command.clone());
}
}
if let Some(probe) = &self.readinessProbe {
if let Some(exec) = &probe.exec {
commands.push(exec.command.join(" "));
commands.push(exec.command.clone());
}
}
if let Some(probe) = &self.startupProbe {
if let Some(exec) = &probe.exec {
commands.push(exec.command.join(" "));
commands.push(exec.command.clone());
}
}
if let Some(lifecycle) = &self.lifecycle {
if let Some(postStart) = &lifecycle.postStart {
if let Some(exec) = &postStart.exec {
commands.push(exec.command.join(" "));
commands.push(exec.command.clone());
}
}
if let Some(preStop) = &lifecycle.preStop {
if let Some(exec) = &preStop.exec {
commands.push(exec.command.join(" "));
commands.push(exec.command.clone());
}
}
}

View File

@@ -271,7 +271,7 @@ pub struct ContainerPolicy {
/// Allow list of ommand lines that are allowed to be executed using
/// ExecProcessRequest. By default, all ExecProcessRequest calls are blocked
/// by the policy.
exec_commands: Vec<String>,
exec_commands: Vec<Vec<String>>,
}
/// See Reference / Kubernetes API / Config and Storage Resources / Volume.

View File

@@ -205,12 +205,8 @@ test_pod_policy_error() {
pod_exec_allowed_command "${pod_name}" "sh" "-c" "ls -l /"
pod_exec_allowed_command "${pod_name}" "echo" "startupProbe" "test"
# This test should fail but it passes because genpolicy joins the exec args from its
# input K8s YAML file and from the command being executed, and compares the joined
# command lines instead of comparing each argument.
pod_exec_allowed_command "${pod_name}" "echo" "livenessProbe test"
# Try to execute commands disallowed by the policy.
pod_exec_blocked_command "${pod_name}" "echo" "livenessProbe test"
pod_exec_blocked_command "${pod_name}" "echo" "livenessProbe" "test2"
pod_exec_blocked_command "${pod_name}" "echo" "livenessProbe" "test" "yes"
pod_exec_blocked_command "${pod_name}" "echo" "livenessProbe" "test foo"