Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

policy: cherry pick state policy changes from upstream #273

Draft
wants to merge 6 commits into
base: msft-main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 43 additions & 73 deletions src/agent/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions src/agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,12 @@ hex = { version = "0.4.2", optional = true }
sev = { git = "https://github.com/virtee/sev", version = "1.2", default-features = false, features = ["snp"], optional = true }

# Agent Policy
# TODO: use regorus version 0.1.5 when it will be released to crates.io.
regorus = { git = "https://github.com/anakrish/regorus", rev = "fc6f5d4", default-features = false, features = ["arc", "base64", "base64url", "regex"], optional = true }
regorus = { version = "0.2.6", default-features = false, features = [
"arc",
"regex",
"std",
], optional = true }
json-patch = "2.0.0"

[dev-dependencies]
tempfile = "3.1.0"
Expand Down
2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/configmap/pod-cm1.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/configmap/pod-cm2.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/configmap/pod-cm3.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/job/test-job.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/job/test-job2.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/pod/pod-exec.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/pod/pod-lifecycle.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/pod/pod-many-layers.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/pod/pod-one-container.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/pod/pod-spark.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/pod/pod-ubuntu.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/replica-set/replica2.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/stateful-set/web.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/stateful-set/web2.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook/webhook-pod1.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook/webhook-pod2.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook/webhook-pod3.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook/webhook-pod4.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook/webhook-pod5.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook/webhook-pod6.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook/webhook-pod7.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook2/webhook-pod8.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook2/webhook-pod9.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook3/dns-test.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/agent/samples/policy/yaml/webhook3/many-layers.yaml

Large diffs are not rendered by default.

94 changes: 83 additions & 11 deletions src/agent/src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ pub struct AgentPolicy {
engine: regorus::Engine,
}

#[derive(serde::Deserialize, Debug)]
struct MetadataResponse {
allowed: bool,
ops: Option<json_patch::Patch>,
}

impl AgentPolicy {
/// Create AgentPolicy object.
pub fn new() -> Self {
Expand All @@ -134,6 +140,17 @@ impl AgentPolicy {
let mut engine = regorus::Engine::new();
engine.set_strict_builtin_errors(false);
engine.set_gather_prints(true);
// assign a slice of the engine data "pstate" to be used as policy state
engine
.add_data(
regorus::Value::from_json_str(
r#"{
"pstate": {}
}"#,
)
.unwrap(),
)
.unwrap();
engine
}

Expand All @@ -156,6 +173,23 @@ impl AgentPolicy {
Ok(())
}

async fn apply_patch_to_state(&mut self, patch: json_patch::Patch) -> Result<()> {
// Convert the current engine data to a JSON value
let mut state = serde_json::to_value(self.engine.get_data())?;

// Apply the patch to the state
json_patch::patch(&mut state, &patch)?;

// Clear the existing data in the engine
self.engine.clear_data();

// Add the patched state back to the engine
self.engine
.add_data(regorus::Value::from_json_str(&state.to_string())?)?;

Ok(())
}

/// Ask regorus if an API call should be allowed or not.
async fn allow_request(&mut self, ep: &str, ep_input: &str) -> Result<(bool, String)> {
debug!(sl!(), "policy check: {ep}");
Expand All @@ -164,13 +198,56 @@ impl AgentPolicy {
let query = format!("data.agent_policy.{ep}");
self.engine.set_input_json(ep_input)?;

let mut allow = match self.engine.eval_bool_query(query, false) {
Ok(a) => a,
Err(e) => {
if !self.allow_failures {
return Err(e);
let results = self.engine.eval_query(query, false)?;

let prints = match self.engine.take_prints() {
Ok(p) => p.join(" "),
Err(e) => format!("Failed to get policy log: {e}"),
};

if results.result.len() != 1 {
// Results are empty when AllowRequestsFailingPolicy is used to allow a Request that hasn't been defined in the policy
if self.allow_failures {
return Ok((true, prints));
}
bail!(
"policy check: unexpected eval_query result len {:?}",
results
);
}

if results.result[0].expressions.len() != 1 {
bail!(
"policy check: unexpected eval_query result expressions {:?}",
results
);
}

let mut allow = match &results.result[0].expressions[0].value {
regorus::Value::Bool(b) => *b,

// Match against a specific variant that could be interpreted as MetadataResponse
regorus::Value::Object(obj) => {
let json_str = serde_json::to_string(obj)?;

self.log_eval_input(ep, &json_str).await;

let metadata_response: MetadataResponse = serde_json::from_str(&json_str)?;

if metadata_response.allowed {
if let Some(ops) = metadata_response.ops {
self.apply_patch_to_state(ops).await?;
}
}
false
metadata_response.allowed
}

_ => {
error!(sl!(), "allow_request: unexpected eval_query result type");
bail!(
"policy check: unexpected eval_query result type {:?}",
results
);
}
};

Expand All @@ -179,11 +256,6 @@ impl AgentPolicy {
allow = true;
}

let prints = match self.engine.take_prints() {
Ok(p) => p.join(" "),
Err(e) => format!("Failed to get policy log: {e}"),
};

Ok((allow, prints))
}

Expand Down
4 changes: 1 addition & 3 deletions src/tools/genpolicy/genpolicy-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,7 @@
"kata_config": {
"confidential_guest": true
},
"cluster_config": {
"default_namespace": "default"
},
"cluster_config": {},
"request_defaults": {
"CreateContainerRequest": {
"allow_env_regex": [
Expand Down
Loading
Loading