mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat: implement net.cidr_is_valid builtin (#422)
Signed-off-by: tjons <tylerschade99@gmail.com>
This commit is contained in:
@@ -32,6 +32,7 @@ http = []
|
||||
glob = ["dep:globset"]
|
||||
graph = []
|
||||
jsonschema = ["dep:jsonschema"]
|
||||
net = []
|
||||
no_std = ["lazy_static/spin_no_std"]
|
||||
opa-runtime = []
|
||||
regex = ["dep:regex"]
|
||||
@@ -50,6 +51,7 @@ full-opa = [
|
||||
"hex",
|
||||
"http",
|
||||
"jsonschema",
|
||||
"net",
|
||||
"opa-runtime",
|
||||
"regex",
|
||||
"semver",
|
||||
|
||||
@@ -14,6 +14,9 @@ mod glob;
|
||||
mod graph;
|
||||
#[cfg(feature = "http")]
|
||||
mod http;
|
||||
#[cfg(feature = "net")]
|
||||
mod net;
|
||||
|
||||
pub mod numbers;
|
||||
mod objects;
|
||||
#[cfg(feature = "opa-runtime")]
|
||||
@@ -80,6 +83,8 @@ lazy_static! {
|
||||
//graphql::register(&mut m);
|
||||
#[cfg(feature = "http")]
|
||||
http::register(&mut m);
|
||||
#[cfg(feature = "net")]
|
||||
net::register(&mut m);
|
||||
//net::register(&mut m);
|
||||
#[cfg(feature = "uuid")]
|
||||
uuid::register(&mut m);
|
||||
|
||||
86
src/builtins/net.rs
Normal file
86
src/builtins/net.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use core::net::IpAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::ast::{Expr, Ref};
|
||||
use crate::builtins;
|
||||
use crate::builtins::utils::ensure_args_count;
|
||||
use crate::lexer::Span;
|
||||
use crate::value::Value;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use super::utils::ensure_string;
|
||||
|
||||
pub fn register(m: &mut builtins::BuiltinsMap<&'static str, builtins::BuiltinFcn>) {
|
||||
m.insert("net.cidr_is_valid", (cidr_is_valid, 1));
|
||||
}
|
||||
|
||||
/// Checks if a CIDR string is valid or invalid. Uses the
|
||||
/// `net::IpAddr` type to determine if the string is a valid IP,
|
||||
/// and checks to ensure that the mask is in bounds for the parsed
|
||||
/// IP address type (v4 or v6).
|
||||
pub fn cidr_is_valid(
|
||||
span: &Span,
|
||||
params: &[Ref<Expr>],
|
||||
args: &[Value],
|
||||
_strict: bool,
|
||||
) -> Result<Value> {
|
||||
ensure_args_count(span, "cidr_is_valid", params, args, 1)?;
|
||||
let cidr = ensure_string("cidr_is_valid", ¶ms[0], &args[0])?;
|
||||
|
||||
Ok(Value::from(is_valid_cidr(cidr)))
|
||||
}
|
||||
|
||||
fn is_valid_cidr(cidr: Arc<str>) -> bool {
|
||||
let Some((ip_addr, prefix_len)) = cidr.split_once("/") else {
|
||||
return false;
|
||||
};
|
||||
match ip_addr.parse::<IpAddr>() {
|
||||
Ok(addr) => {
|
||||
let Ok(mask) = prefix_len.parse::<i16>() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
match addr {
|
||||
IpAddr::V4(_) => {
|
||||
if !(0..=32).contains(&mask) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
IpAddr::V6(_) => {
|
||||
if !(0..=128).contains(&mask) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod net_tests {
|
||||
use super::*;
|
||||
use std::vec::Vec;
|
||||
|
||||
#[test]
|
||||
fn test_cidr_is_valid() {
|
||||
let valids = Vec::from(["127.0.0.1/32", "10.0.0.0/8", "0.1.2.3/32", "::1/128"]);
|
||||
let invalids = Vec::from(["256.0.0.0/8", "127.0.0.1/33", "::1/129"]);
|
||||
|
||||
for cidr in valids {
|
||||
assert!(
|
||||
is_valid_cidr(Arc::from(cidr)),
|
||||
"Valid CIDR {cidr} deemed invalid"
|
||||
);
|
||||
}
|
||||
|
||||
for cidr in invalids {
|
||||
assert!(
|
||||
!is_valid_cidr(Arc::from(cidr)),
|
||||
"Invalid CIDR {cidr} deemed valid"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ v0/jsonremoveidempotent
|
||||
v0/jsonschema
|
||||
v0/negation
|
||||
v0/nestedreferences
|
||||
v0/netcidrisvalid
|
||||
v0/numbersrange
|
||||
v0/numbersrangestep
|
||||
v0/objectfilter
|
||||
@@ -149,6 +150,7 @@ v1/jsonremoveidempotent
|
||||
v1/jsonschema
|
||||
v1/negation
|
||||
v1/nestedreferences
|
||||
v1/netcidrisvalid
|
||||
v1/numbersrange
|
||||
v1/numbersrangestep
|
||||
v1/objectfilter
|
||||
|
||||
Reference in New Issue
Block a user