mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
Lock down ACI tests and more OPA test folders (#54)
Borrowed from rego-cpp Significantly (> 10 times) faster execution. $ cargo test -r --test aci aci/mount_device passed 9.597958ms aci/mount_overlay passed 10.159208ms aci/scratch_mount passed 8.598875ms aci/create_container passed 10.237292ms aci/shutdown_container passed 6.904084ms aci/scratch_unmount passed 6.530875ms aci/unmount_overlay passed 5.958875ms aci/unmount_device passed 5.657834ms aci/load_fragment passed 6.049917ms Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
639ba72c90
commit
bb0ca29753
@@ -17,6 +17,7 @@ env_logger="0.10.0"
|
|||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
data-encoding = "2.4.0"
|
data-encoding = "2.4.0"
|
||||||
|
regex = "1.10.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
clap = { version = "4.4.7", features = ["derive"] }
|
clap = { version = "4.4.7", features = ["derive"] }
|
||||||
@@ -33,3 +34,8 @@ debug = true
|
|||||||
name="opa"
|
name="opa"
|
||||||
harness=false
|
harness=false
|
||||||
test=false
|
test=false
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name="aci"
|
||||||
|
harness=false
|
||||||
|
test=false
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
use crate::ast::{Expr, Ref};
|
use crate::ast::{Expr, Ref};
|
||||||
|
use crate::builtins::regex::regex_match;
|
||||||
use crate::builtins::utils::{ensure_args_count, ensure_set};
|
use crate::builtins::utils::{ensure_args_count, ensure_set};
|
||||||
use crate::builtins::BuiltinFcn;
|
use crate::builtins::BuiltinFcn;
|
||||||
use crate::lexer::Span;
|
use crate::lexer::Span;
|
||||||
@@ -20,6 +21,7 @@ lazy_static! {
|
|||||||
m.insert("all", (all, 1));
|
m.insert("all", (all, 1));
|
||||||
m.insert("any", (any, 1));
|
m.insert("any", (any, 1));
|
||||||
m.insert("set_diff", (set_diff, 2));
|
m.insert("set_diff", (set_diff, 2));
|
||||||
|
m.insert("re_match", (regex_match, 2));
|
||||||
m
|
m
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub mod deprecated;
|
|||||||
mod encoding;
|
mod encoding;
|
||||||
pub mod numbers;
|
pub mod numbers;
|
||||||
mod objects;
|
mod objects;
|
||||||
|
mod regex;
|
||||||
mod semver;
|
mod semver;
|
||||||
pub mod sets;
|
pub mod sets;
|
||||||
mod strings;
|
mod strings;
|
||||||
@@ -45,7 +46,7 @@ lazy_static! {
|
|||||||
sets::register(&mut m);
|
sets::register(&mut m);
|
||||||
objects::register(&mut m);
|
objects::register(&mut m);
|
||||||
strings::register(&mut m);
|
strings::register(&mut m);
|
||||||
//regex::register(&mut m);
|
regex::register(&mut m);
|
||||||
//glob::register(&mut m);
|
//glob::register(&mut m);
|
||||||
bitwise::register(&mut m);
|
bitwise::register(&mut m);
|
||||||
conversions::register(&mut m);
|
conversions::register(&mut m);
|
||||||
|
|||||||
51
src/builtins/regex.rs
Normal file
51
src/builtins/regex.rs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
use crate::ast::{Expr, Ref};
|
||||||
|
use crate::builtins;
|
||||||
|
use crate::builtins::utils::{ensure_args_count, ensure_string};
|
||||||
|
use crate::lexer::Span;
|
||||||
|
use crate::value::Value;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
pub fn register(m: &mut HashMap<&'static str, builtins::BuiltinFcn>) {
|
||||||
|
m.insert("regex.is_valid", (is_valid, 1));
|
||||||
|
m.insert("regex.match", (regex_match, 2));
|
||||||
|
m.insert("regex.split", (regex_split, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid(span: &Span, params: &[Ref<Expr>], args: &[Value]) -> Result<Value> {
|
||||||
|
let name = "regex.is_valid";
|
||||||
|
ensure_args_count(span, name, params, args, 1)?;
|
||||||
|
Ok(ensure_string(name, ¶ms[0], &args[0])
|
||||||
|
.map_or(Value::Bool(false), |p| Value::Bool(Regex::new(&p).is_ok())))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn regex_match(span: &Span, params: &[Ref<Expr>], args: &[Value]) -> Result<Value> {
|
||||||
|
let name = "regex.match";
|
||||||
|
ensure_args_count(span, name, params, args, 2)?;
|
||||||
|
let pattern = ensure_string(name, ¶ms[0], &args[0])?;
|
||||||
|
let value = ensure_string(name, ¶ms[1], &args[1])?;
|
||||||
|
|
||||||
|
let pattern = Regex::new(&pattern).or_else(|_| bail!(span.error("invalid regex")))?;
|
||||||
|
Ok(Value::Bool(pattern.is_match(&value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn regex_split(span: &Span, params: &[Ref<Expr>], args: &[Value]) -> Result<Value> {
|
||||||
|
let name = "regex.split";
|
||||||
|
ensure_args_count(span, name, params, args, 2)?;
|
||||||
|
let pattern = ensure_string(name, ¶ms[0], &args[0])?;
|
||||||
|
let value = ensure_string(name, ¶ms[1], &args[1])?;
|
||||||
|
|
||||||
|
let pattern = Regex::new(&pattern).or_else(|_| bail!(span.error("invalid regex")))?;
|
||||||
|
Ok(Value::from_array(
|
||||||
|
pattern
|
||||||
|
.split(&value)
|
||||||
|
.map(|s| Value::String(s.into()))
|
||||||
|
.collect::<Vec<Value>>(),
|
||||||
|
))
|
||||||
|
}
|
||||||
@@ -242,7 +242,7 @@ impl Interpreter {
|
|||||||
// Stop path collection upon encountering the leading variable.
|
// Stop path collection upon encountering the leading variable.
|
||||||
Expr::Var(v) => {
|
Expr::Var(v) => {
|
||||||
path.reverse();
|
path.reverse();
|
||||||
return self.lookup_var(v, &path[..]);
|
return self.lookup_var(v, &path[..], false);
|
||||||
}
|
}
|
||||||
// Accumulate chained . field accesses.
|
// Accumulate chained . field accesses.
|
||||||
Expr::RefDot { refr, field, .. } => {
|
Expr::RefDot { refr, field, .. } => {
|
||||||
@@ -259,8 +259,23 @@ impl Interpreter {
|
|||||||
// Note, we have the choice to evaluate a non-string index
|
// Note, we have the choice to evaluate a non-string index
|
||||||
_ => {
|
_ => {
|
||||||
path.reverse();
|
path.reverse();
|
||||||
let obj = self.eval_expr(refr)?;
|
|
||||||
let index = self.eval_expr(index)?;
|
let index = self.eval_expr(index)?;
|
||||||
|
|
||||||
|
// Handle indexing into data.
|
||||||
|
if let Ok(ref_path) = get_path_string(refr, None) {
|
||||||
|
if get_root_var(refr)?.text() == "data" && index != Value::Undefined {
|
||||||
|
let index = match &index {
|
||||||
|
Value::String(s) => s.to_string(),
|
||||||
|
_ => index.to_string(),
|
||||||
|
};
|
||||||
|
let ref_path = ref_path + "." + &index + "." + &path.join("");
|
||||||
|
self.ensure_rule_evaluated(ref_path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let obj = self.eval_expr(refr)?;
|
||||||
|
|
||||||
let mut v = obj[&index].clone();
|
let mut v = obj[&index].clone();
|
||||||
// Qualified references starting with data (e.g data.p.q) can
|
// Qualified references starting with data (e.g data.p.q) can
|
||||||
// be indexed using numbers. The number will be converted to string
|
// be indexed using numbers. The number will be converted to string
|
||||||
@@ -451,55 +466,87 @@ impl Interpreter {
|
|||||||
let (name, value) = match op {
|
let (name, value) = match op {
|
||||||
AssignOp::Eq => {
|
AssignOp::Eq => {
|
||||||
match (lhs.as_ref(), rhs.as_ref()) {
|
match (lhs.as_ref(), rhs.as_ref()) {
|
||||||
(Expr::Var(lhs_span), Expr::Var(rhs_span)) => {
|
(_, Expr::Var(var)) if self.lookup_var(var, &[], true)? == Value::Undefined => {
|
||||||
let (lhs_name, lhs_var) = (lhs_span.source_str(), self.eval_expr(lhs)?);
|
(var.source_str(), self.eval_expr(lhs)?)
|
||||||
let (rhs_name, rhs_var) = (rhs_span.source_str(), self.eval_expr(rhs)?);
|
}
|
||||||
|
(Expr::Var(var), _) if self.lookup_var(var, &[], true)? == Value::Undefined => {
|
||||||
match (&lhs_var, &rhs_var) {
|
(var.source_str(), self.eval_expr(rhs)?)
|
||||||
(Value::Undefined, Value::Undefined) => {
|
}
|
||||||
bail!(lhs.span().error("both operands are unsafe"))
|
(
|
||||||
|
Expr::Array {
|
||||||
|
items: lhs_items, ..
|
||||||
|
},
|
||||||
|
Expr::Array {
|
||||||
|
items: rhs_items,
|
||||||
|
span: rhs_span,
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
if lhs_items.len() != rhs_items.len() {
|
||||||
|
bail!(rhs_span
|
||||||
|
.error("mismatch in number of array elements in lhs and rhs"));
|
||||||
|
}
|
||||||
|
for (lhs, rhs) in std::iter::zip(lhs_items.iter(), rhs_items.iter()) {
|
||||||
|
if self.eval_assign_expr(&AssignOp::Eq, lhs, rhs)? != Value::Bool(true)
|
||||||
|
{
|
||||||
|
return Ok(Value::Bool(false));
|
||||||
}
|
}
|
||||||
(Value::Undefined, _) => (lhs_name, rhs_var),
|
|
||||||
(_, Value::Undefined) => (rhs_name, lhs_var),
|
|
||||||
// TODO: avoid reeval
|
|
||||||
_ => return self.eval_bool_expr(&BoolOp::Eq, lhs, rhs),
|
|
||||||
}
|
}
|
||||||
|
return Ok(Value::Bool(true));
|
||||||
}
|
}
|
||||||
(Expr::Var(lhs_span), _) => {
|
(Expr::Object { .. }, Expr::Object { .. }) => {
|
||||||
let (name, var) = (lhs_span.source_str(), self.eval_expr(lhs)?);
|
// TODO: destructure
|
||||||
|
return self.eval_bool_expr(&BoolOp::Eq, lhs, rhs);
|
||||||
// TODO: Check this
|
|
||||||
// Allow variable overwritten inside a loop
|
|
||||||
if !matches!(var, Value::Undefined)
|
|
||||||
&& self.loop_var_values.get(rhs).is_none()
|
|
||||||
{
|
|
||||||
return self.eval_bool_expr(&BoolOp::Eq, lhs, rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
(name, self.eval_expr(rhs)?)
|
|
||||||
}
|
}
|
||||||
(_, Expr::Var(rhs_span)) => {
|
(Expr::Array { .. }, _) => {
|
||||||
let (name, var) = (rhs_span.source_str(), self.eval_expr(rhs)?);
|
let value = self.eval_expr(rhs)?;
|
||||||
|
let mut cache = BTreeMap::new();
|
||||||
// TODO: Check this
|
let mut type_match = BTreeSet::new();
|
||||||
// Allow variable overwritten inside a loop
|
return self
|
||||||
if !matches!(var, Value::Undefined)
|
.make_bindings(false, &mut type_match, &mut cache, lhs, &value)
|
||||||
&& self.loop_var_values.get(lhs).is_none()
|
.map(Value::Bool);
|
||||||
{
|
}
|
||||||
return self.eval_bool_expr(&BoolOp::Eq, lhs, rhs);
|
(_, Expr::Array { .. }) => {
|
||||||
}
|
let value = self.eval_expr(lhs)?;
|
||||||
|
let mut cache = BTreeMap::new();
|
||||||
(name, self.eval_expr(lhs)?)
|
let mut type_match = BTreeSet::new();
|
||||||
|
return self
|
||||||
|
.make_bindings(false, &mut type_match, &mut cache, rhs, &value)
|
||||||
|
.map(Value::Bool);
|
||||||
|
}
|
||||||
|
(Expr::Object { .. }, _) => {
|
||||||
|
let value = self.eval_expr(rhs)?;
|
||||||
|
let mut cache = BTreeMap::new();
|
||||||
|
let mut type_match = BTreeSet::new();
|
||||||
|
return self
|
||||||
|
.make_bindings(false, &mut type_match, &mut cache, lhs, &value)
|
||||||
|
.map(Value::Bool);
|
||||||
|
}
|
||||||
|
(_, Expr::Object { .. }) => {
|
||||||
|
let value = self.eval_expr(lhs)?;
|
||||||
|
let mut cache = BTreeMap::new();
|
||||||
|
let mut type_match = BTreeSet::new();
|
||||||
|
return self
|
||||||
|
.make_bindings(false, &mut type_match, &mut cache, rhs, &value)
|
||||||
|
.map(Value::Bool);
|
||||||
}
|
}
|
||||||
// Treat the assignment as comparison if neither lhs nor rhs is a variable
|
// Treat the assignment as comparison if neither lhs nor rhs is a variable
|
||||||
_ => return self.eval_bool_expr(&BoolOp::Eq, lhs, rhs),
|
_ => return self.eval_bool_expr(&BoolOp::Eq, lhs, rhs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssignOp::ColEq => {
|
AssignOp::ColEq => {
|
||||||
|
let rhs_value = self.eval_expr(rhs)?;
|
||||||
|
if rhs_value == Value::Undefined {
|
||||||
|
return Ok(rhs_value);
|
||||||
|
}
|
||||||
|
|
||||||
let name = if let Expr::Var(span) = lhs.as_ref() {
|
let name = if let Expr::Var(span) = lhs.as_ref() {
|
||||||
span.source_str()
|
span.source_str()
|
||||||
} else {
|
} else {
|
||||||
bail!("internal error: unexpected");
|
let mut cache = BTreeMap::new();
|
||||||
|
let mut type_match = BTreeSet::new();
|
||||||
|
return self
|
||||||
|
.make_bindings(false, &mut type_match, &mut cache, lhs, &rhs_value)
|
||||||
|
.map(Value::Bool);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Check this
|
// TODO: Check this
|
||||||
@@ -513,7 +560,7 @@ impl Interpreter {
|
|||||||
.error(&format!("redefinition for variable {}", name)));
|
.error(&format!("redefinition for variable {}", name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
(name, self.eval_expr(rhs)?)
|
(name, rhs_value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -632,6 +679,7 @@ impl Interpreter {
|
|||||||
let raise_error = is_last && type_match.get(expr).is_none();
|
let raise_error = is_last && type_match.get(expr).is_none();
|
||||||
|
|
||||||
match (expr.as_ref(), value) {
|
match (expr.as_ref(), value) {
|
||||||
|
(Expr::Var(ident), _) if ident.text().as_ref() == &"_" => Ok(true),
|
||||||
(Expr::Var(ident), _) => {
|
(Expr::Var(ident), _) => {
|
||||||
self.add_variable(&ident.source_str(), value.clone())?;
|
self.add_variable(&ident.source_str(), value.clone())?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@@ -1649,29 +1697,25 @@ impl Interpreter {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut args_scope = Scope::new();
|
// Back up local variables of current function and empty
|
||||||
for (idx, a) in args.iter().enumerate() {
|
// the local variables of callee function.
|
||||||
let a = match a.as_ref() {
|
let scopes = std::mem::take(&mut self.scopes);
|
||||||
Expr::Var(s) => s.source_str(),
|
|
||||||
_ => {
|
|
||||||
match self.eval_expr(a) {
|
|
||||||
Ok(a) => {
|
|
||||||
if a != param_values[idx] {
|
|
||||||
// Skip this rule definition.
|
|
||||||
continue 'outer;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
// Set the arguments scope.
|
||||||
}
|
let args_scope = Scope::new();
|
||||||
_ => {
|
self.scopes.push(args_scope);
|
||||||
// TODO: destructuring function arguments.
|
|
||||||
continue;
|
let mut cache = BTreeMap::new();
|
||||||
}
|
let mut type_match = BTreeSet::new();
|
||||||
}
|
|
||||||
}
|
for (idx, a) in args.iter().enumerate() {
|
||||||
};
|
if self
|
||||||
//TODO: check call in params
|
.make_bindings(false, &mut type_match, &mut cache, a, ¶m_values[idx])
|
||||||
args_scope.insert(a, param_values[idx].clone());
|
.is_err()
|
||||||
|
{
|
||||||
|
self.scopes = scopes;
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
@@ -1683,12 +1727,6 @@ impl Interpreter {
|
|||||||
is_compr: false,
|
is_compr: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Back up local variables of current function and empty
|
|
||||||
// the local variables of callee function.
|
|
||||||
let scopes = std::mem::take(&mut self.scopes);
|
|
||||||
|
|
||||||
// Set the arguments scope.
|
|
||||||
self.scopes.push(args_scope);
|
|
||||||
let value = match self.eval_rule_bodies(ctx, span, bodies) {
|
let value = match self.eval_rule_bodies(ctx, span, bodies) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -1768,10 +1806,17 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
Ok(Value::Bool(true))
|
Ok(Value::Bool(true))
|
||||||
}
|
}
|
||||||
_ => {
|
_ if allow_return_arg => {
|
||||||
let ret_value = self.eval_call_impl(span, fcn, ¶ms[..params.len() - 1])?;
|
let ret_value = self.eval_call_impl(span, fcn, ¶ms[..params.len() - 1])?;
|
||||||
let value = self.eval_expr(&ea)?;
|
let mut cache = BTreeMap::new();
|
||||||
Ok(Value::Bool(ret_value == value))
|
let mut type_match = BTreeSet::new();
|
||||||
|
self.make_bindings(false, &mut type_match, &mut cache, &ea, &ret_value)
|
||||||
|
.map(Value::Bool)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let expected = self.eval_expr(¶ms[params.len() - 1])?;
|
||||||
|
let ret_value = self.eval_call_impl(span, fcn, ¶ms[..params.len() - 1])?;
|
||||||
|
Ok(Value::Bool(ret_value == expected))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1813,7 +1858,7 @@ impl Interpreter {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_var(&mut self, span: &Span, fields: &[&str]) -> Result<Value> {
|
fn lookup_var(&mut self, span: &Span, fields: &[&str], no_error: bool) -> Result<Value> {
|
||||||
let name = span.source_str();
|
let name = span.source_str();
|
||||||
|
|
||||||
// Return local variable/argument.
|
// Return local variable/argument.
|
||||||
@@ -1828,6 +1873,9 @@ impl Interpreter {
|
|||||||
|
|
||||||
// TODO: should we return before checking for input?
|
// TODO: should we return before checking for input?
|
||||||
if self.no_rules_lookup {
|
if self.no_rules_lookup {
|
||||||
|
if no_error {
|
||||||
|
return Ok(Value::Undefined);
|
||||||
|
}
|
||||||
return Err(span.error("undefined var"));
|
return Err(span.error("undefined var"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1869,6 +1917,12 @@ impl Interpreter {
|
|||||||
Self::get_path_string(&self.current_module()?.package.refr, Some("data"))?;
|
Self::get_path_string(&self.current_module()?.package.refr, Some("data"))?;
|
||||||
let rule_path = module_path + "." + name.text();
|
let rule_path = module_path + "." + name.text();
|
||||||
|
|
||||||
|
if !no_error
|
||||||
|
&& self.rules.get(&rule_path).is_none()
|
||||||
|
&& self.default_rules.get(&rule_path).is_none()
|
||||||
|
{
|
||||||
|
bail!(span.error("var is unsafe"));
|
||||||
|
}
|
||||||
self.ensure_rule_evaluated(rule_path)?;
|
self.ensure_rule_evaluated(rule_path)?;
|
||||||
|
|
||||||
let value = Self::get_value_chained(self.data.clone(), &path[..]);
|
let value = Self::get_value_chained(self.data.clone(), &path[..]);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ impl Source {
|
|||||||
let col_spaces = col as usize - 1;
|
let col_spaces = col as usize - 1;
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"\n-->{}:{}:{}\n{:<line_num_width$}|\n\
|
"\n--> {}:{}:{}\n{:<line_num_width$}|\n\
|
||||||
{:<line_num_width$}| {}\n\
|
{:<line_num_width$}| {}\n\
|
||||||
{:<line_num_width$}| {:<col_spaces$}^\n\
|
{:<line_num_width$}| {:<col_spaces$}^\n\
|
||||||
{}: {}",
|
{}: {}",
|
||||||
|
|||||||
@@ -570,6 +570,15 @@ impl Analyzer {
|
|||||||
} else {
|
} else {
|
||||||
gather_input_vars(expr, &self.scopes, scope)?;
|
gather_input_vars(expr, &self.scopes, scope)?;
|
||||||
gather_loop_vars(expr, &self.scopes, scope)?;
|
gather_loop_vars(expr, &self.scopes, scope)?;
|
||||||
|
|
||||||
|
let extra_arg = get_extra_arg(
|
||||||
|
expr,
|
||||||
|
Some(self.current_module_path.as_str()),
|
||||||
|
&self.functions,
|
||||||
|
);
|
||||||
|
if let Some(ea) = extra_arg {
|
||||||
|
gather_vars(&ea, false, &self.scopes, scope)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Literal::Every { domain, .. } => {
|
Literal::Every { domain, .. } => {
|
||||||
@@ -600,19 +609,26 @@ impl Analyzer {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
first_use: &mut BTreeMap<SourceStr, Span>,
|
first_use: &mut BTreeMap<SourceStr, Span>,
|
||||||
definitions: &mut Vec<Definition<SourceStr>>,
|
definitions: &mut Vec<Definition<SourceStr>>,
|
||||||
return_arg: &Option<Ref<Expr>>,
|
assigned_vars: &Option<&BTreeSet<SourceStr>>,
|
||||||
) -> Result<(Vec<SourceStr>, Vec<Ref<Expr>>)> {
|
) -> Result<(Vec<SourceStr>, Vec<Ref<Expr>>)> {
|
||||||
let mut used_vars = vec![];
|
let mut used_vars = vec![];
|
||||||
let mut comprs = vec![];
|
let mut comprs = vec![];
|
||||||
traverse(expr, &mut |e| match e.as_ref() {
|
traverse(expr, &mut |e| match e.as_ref() {
|
||||||
Var(v) if !matches!(*v.text(), "_" | "input" | "data") => {
|
Var(v) if !matches!(*v.text(), "_" | "input" | "data") => {
|
||||||
let name = v.source_str();
|
let name = v.source_str();
|
||||||
|
let is_extra_arg = match assigned_vars {
|
||||||
|
Some(vars) => vars.contains(&v.source_str()),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
if scope.locals.contains(&name)
|
if scope.locals.contains(&name)
|
||||||
/*|| scope.inputs.contains(name) */
|
/*|| scope.inputs.contains(name) */
|
||||||
{
|
{
|
||||||
used_vars.push(name.clone());
|
if !is_extra_arg {
|
||||||
first_use.entry(name).or_insert(v.clone());
|
used_vars.push(name.clone());
|
||||||
} else if !scope.inputs.contains(&name) && Some(e.clone()) != *return_arg {
|
first_use.entry(name).or_insert(v.clone());
|
||||||
|
}
|
||||||
|
} else if !scope.inputs.contains(&name) {
|
||||||
bail!(v.error(format!("use of undefined variable `{name}` is unsafe").as_str()));
|
bail!(v.error(format!("use of undefined variable `{name}` is unsafe").as_str()));
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
@@ -627,7 +643,7 @@ impl Analyzer {
|
|||||||
scope,
|
scope,
|
||||||
first_use,
|
first_use,
|
||||||
definitions,
|
definitions,
|
||||||
return_arg,
|
assigned_vars,
|
||||||
)?;
|
)?;
|
||||||
definitions.push(Definition {
|
definitions.push(Definition {
|
||||||
var: var.clone(),
|
var: var.clone(),
|
||||||
@@ -992,30 +1008,42 @@ impl Analyzer {
|
|||||||
&self.functions,
|
&self.functions,
|
||||||
);
|
);
|
||||||
if let Some(ref ea) = extra_arg {
|
if let Some(ref ea) = extra_arg {
|
||||||
if let Expr::Var(return_arg) = ea.as_ref() {
|
// Gather vars that are being bound
|
||||||
let (mut used_vars, comprs) = Self::gather_used_vars_comprs_index_vars(
|
let mut extras_scope = Scope::default();
|
||||||
expr,
|
gather_assigned_vars(ea, false, &self.scopes, &mut extras_scope)?;
|
||||||
&mut scope,
|
|
||||||
&mut first_use,
|
for var in &extras_scope.locals {
|
||||||
&mut definitions,
|
scope.locals.insert(var.clone());
|
||||||
&extra_arg,
|
}
|
||||||
)?;
|
|
||||||
let var = if *return_arg.text() != "_" {
|
// Gather vars being used.
|
||||||
// The var in the return argument slot would have been processed as
|
let (mut used_vars, comprs) = Self::gather_used_vars_comprs_index_vars(
|
||||||
// an used var. Remove it from used vars and add it as the variable being
|
expr,
|
||||||
// defined.
|
&mut scope,
|
||||||
used_vars.pop();
|
&mut first_use,
|
||||||
return_arg.source_str()
|
&mut definitions,
|
||||||
} else {
|
&Some(&extras_scope.locals),
|
||||||
empty_str.clone()
|
)?;
|
||||||
};
|
|
||||||
self.process_comprs(
|
self.process_comprs(
|
||||||
&comprs[..],
|
&comprs[..],
|
||||||
&mut scope,
|
&mut scope,
|
||||||
&mut first_use,
|
&mut first_use,
|
||||||
&mut used_vars,
|
&mut used_vars,
|
||||||
)?;
|
)?;
|
||||||
definitions.push(Definition { var, used_vars });
|
|
||||||
|
if !extras_scope.locals.is_empty() {
|
||||||
|
for var in extras_scope.locals {
|
||||||
|
definitions.push(Definition {
|
||||||
|
var,
|
||||||
|
used_vars: used_vars.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
definitions.push(Definition {
|
||||||
|
var: empty_str.clone(),
|
||||||
|
used_vars,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.process_expr(expr, &mut scope, &mut first_use, &mut definitions)?;
|
self.process_expr(expr, &mut scope, &mut first_use, &mut definitions)?;
|
||||||
|
|||||||
390
tests/aci/aci.yaml
Normal file
390
tests/aci/aci.yaml
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
# Copyright (c) Microsoft Corporation.
|
||||||
|
# Licensed under the MIT License.
|
||||||
|
cases:
|
||||||
|
- note: aci/mount_device
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
deviceHash: 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
target: /run/layers/p0-layer0
|
||||||
|
data:
|
||||||
|
metadata: {}
|
||||||
|
query: data.policy.mount_device=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: add
|
||||||
|
key: /run/layers/p0-layer0
|
||||||
|
name: devices
|
||||||
|
value: 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
- note: aci/mount_overlay
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
containerID: container0
|
||||||
|
layerPaths:
|
||||||
|
- /run/layers/p0-layer0
|
||||||
|
- /run/layers/p0-layer1
|
||||||
|
- /run/layers/p0-layer2
|
||||||
|
- /run/layers/p0-layer3
|
||||||
|
- /run/layers/p0-layer4
|
||||||
|
- /run/layers/p0-layer5
|
||||||
|
target: /run/gcs/c/container0/rootfs
|
||||||
|
data:
|
||||||
|
metadata:
|
||||||
|
devices:
|
||||||
|
"/run/layers/p0-layer0": 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
"/run/layers/p0-layer1": e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c
|
||||||
|
"/run/layers/p0-layer2": eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79
|
||||||
|
"/run/layers/p0-layer3": 41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156
|
||||||
|
"/run/layers/p0-layer4": 4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c
|
||||||
|
"/run/layers/p0-layer5": fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a
|
||||||
|
query: data.policy.mount_overlay=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: add
|
||||||
|
key: container0
|
||||||
|
name: matches
|
||||||
|
value:
|
||||||
|
- {"allow_elevated":true,"allow_stdio_access":false,"capabilities":{"ambient":["CAP_SYS_ADMIN"],"bounding":["CAP_SYS_ADMIN"],"effective":["CAP_SYS_ADMIN"],"inheritable":["CAP_SYS_ADMIN"],"permitted":["CAP_SYS_ADMIN"]},"command":["rustc","--help"],"env_rules":[{"pattern":"PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","required":true,"strategy":"string"},{"pattern":"RUSTUP_HOME=/usr/local/rustup","required":true,"strategy":"string"},{"pattern":"CARGO_HOME=/usr/local/cargo","required":true,"strategy":"string"},{"pattern":"RUST_VERSION=1.52.1","required":true,"strategy":"string"},{"pattern":"TERM=xterm","required":false,"strategy":"string"},{"pattern":"PREFIX_.+=.+","required":false,"strategy":"re2"}],"exec_processes":[{"command":["top"],"signals":[]}],"layers":["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],"mounts":[{"destination":"/container/path/one","options":["rbind","rshared","rw"],"source":"sandbox:///host/path/one","type":"bind"},{"destination":"/container/path/two","options":["rbind","rshared","ro"],"source":"sandbox:///host/path/two","type":"bind"}],"no_new_privileges":true,"seccomp_profile_sha256":"","signals":[],"user":{"group_idnames":[{"pattern":"","strategy":"any"}],"umask":"0022","user_idname":{"pattern":"","strategy":"any"}},"working_dir":"/home/user"}
|
||||||
|
- action: add
|
||||||
|
key: /run/gcs/c/container0/rootfs
|
||||||
|
name: overlayTargets
|
||||||
|
value: true
|
||||||
|
- note: aci/scratch_mount
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
encrypted: true
|
||||||
|
target: /mnt/layer6
|
||||||
|
data:
|
||||||
|
metadata: {}
|
||||||
|
query: data.policy.scratch_mount=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: add
|
||||||
|
key: /mnt/layer6
|
||||||
|
name: scratch_mounts
|
||||||
|
value:
|
||||||
|
encrypted: true
|
||||||
|
- note: aci/create_container
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
argList:
|
||||||
|
- rustc
|
||||||
|
- --help
|
||||||
|
capabilities:
|
||||||
|
ambient: ["CAP_SYS_ADMIN"]
|
||||||
|
bounding: ["CAP_SYS_ADMIN"]
|
||||||
|
effective: ["CAP_SYS_ADMIN"]
|
||||||
|
inheritable: ["CAP_SYS_ADMIN"]
|
||||||
|
permitted: ["CAP_SYS_ADMIN"]
|
||||||
|
containerID: container0
|
||||||
|
envList:
|
||||||
|
- CARGO_HOME=/usr/local/cargo
|
||||||
|
- RUST_VERSION=1.52.1
|
||||||
|
- TERM=xterm
|
||||||
|
- PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
- RUSTUP_HOME=/usr/local/rustup
|
||||||
|
groups:
|
||||||
|
- id: 0
|
||||||
|
name: root
|
||||||
|
hugePagesDir: /run/gcs/c/sandbox0/hugepages
|
||||||
|
mounts:
|
||||||
|
- destination: /container/path/one
|
||||||
|
options: ["rbind", "rshared", "rw"]
|
||||||
|
source: /run/gcs/c/sandbox0/sandboxMounts/host/path/one
|
||||||
|
type: bind
|
||||||
|
- destination: /container/path/two
|
||||||
|
options: ["rbind", "rshared", "ro"]
|
||||||
|
source: /run/gcs/c/sandbox0/sandboxMounts/host/path/two
|
||||||
|
type: bind
|
||||||
|
noNewPrivileges: true
|
||||||
|
privileged: false
|
||||||
|
seccompProfileSHA256: ""
|
||||||
|
sandboxDir: /run/gcs/c/sandbox0/sandboxMounts
|
||||||
|
umask: "0022"
|
||||||
|
user:
|
||||||
|
id: 0
|
||||||
|
name: root
|
||||||
|
workingDir: /home/user
|
||||||
|
data:
|
||||||
|
sandboxPrefix: "sandbox://"
|
||||||
|
hugePagesPrefix: "hugepages://"
|
||||||
|
plan9Prefix: "plan9://"
|
||||||
|
defaultMounts: []
|
||||||
|
privilegedMounts: []
|
||||||
|
defaultPrivilegedCapabilities:
|
||||||
|
- CAP_CHOWN
|
||||||
|
- CAP_DAC_OVERRIDE
|
||||||
|
- CAP_DAC_READ_SEARCH
|
||||||
|
- CAP_FOWNER
|
||||||
|
- CAP_FSETID
|
||||||
|
- CAP_KILL
|
||||||
|
- CAP_SETGID
|
||||||
|
- CAP_SETUID
|
||||||
|
- CAP_SETPCAP
|
||||||
|
- CAP_LINUX_IMMUTABLE
|
||||||
|
- CAP_NET_BIND_SERVICE
|
||||||
|
- CAP_NET_BROADCAST
|
||||||
|
- CAP_NET_ADMIN
|
||||||
|
- CAP_NET_RAW
|
||||||
|
- CAP_IPC_LOCK
|
||||||
|
- CAP_IPC_OWNER
|
||||||
|
- CAP_SYS_MODULE
|
||||||
|
- CAP_SYS_RAWIO
|
||||||
|
- CAP_SYS_CHROOT
|
||||||
|
- CAP_SYS_PTRACE
|
||||||
|
- CAP_SYS_PACCT
|
||||||
|
- CAP_SYS_ADMIN
|
||||||
|
- CAP_SYS_BOOT
|
||||||
|
- CAP_SYS_NICE
|
||||||
|
- CAP_SYS_RESOURCE
|
||||||
|
- CAP_SYS_TIME
|
||||||
|
- CAP_SYS_TTY_CONFIG
|
||||||
|
- CAP_MKNOD
|
||||||
|
- CAP_LEASE
|
||||||
|
- CAP_AUDIT_WRITE
|
||||||
|
- CAP_AUDIT_CONTROL
|
||||||
|
- CAP_SETFCAP
|
||||||
|
- CAP_MAC_OVERRIDE
|
||||||
|
- CAP_MAC_ADMIN
|
||||||
|
- CAP_SYSLOG
|
||||||
|
- CAP_WAKE_ALARM
|
||||||
|
- CAP_BLOCK_SUSPEND
|
||||||
|
- CAP_AUDIT_READ
|
||||||
|
- CAP_PERFMON
|
||||||
|
- CAP_BPF
|
||||||
|
- CAP_CHECKPOINT_RESTORE
|
||||||
|
defaultUnprivilegedCapabilities:
|
||||||
|
- CAP_DAC_OVERRIDE
|
||||||
|
- CAP_FSETID
|
||||||
|
- CAP_FOWNER
|
||||||
|
- CAP_MKNOD
|
||||||
|
- CAP_NET_RAW
|
||||||
|
- CAP_SETGID
|
||||||
|
- CAP_SETUID
|
||||||
|
- CAP_SETFCAP
|
||||||
|
- CAP_SETPCAP
|
||||||
|
- CAP_NET_BIND_SERVICE
|
||||||
|
- CAP_SYS_CHROOT
|
||||||
|
- CAP_KILL
|
||||||
|
- CAP_AUDIT_WRITE
|
||||||
|
metadata:
|
||||||
|
devices:
|
||||||
|
"/run/layers/p0-layer0": 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
"/run/layers/p0-layer1": e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c
|
||||||
|
"/run/layers/p0-layer2": eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79
|
||||||
|
"/run/layers/p0-layer3": 41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156
|
||||||
|
"/run/layers/p0-layer4": 4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c
|
||||||
|
"/run/layers/p0-layer5": fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a
|
||||||
|
matches:
|
||||||
|
container0:
|
||||||
|
- {"allow_elevated":true,"allow_stdio_access":false,"capabilities":{"ambient":["CAP_SYS_ADMIN"],"bounding":["CAP_SYS_ADMIN"],"effective":["CAP_SYS_ADMIN"],"inheritable":["CAP_SYS_ADMIN"],"permitted":["CAP_SYS_ADMIN"]},"command":["rustc","--help"],"env_rules":[{"pattern":"PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","required":true,"strategy":"string"},{"pattern":"RUSTUP_HOME=/usr/local/rustup","required":true,"strategy":"string"},{"pattern":"CARGO_HOME=/usr/local/cargo","required":true,"strategy":"string"},{"pattern":"RUST_VERSION=1.52.1","required":true,"strategy":"string"},{"pattern":"TERM=xterm","required":false,"strategy":"string"},{"pattern":"PREFIX_.+=.+","required":false,"strategy":"re2"}],"exec_processes":[{"command":["top"],"signals":[]}],"layers":["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],"mounts":[{"destination":"/container/path/one","options":["rbind","rshared","rw"],"source":"sandbox:///host/path/one","type":"bind"},{"destination":"/container/path/two","options":["rbind","rshared","ro"],"source":"sandbox:///host/path/two","type":"bind"}],"no_new_privileges":true,"seccomp_profile_sha256":"","signals":[],"user":{"group_idnames":[{"pattern":"","strategy":"any"}],"umask":"0022","user_idname":{"pattern":"","strategy":"any"}},"working_dir":"/home/user"}
|
||||||
|
- {"allow_elevated":false,"allow_stdio_access":false,"capabilities":null,"command":["rustc","--version"],"env_rules":[{"pattern":"PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","required":true,"strategy":"string"},{"pattern":"RUSTUP_HOME=/usr/local/rustup","required":true,"strategy":"string"},{"pattern":"CARGO_HOME=/usr/local/cargo","required":true,"strategy":"string"},{"pattern":"RUST_VERSION=1.52.1","required":true,"strategy":"string"},{"pattern":"TERM=xterm","required":false,"strategy":"string"}],"exec_processes":[{"command":["bash"],"signals":[]}],"layers":["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],"mounts":[],"no_new_privileges":true,"seccomp_profile_sha256":"","signals":[],"user":{"group_idnames":[{"pattern":"","strategy":"any"}],"umask":"0022","user_idname":{"pattern":"","strategy":"any"}},"working_dir":"/home/fragment"}
|
||||||
|
overlayTargets:
|
||||||
|
"/run/gcs/c/container0/rootfs": true
|
||||||
|
scratch_mounts:
|
||||||
|
"/mnt/layer6":
|
||||||
|
encrypted: true
|
||||||
|
query: data.policy.create_container=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allow_stdio_access: false
|
||||||
|
allowed: true
|
||||||
|
caps_list:
|
||||||
|
ambient: ["CAP_SYS_ADMIN"]
|
||||||
|
bounding: ["CAP_SYS_ADMIN"]
|
||||||
|
effective: ["CAP_SYS_ADMIN"]
|
||||||
|
inheritable: ["CAP_SYS_ADMIN"]
|
||||||
|
permitted: ["CAP_SYS_ADMIN"]
|
||||||
|
env_list:
|
||||||
|
- CARGO_HOME=/usr/local/cargo
|
||||||
|
- RUST_VERSION=1.52.1
|
||||||
|
- TERM=xterm
|
||||||
|
- PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
- RUSTUP_HOME=/usr/local/rustup
|
||||||
|
metadata:
|
||||||
|
- action: update
|
||||||
|
key: container0
|
||||||
|
name: matches
|
||||||
|
value:
|
||||||
|
- {"allow_elevated":true,"allow_stdio_access":false,"capabilities":{"ambient":["CAP_SYS_ADMIN"],"bounding":["CAP_SYS_ADMIN"],"effective":["CAP_SYS_ADMIN"],"inheritable":["CAP_SYS_ADMIN"],"permitted":["CAP_SYS_ADMIN"]},"command":["rustc","--help"],"env_rules":[{"pattern":"PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","required":true,"strategy":"string"},{"pattern":"RUSTUP_HOME=/usr/local/rustup","required":true,"strategy":"string"},{"pattern":"CARGO_HOME=/usr/local/cargo","required":true,"strategy":"string"},{"pattern":"RUST_VERSION=1.52.1","required":true,"strategy":"string"},{"pattern":"TERM=xterm","required":false,"strategy":"string"},{"pattern":"PREFIX_.+=.+","required":false,"strategy":"re2"}],"exec_processes":[{"command":["top"],"signals":[]}],"layers":["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],"mounts":[{"destination":"/container/path/one","options":["rbind","rshared","rw"],"source":"sandbox:///host/path/one","type":"bind"},{"destination":"/container/path/two","options":["rbind","rshared","ro"],"source":"sandbox:///host/path/two","type":"bind"}],"no_new_privileges":true,"seccomp_profile_sha256":"","signals":[],"user":{"group_idnames":[{"pattern":"","strategy":"any"}],"umask":"0022","user_idname":{"pattern":"","strategy":"any"}},"working_dir":"/home/user"}
|
||||||
|
- action: add
|
||||||
|
key: container0
|
||||||
|
name: started
|
||||||
|
value:
|
||||||
|
privileged: false
|
||||||
|
- note: aci/shutdown_container
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
containerID: container0
|
||||||
|
data:
|
||||||
|
metadata:
|
||||||
|
devices:
|
||||||
|
"/run/layers/p0-layer0": 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
"/run/layers/p0-layer1": e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c
|
||||||
|
"/run/layers/p0-layer2": eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79
|
||||||
|
"/run/layers/p0-layer3": 41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156
|
||||||
|
"/run/layers/p0-layer4": 4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c
|
||||||
|
"/run/layers/p0-layer5": fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a
|
||||||
|
matches:
|
||||||
|
container0:
|
||||||
|
- {"allow_elevated":true,"allow_stdio_access":false,"capabilities":{"ambient":["CAP_SYS_ADMIN"],"bounding":["CAP_SYS_ADMIN"],"effective":["CAP_SYS_ADMIN"],"inheritable":["CAP_SYS_ADMIN"],"permitted":["CAP_SYS_ADMIN"]},"command":["rustc","--help"],"env_rules":[{"pattern":"PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","required":true,"strategy":"string"},{"pattern":"RUSTUP_HOME=/usr/local/rustup","required":true,"strategy":"string"},{"pattern":"CARGO_HOME=/usr/local/cargo","required":true,"strategy":"string"},{"pattern":"RUST_VERSION=1.52.1","required":true,"strategy":"string"},{"pattern":"TERM=xterm","required":false,"strategy":"string"},{"pattern":"PREFIX_.+=.+","required":false,"strategy":"re2"}],"exec_processes":[{"command":["top"],"signals":[]}],"layers":["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],"mounts":[{"destination":"/container/path/one","options":["rbind","rshared","rw"],"source":"sandbox:///host/path/one","type":"bind"},{"destination":"/container/path/two","options":["rbind","rshared","ro"],"source":"sandbox:///host/path/two","type":"bind"}],"no_new_privileges":true,"seccomp_profile_sha256":"","signals":[],"user":{"group_idnames":[{"pattern":"","strategy":"any"}],"umask":"0022","user_idname":{"pattern":"","strategy":"any"}},"working_dir":"/home/user"}
|
||||||
|
- {"allow_elevated":false,"allow_stdio_access":false,"capabilities":null,"command":["rustc","--version"],"env_rules":[{"pattern":"PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","required":true,"strategy":"string"},{"pattern":"RUSTUP_HOME=/usr/local/rustup","required":true,"strategy":"string"},{"pattern":"CARGO_HOME=/usr/local/cargo","required":true,"strategy":"string"},{"pattern":"RUST_VERSION=1.52.1","required":true,"strategy":"string"},{"pattern":"TERM=xterm","required":false,"strategy":"string"}],"exec_processes":[{"command":["bash"],"signals":[]}],"layers":["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],"mounts":[],"no_new_privileges":true,"seccomp_profile_sha256":"","signals":[],"user":{"group_idnames":[{"pattern":"","strategy":"any"}],"umask":"0022","user_idname":{"pattern":"","strategy":"any"}},"working_dir":"/home/fragment"}
|
||||||
|
overlayTargets:
|
||||||
|
"/run/gcs/c/container0/rootfs": true
|
||||||
|
scratch_mounts:
|
||||||
|
"/mnt/layer6":
|
||||||
|
encrypted: true
|
||||||
|
started:
|
||||||
|
container0:
|
||||||
|
- {"privileged": false}
|
||||||
|
query: data.policy.shutdown_container=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: remove
|
||||||
|
key: container0
|
||||||
|
name: matches
|
||||||
|
- note: aci/scratch_unmount
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
unmountTarget: /mnt/layer6
|
||||||
|
data:
|
||||||
|
metadata:
|
||||||
|
devices:
|
||||||
|
"/run/layers/p0-layer0": 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
"/run/layers/p0-layer1": e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c
|
||||||
|
"/run/layers/p0-layer2": eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79
|
||||||
|
"/run/layers/p0-layer3": 41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156
|
||||||
|
"/run/layers/p0-layer4": 4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c
|
||||||
|
"/run/layers/p0-layer5": fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a
|
||||||
|
overlayTargets:
|
||||||
|
"/run/gcs/c/container0/rootfs": true
|
||||||
|
scratch_mounts:
|
||||||
|
"/mnt/layer6":
|
||||||
|
encrypted: true
|
||||||
|
query: data.policy.scratch_unmount=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: remove
|
||||||
|
key: /mnt/layer6
|
||||||
|
name: scratch_mounts
|
||||||
|
- note: aci/unmount_overlay
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
unmountTarget: /run/gcs/c/container0/rootfs
|
||||||
|
data:
|
||||||
|
metadata:
|
||||||
|
devices:
|
||||||
|
"/run/layers/p0-layer0": 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
"/run/layers/p0-layer1": e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c
|
||||||
|
"/run/layers/p0-layer2": eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79
|
||||||
|
"/run/layers/p0-layer3": 41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156
|
||||||
|
"/run/layers/p0-layer4": 4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c
|
||||||
|
"/run/layers/p0-layer5": fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a
|
||||||
|
overlayTargets:
|
||||||
|
"/run/gcs/c/container0/rootfs": true
|
||||||
|
scratch_mounts: []
|
||||||
|
query: data.policy.unmount_overlay=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: remove
|
||||||
|
key: /run/gcs/c/container0/rootfs
|
||||||
|
name: overlayTargets
|
||||||
|
- note: aci/unmount_device
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
input:
|
||||||
|
unmountTarget: /run/layers/p0-layer0
|
||||||
|
data:
|
||||||
|
metadata:
|
||||||
|
devices:
|
||||||
|
"/run/layers/p0-layer0": 1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766
|
||||||
|
query: data.policy.unmount_device=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: remove
|
||||||
|
key: /run/layers/p0-layer0
|
||||||
|
name: devices
|
||||||
|
- note: aci/load_fragment
|
||||||
|
modules:
|
||||||
|
- api.rego
|
||||||
|
- framework.rego
|
||||||
|
- policy.rego
|
||||||
|
- |
|
||||||
|
package fragment
|
||||||
|
|
||||||
|
svn := "1"
|
||||||
|
framework_version := "0.3.0"
|
||||||
|
|
||||||
|
containers := [
|
||||||
|
{
|
||||||
|
"command": ["rustc","--version"],
|
||||||
|
"env_rules": [{"pattern": `PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true},{"pattern": `RUSTUP_HOME=/usr/local/rustup`, "strategy": "string", "required": true},{"pattern": `CARGO_HOME=/usr/local/cargo`, "strategy": "string", "required": true},{"pattern": `RUST_VERSION=1.52.1`, "strategy": "string", "required": true},{"pattern": `TERM=xterm`, "strategy": "string", "required": false}],
|
||||||
|
"layers": ["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],
|
||||||
|
"mounts": [],
|
||||||
|
"exec_processes": [{"command": ["bash"], "signals": []}],
|
||||||
|
"signals": [],
|
||||||
|
"user": {
|
||||||
|
"user_idname": {"pattern": ``, "strategy": "any"},
|
||||||
|
"group_idnames": [{"pattern": ``, "strategy": "any"}],
|
||||||
|
"umask": "0022"
|
||||||
|
},
|
||||||
|
"capabilities": null,
|
||||||
|
"seccomp_profile_sha256": "",
|
||||||
|
"allow_elevated": false,
|
||||||
|
"working_dir": "/home/fragment",
|
||||||
|
"allow_stdio_access": false,
|
||||||
|
"no_new_privileges": true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
input:
|
||||||
|
feed: contoso.azurecr.io/infra
|
||||||
|
issuer: did:web:contoso.com
|
||||||
|
namespace: fragment
|
||||||
|
data:
|
||||||
|
metadata: {}
|
||||||
|
query: data.policy.load_fragment=x
|
||||||
|
want_result:
|
||||||
|
- x:
|
||||||
|
add_module: false
|
||||||
|
allowed: true
|
||||||
|
metadata:
|
||||||
|
- action: update
|
||||||
|
key: did:web:contoso.com
|
||||||
|
name: issuers
|
||||||
|
value: {"feeds":{"contoso.azurecr.io/infra":[{"containers":[{"allow_elevated":false,"allow_stdio_access":false,"capabilities":null,"command":["rustc","--version"],"env_rules":[{"pattern":"PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","required":true,"strategy":"string"},{"pattern":"RUSTUP_HOME=/usr/local/rustup","required":true,"strategy":"string"},{"pattern":"CARGO_HOME=/usr/local/cargo","required":true,"strategy":"string"},{"pattern":"RUST_VERSION=1.52.1","required":true,"strategy":"string"},{"pattern":"TERM=xterm","required":false,"strategy":"string"}],"exec_processes":[{"command":["bash"],"signals":[]}],"layers":["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],"mounts":[],"no_new_privileges":true,"seccomp_profile_sha256":"","signals":[],"user":{"group_idnames":[{"pattern":"","strategy":"any"}],"umask":"0022","user_idname":{"pattern":"","strategy":"any"}},"working_dir":"/home/fragment"}]}]}}
|
||||||
26
tests/aci/api.rego
Normal file
26
tests/aci/api.rego
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Copyright (c) Microsoft Corporation.
|
||||||
|
# Licensed under the MIT License.
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
version := "0.10.0"
|
||||||
|
|
||||||
|
enforcement_points := {
|
||||||
|
"mount_device": {"introducedVersion": "0.1.0", "default_results": {"allowed": false}},
|
||||||
|
"mount_overlay": {"introducedVersion": "0.1.0", "default_results": {"allowed": false}},
|
||||||
|
"create_container": {"introducedVersion": "0.1.0", "default_results": {"allowed": false, "env_list": null, "allow_stdio_access": false}},
|
||||||
|
"unmount_device": {"introducedVersion": "0.2.0", "default_results": {"allowed": true}},
|
||||||
|
"unmount_overlay": {"introducedVersion": "0.6.0", "default_results": {"allowed": true}},
|
||||||
|
"exec_in_container": {"introducedVersion": "0.2.0", "default_results": {"allowed": true, "env_list": null}},
|
||||||
|
"exec_external": {"introducedVersion": "0.3.0", "default_results": {"allowed": true, "env_list": null, "allow_stdio_access": false}},
|
||||||
|
"shutdown_container": {"introducedVersion": "0.4.0", "default_results": {"allowed": true}},
|
||||||
|
"signal_container_process": {"introducedVersion": "0.5.0", "default_results": {"allowed": true}},
|
||||||
|
"plan9_mount": {"introducedVersion": "0.6.0", "default_results": {"allowed": true}},
|
||||||
|
"plan9_unmount": {"introducedVersion": "0.6.0", "default_results": {"allowed": true}},
|
||||||
|
"get_properties": {"introducedVersion": "0.7.0", "default_results": {"allowed": true}},
|
||||||
|
"dump_stacks": {"introducedVersion": "0.7.0", "default_results": {"allowed": true}},
|
||||||
|
"runtime_logging": {"introducedVersion": "0.8.0", "default_results": {"allowed": true}},
|
||||||
|
"load_fragment": {"introducedVersion": "0.9.0", "default_results": {"allowed": false, "add_module": false}},
|
||||||
|
"scratch_mount": {"introducedVersion": "0.10.0", "default_results": {"allowed": true}},
|
||||||
|
"scratch_unmount": {"introducedVersion": "0.10.0", "default_results": {"allowed": true}},
|
||||||
|
}
|
||||||
1831
tests/aci/framework.rego
Normal file
1831
tests/aci/framework.rego
Normal file
File diff suppressed because it is too large
Load Diff
120
tests/aci/main.rs
Normal file
120
tests/aci/main.rs
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
use regorus::*;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use clap::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct TestCase {
|
||||||
|
note: String,
|
||||||
|
data: Value,
|
||||||
|
input: Value,
|
||||||
|
modules: Vec<String>,
|
||||||
|
query: String,
|
||||||
|
want_result: Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct YamlTest {
|
||||||
|
cases: Vec<TestCase>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_test_case(dir: &Path, case: &TestCase) -> Result<Value> {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
engine.add_data(case.data.clone())?;
|
||||||
|
engine.set_input(case.input.clone());
|
||||||
|
|
||||||
|
for (idx, rego) in case.modules.iter().enumerate() {
|
||||||
|
if rego.ends_with(".rego") {
|
||||||
|
let path = dir.join(rego);
|
||||||
|
let path = path.to_str().expect("not a valid path");
|
||||||
|
engine.add_policy_from_file(path.to_string())?;
|
||||||
|
} else {
|
||||||
|
engine.add_policy(format!("rego{idx}.rego"), rego.clone())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let query_results = engine.eval_query(case.query.clone(), true)?;
|
||||||
|
|
||||||
|
let mut values = vec![];
|
||||||
|
for qr in query_results.result {
|
||||||
|
values.push(if !qr.bindings.is_empty_object() {
|
||||||
|
qr.bindings.clone()
|
||||||
|
} else if let Some(v) = qr.expressions.last() {
|
||||||
|
v["value"].clone()
|
||||||
|
} else {
|
||||||
|
Value::Undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let result = Value::from_array(values);
|
||||||
|
// Make result json compatible. (E.g: avoid sets).
|
||||||
|
Value::from_json_str(&result.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_aci_tests(dir: &Path) -> Result<()> {
|
||||||
|
let mut nfailures = 0;
|
||||||
|
for entry in WalkDir::new(dir)
|
||||||
|
.sort_by_file_name()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|e| e.ok())
|
||||||
|
{
|
||||||
|
let path = entry.path();
|
||||||
|
if !path.to_string_lossy().ends_with(".yaml") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let yaml = std::fs::read(&path)?;
|
||||||
|
let yaml = String::from_utf8_lossy(&yaml);
|
||||||
|
let test: YamlTest = serde_yaml::from_str(&yaml)?;
|
||||||
|
|
||||||
|
for case in &test.cases {
|
||||||
|
print!("{:50}", case.note);
|
||||||
|
let start = Instant::now();
|
||||||
|
let results = eval_test_case(dir, case);
|
||||||
|
let duration = start.elapsed();
|
||||||
|
|
||||||
|
match results {
|
||||||
|
Ok(actual) if actual == case.want_result => {
|
||||||
|
println!("passed {:?}", duration);
|
||||||
|
}
|
||||||
|
Ok(actual) => {
|
||||||
|
println!("failed {:?}", duration);
|
||||||
|
println!("ACTUAL:");
|
||||||
|
println!("{}", serde_json::to_string(&actual)?);
|
||||||
|
println!("EXPECTED");
|
||||||
|
println!("{}", serde_json::to_string(&case.want_result)?);
|
||||||
|
nfailures += 1;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("failed {:?}", duration);
|
||||||
|
println!("{e}");
|
||||||
|
nfailures += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(nfailures == 0);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(clap::Parser)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
struct Cli {
|
||||||
|
/// Path to ACI test suite.
|
||||||
|
#[arg(long, short)]
|
||||||
|
#[clap(default_value = "tests/aci")]
|
||||||
|
test_dir: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let cli = Cli::parse();
|
||||||
|
run_aci_tests(&Path::new(&cli.test_dir))
|
||||||
|
}
|
||||||
89
tests/aci/policy.rego
Normal file
89
tests/aci/policy.rego
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# Copyright (c) Microsoft Corporation.
|
||||||
|
# Licensed under the MIT License.
|
||||||
|
|
||||||
|
package policy
|
||||||
|
|
||||||
|
api_version := "0.10.0"
|
||||||
|
framework_version := "0.3.0"
|
||||||
|
|
||||||
|
fragments := [
|
||||||
|
{"issuer": "did:web:contoso.com", "feed": "contoso.azurecr.io/infra", "minimum_svn": "1", "includes": ["containers"]},
|
||||||
|
]
|
||||||
|
containers := [
|
||||||
|
{
|
||||||
|
"command": ["rustc","--help"],
|
||||||
|
"env_rules": [{"pattern": `PATH=/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true},{"pattern": `RUSTUP_HOME=/usr/local/rustup`, "strategy": "string", "required": true},{"pattern": `CARGO_HOME=/usr/local/cargo`, "strategy": "string", "required": true},{"pattern": `RUST_VERSION=1.52.1`, "strategy": "string", "required": true},{"pattern": `TERM=xterm`, "strategy": "string", "required": false},{"pattern": `PREFIX_.+=.+`, "strategy": "re2", "required": false}],
|
||||||
|
"layers": ["fe84c9d5bfddd07a2624d00333cf13c1a9c941f3a261f13ead44fc6a93bc0e7a","4dedae42847c704da891a28c25d32201a1ae440bce2aecccfa8e6f03b97a6a6c","41d64cdeb347bf236b4c13b7403b633ff11f1cf94dbc7cf881a44d6da88c5156","eb36921e1f82af46dfe248ef8f1b3afb6a5230a64181d960d10237a08cd73c79","e769d7487cc314d3ee748a4440805317c19262c7acd2fdbdb0d47d2e4613a15c","1b80f120dbd88e4355d6241b519c3e25290215c469516b49dece9cf07175a766"],
|
||||||
|
"mounts": [{"destination": "/container/path/one", "options": ["rbind","rshared","rw"], "source": "sandbox:///host/path/one", "type": "bind"},{"destination": "/container/path/two", "options": ["rbind","rshared","ro"], "source": "sandbox:///host/path/two", "type": "bind"}],
|
||||||
|
"exec_processes": [{"command": ["top"], "signals": []}],
|
||||||
|
"signals": [],
|
||||||
|
"user": {
|
||||||
|
"user_idname": {"pattern": ``, "strategy": "any"},
|
||||||
|
"group_idnames": [{"pattern": ``, "strategy": "any"}],
|
||||||
|
"umask": "0022"
|
||||||
|
},
|
||||||
|
"capabilities": {
|
||||||
|
"bounding": ["CAP_SYS_ADMIN"],
|
||||||
|
"effective": ["CAP_SYS_ADMIN"],
|
||||||
|
"inheritable": ["CAP_SYS_ADMIN"],
|
||||||
|
"permitted": ["CAP_SYS_ADMIN"],
|
||||||
|
"ambient": ["CAP_SYS_ADMIN"],
|
||||||
|
},
|
||||||
|
"seccomp_profile_sha256": "",
|
||||||
|
"allow_elevated": true,
|
||||||
|
"working_dir": "/home/user",
|
||||||
|
"allow_stdio_access": false,
|
||||||
|
"no_new_privileges": true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": ["/pause"],
|
||||||
|
"env_rules": [{"pattern": `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true},{"pattern": `TERM=xterm`, "strategy": "string", "required": false}],
|
||||||
|
"layers": ["16b514057a06ad665f92c02863aca074fd5976c755d26bff16365299169e8415"],
|
||||||
|
"mounts": [],
|
||||||
|
"exec_processes": [],
|
||||||
|
"signals": [],
|
||||||
|
"user": {
|
||||||
|
"user_idname": {"pattern": ``, "strategy": "any"},
|
||||||
|
"group_idnames": [{"pattern": ``, "strategy": "any"}],
|
||||||
|
"umask": "0022"
|
||||||
|
},
|
||||||
|
"capabilities": null,
|
||||||
|
"seccomp_profile_sha256": "",
|
||||||
|
"allow_elevated": false,
|
||||||
|
"working_dir": "/",
|
||||||
|
"allow_stdio_access": false,
|
||||||
|
"no_new_privileges": true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
external_processes := [
|
||||||
|
{"command": ["bash"], "env_rules": [{"pattern": `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, "strategy": "string", "required": true}], "working_dir": "/", "allow_stdio_access": false},
|
||||||
|
]
|
||||||
|
allow_properties_access := false
|
||||||
|
allow_dump_stacks := false
|
||||||
|
allow_runtime_logging := false
|
||||||
|
allow_environment_variable_dropping := false
|
||||||
|
allow_unencrypted_scratch := false
|
||||||
|
allow_capability_dropping := true
|
||||||
|
|
||||||
|
|
||||||
|
mount_device := data.framework.mount_device
|
||||||
|
unmount_device := data.framework.unmount_device
|
||||||
|
mount_overlay := data.framework.mount_overlay
|
||||||
|
unmount_overlay := data.framework.unmount_overlay
|
||||||
|
create_container := data.framework.create_container
|
||||||
|
exec_in_container := data.framework.exec_in_container
|
||||||
|
exec_external := data.framework.exec_external
|
||||||
|
shutdown_container := data.framework.shutdown_container
|
||||||
|
signal_container_process := data.framework.signal_container_process
|
||||||
|
plan9_mount := data.framework.plan9_mount
|
||||||
|
plan9_unmount := data.framework.plan9_unmount
|
||||||
|
get_properties := data.framework.get_properties
|
||||||
|
dump_stacks := data.framework.dump_stacks
|
||||||
|
runtime_logging := data.framework.runtime_logging
|
||||||
|
load_fragment := data.framework.load_fragment
|
||||||
|
scratch_mount := data.framework.scratch_mount
|
||||||
|
scratch_unmount := data.framework.scratch_unmount
|
||||||
|
reason := {
|
||||||
|
"errors": data.framework.errors,
|
||||||
|
"error_objects": data.framework.error_objects,
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ embeddedvirtualdoc
|
|||||||
evaltermexpr
|
evaltermexpr
|
||||||
example
|
example
|
||||||
fix1863
|
fix1863
|
||||||
|
indexing
|
||||||
intersection
|
intersection
|
||||||
invalidkeyerror
|
invalidkeyerror
|
||||||
jsonfilteridempotent
|
jsonfilteridempotent
|
||||||
@@ -26,6 +27,9 @@ objectremoveidempotent
|
|||||||
objectremovenonstringkey
|
objectremovenonstringkey
|
||||||
partialsetdoc
|
partialsetdoc
|
||||||
rand
|
rand
|
||||||
|
regexisvalid
|
||||||
|
regexmatch
|
||||||
|
regexsplit
|
||||||
replacen
|
replacen
|
||||||
semvercompare
|
semvercompare
|
||||||
sets
|
sets
|
||||||
@@ -35,8 +39,10 @@ trim
|
|||||||
trimleft
|
trimleft
|
||||||
trimprefix
|
trimprefix
|
||||||
trimright
|
trimright
|
||||||
|
trimspace
|
||||||
trimsuffix
|
trimsuffix
|
||||||
typebuiltin
|
typebuiltin
|
||||||
typenamebuiltin
|
typenamebuiltin
|
||||||
|
undos
|
||||||
union
|
union
|
||||||
units
|
units
|
||||||
@@ -121,7 +121,12 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
|
|||||||
}
|
}
|
||||||
(r, _) => {
|
(r, _) => {
|
||||||
print!("\n{} failed.", case.note);
|
print!("\n{} failed.", case.note);
|
||||||
dbg!((&case, &r));
|
println!("{}", serde_yaml::to_string(&case)?);
|
||||||
|
match &r {
|
||||||
|
Ok(actual) => println!("GOT\n{}", serde_yaml::to_string(&actual)?),
|
||||||
|
Err(e) => println!("ERROR: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(e) = r {
|
if let Err(e) = r {
|
||||||
let msg = e.to_string();
|
let msg = e.to_string();
|
||||||
let pat = "could not find function ";
|
let pat = "could not find function ";
|
||||||
|
|||||||
Reference in New Issue
Block a user