Merge pull request #10022 from microsoft/danmihai1/probes-and-lifecycle

genpolicy: container.exec_commands args validation
This commit is contained in:
Aurélien Bombo 2024-07-18 12:21:31 -07:00 committed by GitHub
commit ab6f37aa52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 83 additions and 15 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

@ -46,12 +46,17 @@ setup() {
cp "${pre_generate_pod_yaml}" "${testcase_pre_generate_pod_yaml}"
}
@test "Successful pod with auto-generated policy" {
# Common function for several test cases from this bats script.
wait_for_pod_ready() {
kubectl create -f "${correct_configmap_yaml}"
kubectl create -f "${correct_pod_yaml}"
kubectl wait --for=condition=Ready "--timeout=${timeout}" pod "${pod_name}"
}
@test "Successful pod with auto-generated policy" {
wait_for_pod_ready
}
@test "Successful pod with auto-generated policy and runtimeClassName filter" {
runtime_class_name=$(yq ".spec.runtimeClassName" < "${testcase_pre_generate_pod_yaml}")
@ -192,6 +197,22 @@ test_pod_policy_error() {
kubectl wait --for=condition=Ready "--timeout=${timeout}" pod "${pod_name}"
}
@test "ExecProcessRequest tests" {
wait_for_pod_ready
# Execute commands allowed by the policy.
pod_exec_allowed_command "${pod_name}" "echo" "livenessProbe" "test"
pod_exec_allowed_command "${pod_name}" "sh" "-c" "ls -l /"
pod_exec_allowed_command "${pod_name}" "echo" "startupProbe" "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"
pod_exec_blocked_command "${pod_name}" "echo" "hello"
}
teardown() {
auto_generate_policy_enabled || skip "Auto-generated policy tests are disabled."

View File

@ -28,6 +28,27 @@ spec:
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
livenessProbe:
exec:
command:
- echo
- livenessProbe
- test
failureThreshold: 1
periodSeconds: 5
timeoutSeconds: 10
readinessProbe:
exec:
command:
- "sh"
- "-c"
- "ls -l /"
startupProbe:
exec:
command:
- echo
- startupProbe
- test
topologySpreadConstraints:
- maxSkew: 2
topologyKey: kubernetes.io/hostname

View File

@ -343,10 +343,39 @@ add_allow_all_policy_to_yaml() {
# Execute "kubectl describe ${pod}" in a loop, until its output contains "${endpoint} is blocked by policy"
wait_for_blocked_request() {
endpoint="$1"
pod="$2"
local -r endpoint="$1"
local -r pod="$2"
command="kubectl describe pod ${pod} | grep \"${endpoint} is blocked by policy\""
local -r command="kubectl describe pod ${pod} | grep \"${endpoint} is blocked by policy\""
info "Waiting ${wait_time} seconds for: ${command}"
waitForProcess "${wait_time}" "$sleep_time" "${command}" >/dev/null 2>/dev/null
}
# Execute in a pod a command that is allowed by policy.
pod_exec_allowed_command() {
local -r pod_name="$1"
shift
local -r exec_output=$(kubectl exec "${pod_name}" -- "${@}" 2>&1)
local -r exec_args=$(printf '"%s",' "${@}")
info "Pod ${pod_name}: <${exec_args::-1}>:"
info "${exec_output}"
(echo "${exec_output}" | grep "policy") && die "exec was blocked by policy!"
return 0
}
# Execute in a pod a command that is blocked by policy.
pod_exec_blocked_command() {
local -r pod_name="$1"
shift
local -r exec_output=$(kubectl exec "${pod_name}" -- "${@}" 2>&1)
local -r exec_args=$(printf '"%s",' "${@}")
info "Pod ${pod_name}: <${exec_args::-1}>:"
info "${exec_output}"
(echo "${exec_output}" | grep "ExecProcessRequest is blocked by policy" > /dev/null) || die "exec was not blocked by policy!"
}