mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat: Update to OPA v1.2.0 (#373)
Regorus now defaults to rego v1. `import rego.v1` is no longer needed. Additionally, `future` keywords are automatically imported. See https://www.openpolicyagent.org/docs/latest/v0-upgrade/#changes-to-rego-in-opa-v10 to understand the differences between rego v1 and v0. BREAKING CHANGE: v0 style policies will error out by default. To enable v0 behavior, call engine.set_rego_v0(true) before loading policies. Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
cbd772623a
commit
c963e477a3
@@ -83,8 +83,8 @@ fn parse(span: &Span, params: &[Ref<Expr>], args: &[Value], _strict: bool) -> Re
|
||||
bail!(span.error("spaces not allowed in resource strings"));
|
||||
}
|
||||
|
||||
let (number_part, suffix) = match string.find(|c: char| c.is_alphabetic()) {
|
||||
Some(p) => (&string[0..p], &string[p..]),
|
||||
let (number_part, suffix) = match string.rfind(|c: char| c.is_ascii_digit()) {
|
||||
Some(p) => (&string[0..p + 1], &string[p + 1..]),
|
||||
_ => (string, ""),
|
||||
};
|
||||
|
||||
@@ -161,8 +161,8 @@ fn parse_bytes(span: &Span, params: &[Ref<Expr>], args: &[Value], strict: bool)
|
||||
bail!(span.error("spaces not allowed in resource strings"));
|
||||
}
|
||||
|
||||
let (number_part, suffix) = match string.find(|c: char| c.is_alphabetic()) {
|
||||
Some(p) => (&string[0..p], &string[p..]),
|
||||
let (number_part, suffix) = match string.rfind(|c: char| c.is_ascii_digit()) {
|
||||
Some(p) => (&string[0..p + 1], &string[p + 1..]),
|
||||
_ => (string, ""),
|
||||
};
|
||||
|
||||
|
||||
@@ -37,33 +37,37 @@ impl Engine {
|
||||
modules: vec![],
|
||||
interpreter: Interpreter::new(),
|
||||
prepared: false,
|
||||
rego_v1: false,
|
||||
rego_v1: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Turn rego.v1 on/off for subsequently added policies.
|
||||
///
|
||||
/// Explicit import rego.v1 is not needed if set.
|
||||
/// Enable rego v0.
|
||||
///
|
||||
/// Note that regorus now defaults to v1.
|
||||
/// ```
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let mut engine = Engine::new();
|
||||
///
|
||||
/// engine.set_rego_v1(true);
|
||||
/// // Enable v0 for old style policies.
|
||||
/// engine.set_rego_v0(true);
|
||||
///
|
||||
/// engine.add_policy(
|
||||
/// "test.rego".to_string(),
|
||||
/// r#"
|
||||
/// package test
|
||||
/// allow if true # if keyword is automatically imported
|
||||
///
|
||||
/// allow { # v0 syntax does not require if keyword
|
||||
/// 1 < 2
|
||||
/// }
|
||||
/// "#.to_string())?;
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
pub fn set_rego_v1(&mut self, rego_v1: bool) {
|
||||
self.rego_v1 = rego_v1;
|
||||
pub fn set_rego_v0(&mut self, rego_v0: bool) {
|
||||
self.rego_v1 = !rego_v0;
|
||||
}
|
||||
|
||||
/// Add a policy.
|
||||
@@ -114,6 +118,8 @@ impl Engine {
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let mut engine = Engine::new();
|
||||
/// // framework.rego does not conform to v1.
|
||||
/// engine.set_rego_v0(true);
|
||||
///
|
||||
/// let package = engine.add_policy_from_file("tests/aci/framework.rego")?;
|
||||
///
|
||||
@@ -139,6 +145,8 @@ impl Engine {
|
||||
/// # use regorus::*;
|
||||
/// # fn main() -> anyhow::Result<()> {
|
||||
/// let mut engine = Engine::new();
|
||||
/// // framework.rego does not conform to v1.
|
||||
/// engine.set_rego_v0(true);
|
||||
///
|
||||
/// let _ = engine.add_policy_from_file("tests/aci/framework.rego")?;
|
||||
///
|
||||
@@ -414,6 +422,7 @@ impl Engine {
|
||||
/// let mut engine = Engine::new();
|
||||
///
|
||||
/// // Add policies
|
||||
/// engine.set_rego_v0(true);
|
||||
/// engine.add_policy_from_file("tests/aci/framework.rego")?;
|
||||
/// engine.add_policy_from_file("tests/aci/api.rego")?;
|
||||
/// engine.add_policy_from_file("tests/aci/policy.rego")?;
|
||||
@@ -739,7 +748,7 @@ impl Engine {
|
||||
/// engine.add_policy(
|
||||
/// "policy.rego".to_string(),
|
||||
/// r#"package invalid
|
||||
/// x = y {
|
||||
/// x = y if {
|
||||
/// # y = do_magic(2)
|
||||
/// do_magic(2, y) # y is supplied as an out parameter.
|
||||
/// }
|
||||
@@ -775,7 +784,7 @@ impl Engine {
|
||||
/// r#"
|
||||
/// package test # Line 2
|
||||
///
|
||||
/// x = y { # Line 4
|
||||
/// x = y if { # Line 4
|
||||
/// input.a > 2 # Line 5
|
||||
/// y = 5 # Line 6
|
||||
/// }
|
||||
|
||||
@@ -19,7 +19,7 @@ pub struct Parser<'source> {
|
||||
tok: Token,
|
||||
line: u32,
|
||||
end: u32,
|
||||
future_keywords: BTreeMap<String, Span>,
|
||||
future_keywords: BTreeMap<String, Option<Span>>,
|
||||
rego_v1: bool,
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ impl<'source> Parser<'source> {
|
||||
}
|
||||
|
||||
pub fn enable_rego_v1(&mut self) -> Result<()> {
|
||||
self.turn_on_rego_v1(self.tok.1.clone())
|
||||
self.turn_on_rego_v1(&None)
|
||||
}
|
||||
|
||||
fn turn_on_rego_v1(&mut self, span: Span) -> Result<()> {
|
||||
fn turn_on_rego_v1(&mut self, span: &Option<Span>) -> Result<()> {
|
||||
self.rego_v1 = true;
|
||||
for kw in FUTURE_KEYWORDS {
|
||||
self.set_future_keyword(kw, &span)?;
|
||||
self.set_future_keyword(kw, span)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -97,9 +97,9 @@ impl<'source> Parser<'source> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_future_keyword(&mut self, kw: &str, span: &Span) -> Result<()> {
|
||||
match &self.future_keywords.get(kw) {
|
||||
Some(s) if self.rego_v1 => Err(self.source.error(
|
||||
pub fn set_future_keyword(&mut self, kw: &str, span: &Option<Span>) -> Result<()> {
|
||||
match (span, self.future_keywords.get(kw)) {
|
||||
(Some(span), Some(Some(s))) if self.rego_v1 => Err(self.source.error(
|
||||
span.line,
|
||||
span.col,
|
||||
format!(
|
||||
@@ -155,11 +155,11 @@ impl<'source> Parser<'source> {
|
||||
fn handle_import_future_keywords(&mut self, comps: &[Span]) -> Result<bool> {
|
||||
if comps.len() >= 2 && comps[0].text() == "future" && comps[1].text() == "keywords" {
|
||||
match comps.len() - 2 {
|
||||
1 => self.set_future_keyword(comps[2].text(), &comps[2])?,
|
||||
1 => self.set_future_keyword(comps[2].text(), &Some(comps[2].clone()))?,
|
||||
0 => {
|
||||
let span = &comps[1];
|
||||
for kw in FUTURE_KEYWORDS.iter() {
|
||||
self.set_future_keyword(kw, span)?;
|
||||
self.set_future_keyword(kw, &Some(span.clone()))?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@@ -1709,7 +1709,7 @@ impl<'source> Parser<'source> {
|
||||
|
||||
let is_future_kw =
|
||||
if comps.len() == 2 && comps[0].text() == "rego" && comps[1].text() == "v1" {
|
||||
self.turn_on_rego_v1(span.clone())?;
|
||||
self.turn_on_rego_v1(&Some(span.clone()))?;
|
||||
true
|
||||
} else {
|
||||
self.handle_import_future_keywords(&comps)?
|
||||
|
||||
@@ -141,6 +141,7 @@ pub fn eval_file(
|
||||
strict: bool,
|
||||
) -> Result<(Vec<Value>, Vec<String>)> {
|
||||
let mut engine: Engine = Engine::new();
|
||||
engine.set_rego_v0(true);
|
||||
engine.set_strict_builtin_errors(strict);
|
||||
engine.set_gather_prints(true);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user