Convert typed proto policy fields to JSON suitable for `engine.add_data_json()`. The rego rules reference `data.*` directly, so the JSON structure has top-level keys matching the data expectations: - `data.filesystem_policy` - `data.landlock` - `data.process` - `data.network_policies` When `entrypoint_pid` is non-zero, binary paths that are symlinks inside the container filesystem are resolved v
(proto: &ProtoSandboxPolicy, entrypoint_pid: u32)
| 1115 | /// kernel-resolved canonical paths reported by `/proc/<pid>/exe` (e.g., |
| 1116 | /// `/usr/bin/python3.11`). |
| 1117 | fn proto_to_opa_data_json(proto: &ProtoSandboxPolicy, entrypoint_pid: u32) -> String { |
| 1118 | let filesystem_policy = proto.filesystem.as_ref().map_or_else( |
| 1119 | || { |
| 1120 | serde_json::json!({ |
| 1121 | "include_workdir": true, |
| 1122 | "read_only": [], |
| 1123 | "read_write": [], |
| 1124 | }) |
| 1125 | }, |
| 1126 | |fs| { |
| 1127 | serde_json::json!({ |
| 1128 | "include_workdir": fs.include_workdir, |
| 1129 | "read_only": fs.read_only, |
| 1130 | "read_write": fs.read_write, |
| 1131 | }) |
| 1132 | }, |
| 1133 | ); |
| 1134 | |
| 1135 | let landlock = proto.landlock.as_ref().map_or_else( |
| 1136 | || serde_json::json!({"compatibility": "best_effort"}), |
| 1137 | |ll| serde_json::json!({"compatibility": ll.compatibility}), |
| 1138 | ); |
| 1139 | |
| 1140 | let process = proto.process.as_ref().map_or_else( |
| 1141 | || { |
| 1142 | serde_json::json!({ |
| 1143 | "run_as_user": "sandbox", |
| 1144 | "run_as_group": "sandbox", |
| 1145 | }) |
| 1146 | }, |
| 1147 | |p| { |
| 1148 | serde_json::json!({ |
| 1149 | "run_as_user": p.run_as_user, |
| 1150 | "run_as_group": p.run_as_group, |
| 1151 | }) |
| 1152 | }, |
| 1153 | ); |
| 1154 | |
| 1155 | let network_policies: serde_json::Map<String, serde_json::Value> = proto |
| 1156 | .network_policies |
| 1157 | .iter() |
| 1158 | .map(|(key, rule)| { |
| 1159 | let endpoints: Vec<serde_json::Value> = rule |
| 1160 | .endpoints |
| 1161 | .iter() |
| 1162 | .map(|e| { |
| 1163 | // Normalize port/ports: ports takes precedence, then |
| 1164 | // single port promoted to array. Rego always sees "ports". |
| 1165 | let ports: Vec<u32> = if !e.ports.is_empty() { |
| 1166 | e.ports.clone() |
| 1167 | } else if e.port > 0 { |
| 1168 | vec![e.port] |
| 1169 | } else { |
| 1170 | vec![] |
| 1171 | }; |
| 1172 | let mut ep = serde_json::json!({"host": e.host, "ports": ports}); |
| 1173 | if !e.path.is_empty() { |
| 1174 | ep["path"] = e.path.clone().into(); |