Skip to content

Commit

Permalink
genpolicy: fix validation of env variables sourced from metadata.name…
Browse files Browse the repository at this point in the history
…space

Use $(sandbox-namespace) wildcard in case none is specified in yaml. If wildcard is present, compare
input against annotation value.

Fixes regression introduced in #273
where samples that use metadata.namespace env var were no longer working.

Signed-off-by: Saul Paredes <[email protected]>
  • Loading branch information
Redent0r committed Jan 17, 2025
1 parent 02add57 commit 577b154
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 24 deletions.
70 changes: 47 additions & 23 deletions src/tools/genpolicy/rules.rego
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ get_state() = state {
state := data["pstate"]
}

get_state_val(key) = value {
state := get_state()
value := state[key]
}

get_state_path(key) = path {
# prepend "/pstate/" to key
path := concat("/", ["/pstate", key])
Expand Down Expand Up @@ -239,7 +244,10 @@ allow_by_anno(p_oci, i_oci, p_storages, i_storages) {
i_s_name := i_oci.Annotations[S_NAME_KEY]
print("allow_by_anno 1: i_s_name =", i_s_name)

allow_by_sandbox_name(p_oci, i_oci, p_storages, i_storages, i_s_name)
i_s_namespace := i_oci.Annotations[S_NAMESPACE_KEY]
print("allow_by_anno 1: i_s_namespace =", i_s_namespace)

allow_by_sandbox_name(p_oci, i_oci, p_storages, i_storages, i_s_name, i_s_namespace)

print("allow_by_anno 1: true")
}
Expand All @@ -251,19 +259,23 @@ allow_by_anno(p_oci, i_oci, p_storages, i_storages) {
print("allow_by_anno 2: i_s_name =", i_s_name, "p_s_name =", p_s_name)

allow_sandbox_name(p_s_name, i_s_name)
allow_by_sandbox_name(p_oci, i_oci, p_storages, i_storages, i_s_name)

i_s_namespace := i_oci.Annotations[S_NAMESPACE_KEY]
print("allow_by_anno 2: i_s_namespace =", i_s_namespace)

allow_by_sandbox_name(p_oci, i_oci, p_storages, i_storages, i_s_name, i_s_namespace)

print("allow_by_anno 2: true")
}

allow_by_sandbox_name(p_oci, i_oci, p_storages, i_storages, s_name) {
allow_by_sandbox_name(p_oci, i_oci, p_storages, i_storages, s_name, s_namespace) {
print("allow_by_sandbox_name: start")

i_namespace := i_oci.Annotations[S_NAMESPACE_KEY]

allow_by_container_types(p_oci, i_oci, s_name, i_namespace)
allow_by_bundle_or_sandbox_id(p_oci, i_oci, p_storages, i_storages)
allow_process(p_oci.Process, i_oci.Process, s_name)
allow_process(p_oci.Process, i_oci.Process, s_name, s_namespace)

print("allow_by_sandbox_name: true")
}
Expand Down Expand Up @@ -557,7 +569,7 @@ allow_by_bundle_or_sandbox_id(p_oci, i_oci, p_storages, i_storages) {
print("allow_by_bundle_or_sandbox_id: true")
}

allow_process_common(p_process, i_process, s_name) {
allow_process_common(p_process, i_process, s_name, s_namespace) {
print("allow_process_common: p_process =", p_process)
print("allow_process_common: i_process = ", i_process)
print("allow_process_common: s_name =", s_name)
Expand All @@ -566,28 +578,28 @@ allow_process_common(p_process, i_process, s_name) {
p_process.NoNewPrivileges == i_process.NoNewPrivileges

allow_user(p_process, i_process)
allow_env(p_process, i_process, s_name)
allow_env(p_process, i_process, s_name, s_namespace)

print("allow_process_common: true")
}

# Compare the OCI Process field of a policy container with the input OCI Process from a CreateContainerRequest
allow_process(p_process, i_process, s_name) {
allow_process(p_process, i_process, s_name, s_namespace) {
print("allow_process: start")

allow_args(p_process, i_process, s_name)
allow_process_common(p_process, i_process, s_name)
allow_process_common(p_process, i_process, s_name, s_namespace)
allow_caps(p_process.Capabilities, i_process.Capabilities)
p_process.Terminal == i_process.Terminal

print("allow_process: true")
}

# Compare the OCI Process field of a policy container with the input process field from ExecProcessRequest
allow_interactive_process(p_process, i_process, s_name) {
allow_interactive_process(p_process, i_process, s_name, s_namespace) {
print("allow_interactive_process: start")

allow_process_common(p_process, i_process, s_name)
allow_process_common(p_process, i_process, s_name, s_namespace)
allow_exec_caps(i_process.Capabilities)

# These are commands enabled using ExecProcessRequest commands and/or regex from the settings file.
Expand All @@ -597,10 +609,10 @@ allow_interactive_process(p_process, i_process, s_name) {
}

# Compare the OCI Process field of a policy container with the input process field from ExecProcessRequest
allow_probe_process(p_process, i_process, s_name) {
allow_probe_process(p_process, i_process, s_name, s_namespace) {
print("allow_probe_process: start")

allow_process_common(p_process, i_process, s_name)
allow_process_common(p_process, i_process, s_name, s_namespace)
allow_exec_caps(i_process.Capabilities)
p_process.Terminal == i_process.Terminal

Expand Down Expand Up @@ -675,27 +687,27 @@ allow_arg(i, i_arg, p_process, s_name) {
}

# OCI process.Env field
allow_env(p_process, i_process, s_name) {
allow_env(p_process, i_process, s_name, s_namespace) {
print("allow_env: p env =", p_process.Env)
print("allow_env: i env =", i_process.Env)

every i_var in i_process.Env {
print("allow_env: i_var =", i_var)
allow_var(p_process, i_process, i_var, s_name)
allow_var(p_process, i_process, i_var, s_name, s_namespace)
}

print("allow_env: true")
}

# Allow input env variables that are present in the policy data too.
allow_var(p_process, i_process, i_var, s_name) {
allow_var(p_process, i_process, i_var, s_name, s_namespace) {
some p_var in p_process.Env
p_var == i_var
print("allow_var 1: true")
}

# Match input with one of the policy variables, after substituting $(sandbox-name).
allow_var(p_process, i_process, i_var, s_name) {
allow_var(p_process, i_process, i_var, s_name, s_namespace) {
some p_var in p_process.Env
p_var2 := replace(p_var, "$(sandbox-name)", s_name)

Expand All @@ -706,7 +718,7 @@ allow_var(p_process, i_process, i_var, s_name) {
}

# Allow input env variables that match with a request_defaults regex.
allow_var(p_process, i_process, i_var, s_name) {
allow_var(p_process, i_process, i_var, s_name, s_namespace) {
some p_regex1 in policy_data.request_defaults.CreateContainerRequest.allow_env_regex
p_regex2 := replace(p_regex1, "$(ipv4_a)", policy_data.common.ipv4_a)
p_regex3 := replace(p_regex2, "$(ip_p)", policy_data.common.ip_p)
Expand All @@ -720,7 +732,7 @@ allow_var(p_process, i_process, i_var, s_name) {
}

# Allow fieldRef "fieldPath: status.podIP" values.
allow_var(p_process, i_process, i_var, s_name) {
allow_var(p_process, i_process, i_var, s_name, s_namespace) {
name_value := split(i_var, "=")
count(name_value) == 2
is_ip(name_value[1])
Expand All @@ -732,7 +744,7 @@ allow_var(p_process, i_process, i_var, s_name) {
}

# Allow common fieldRef variables.
allow_var(p_process, i_process, i_var, s_name) {
allow_var(p_process, i_process, i_var, s_name, s_namespace) {
name_value := split(i_var, "=")
count(name_value) == 2

Expand All @@ -751,7 +763,7 @@ allow_var(p_process, i_process, i_var, s_name) {
}

# Allow fieldRef "fieldPath: status.hostIP" values.
allow_var(p_process, i_process, i_var, s_name) {
allow_var(p_process, i_process, i_var, s_name, s_namespace) {
name_value := split(i_var, "=")
count(name_value) == 2
is_ip(name_value[1])
Expand All @@ -763,7 +775,7 @@ allow_var(p_process, i_process, i_var, s_name) {
}

# Allow resourceFieldRef values (e.g., "limits.cpu").
allow_var(p_process, i_process, i_var, s_name) {
allow_var(p_process, i_process, i_var, s_name, s_namespace) {
name_value := split(i_var, "=")
count(name_value) == 2

Expand All @@ -781,6 +793,16 @@ allow_var(p_process, i_process, i_var, s_name) {
print("allow_var 7: true")
}

allow_var(p_process, i_process, i_var, s_name, s_namespace) {
some p_var in p_process.Env
p_var2 := replace(p_var, "$(sandbox-namespace)", s_namespace)

print("allow_var 8: p_var2 =", p_var2)
p_var2 == i_var

print("allow_var 8: true")
}

allow_pod_ip_var(var_name, p_var) {
print("allow_pod_ip_var: var_name =", var_name, "p_var =", p_var)

Expand Down Expand Up @@ -1323,7 +1345,8 @@ allow_exec(p_container, i_process) {

p_oci = p_container.OCI
p_s_name = p_oci.Annotations[S_NAME_KEY]
allow_probe_process(p_oci.Process, i_process, p_s_name)
s_namespace = get_state_val("namespace")
allow_probe_process(p_oci.Process, i_process, p_s_name, s_namespace)

print("allow_exec: true")
}
Expand All @@ -1333,7 +1356,8 @@ allow_interactive_exec(p_container, i_process) {

p_oci = p_container.OCI
p_s_name = p_oci.Annotations[S_NAME_KEY]
allow_interactive_process(p_oci.Process, i_process, p_s_name)
s_namespace = get_state_val("namespace")
allow_interactive_process(p_oci.Process, i_process, p_s_name, s_namespace)

print("allow_interactive_exec: true")
}
Expand Down
8 changes: 7 additions & 1 deletion src/tools/genpolicy/src/pod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,13 @@ impl EnvVar {
let path: &str = &field_ref.fieldPath;
match path {
"metadata.name" => return "$(sandbox-name)".to_string(),
"metadata.namespace" => return namespace.to_string(),
"metadata.namespace" => {
return if namespace.is_empty() {
"$(sandbox-namespace)".to_string()
} else {
namespace.to_string()
};
}
"metadata.uid" => return "$(pod-uid)".to_string(),
"status.hostIP" => return "$(host-ip)".to_string(),
"status.podIP" => return "$(pod-ip)".to_string(),
Expand Down

0 comments on commit 577b154

Please sign in to comment.