@@ -23,6 +23,31 @@ pub struct Engine {
2323 rego_v1 : bool ,
2424}
2525
26+ #[ derive( Debug , Clone , Serialize ) ]
27+ pub struct PolicyPackageNameDefinition {
28+ pub source_file : String ,
29+ pub package_name : String ,
30+ }
31+
32+ #[ derive( Debug , Clone , Serialize ) ]
33+ pub struct PolicyParameter {
34+ pub name : String ,
35+ pub modifiable : bool ,
36+ pub required : bool ,
37+ }
38+
39+ #[ derive( Debug , Clone , Serialize ) ]
40+ pub struct PolicyModifier {
41+ pub name : String ,
42+ }
43+
44+ #[ derive( Debug , Clone , Serialize ) ]
45+ pub struct PolicyParameters {
46+ pub source_file : String ,
47+ pub parameters : Vec < PolicyParameter > ,
48+ pub modifiers : Vec < PolicyModifier > ,
49+ }
50+
2651/// Create a default engine.
2752impl Default for Engine {
2853 fn default ( ) -> Self {
@@ -907,6 +932,113 @@ impl Engine {
907932 serde_json:: to_string_pretty ( & ast) . map_err ( anyhow:: Error :: msg)
908933 }
909934
935+ /// Get the package names of each policy added to the engine.
936+ ///
937+ ///
938+ /// ```rust
939+ /// # use regorus::*;
940+ /// # use anyhow::{bail, Result};
941+ /// # fn main() -> Result<()> {
942+ /// # let mut engine = Engine::new();
943+ /// engine.add_policy("test.rego".to_string(), "package test\n x := 1".to_string())?;
944+ /// engine.add_policy("test2.rego".to_string(), "package test.multi.segment\n x := 1".to_string())?;
945+ ///
946+ /// let package_names = engine.get_policy_package_names()?;
947+ ///
948+ /// assert_eq!("test", package_names[0].package_name);
949+ /// assert_eq!("test.multi.segment", package_names[1].package_name);
950+ /// # Ok(())
951+ /// # }
952+ /// ```
953+ #[ cfg( feature = "azure_policy" ) ]
954+ #[ cfg_attr( docsrs, doc( cfg( feature = "azure_policy" ) ) ) ]
955+ pub fn get_policy_package_names ( & self ) -> Result < Vec < PolicyPackageNameDefinition > > {
956+ let mut package_names = vec ! [ ] ;
957+ for m in & self . modules {
958+ let package_name = Interpreter :: get_path_string ( & m. package . refr , None ) ?;
959+ package_names. push ( PolicyPackageNameDefinition {
960+ source_file : m. package . span . source . file ( ) . to_string ( ) ,
961+ package_name,
962+ } ) ;
963+ }
964+
965+ Ok ( package_names)
966+ }
967+
968+ /// Get the parameters defined in each policy.
969+ ///
970+ ///
971+ /// ```rust
972+ /// # use regorus::*;
973+ /// # use anyhow::{bail, Result};
974+ /// # fn main() -> Result<()> {
975+ /// # let mut engine = Engine::new();
976+ /// engine.add_policy("test.rego".to_string(), "package test default parameters.a = 5 parameters.b = 10\n x := 1".to_string())?;
977+ ///
978+ /// let parameters = engine.get_policy_parameters()?;
979+ ///
980+ /// assert_eq!("a", parameters[0].parameters[0].name);
981+ /// assert_eq!("b", parameters[0].modifiers[0].name);
982+ ///
983+ /// # Ok(())
984+ /// # }
985+ /// ```
986+ #[ cfg( feature = "azure_policy" ) ]
987+ #[ cfg_attr( docsrs, doc( cfg( feature = "azure_policy" ) ) ) ]
988+ pub fn get_policy_parameters ( & self ) -> Result < Vec < PolicyParameters > > {
989+ let mut policy_parameter_definitions = vec ! [ ] ;
990+ for m in & self . modules {
991+ let mut parameters = vec ! [ ] ;
992+ let mut modifiers = vec ! [ ] ;
993+
994+ for rule in & m. policy {
995+ // Extract parameter definitions from the policy rule
996+ // e.g. default parameters.a = 5
997+ if let Rule :: Default { refr, .. } = rule. as_ref ( ) {
998+ let path = Parser :: get_path_ref_components ( refr) ?;
999+ let paths: Vec < & str > = path. iter ( ) . map ( |s| s. text ( ) ) . collect ( ) ;
1000+
1001+ if paths. len ( ) == 2 && paths[ 0 ] == "parameters" {
1002+ // Todo: Fetch fields other than name from rego metadoc for the parameter
1003+ parameters. push ( PolicyParameter {
1004+ name : paths[ 1 ] . to_string ( ) ,
1005+ modifiable : false ,
1006+ required : false ,
1007+ } )
1008+ }
1009+ }
1010+
1011+ // Extract modifiers to the parameters from the policy rule
1012+ // e.g. parameters.a = 5
1013+ if let Rule :: Spec { head, .. } = rule. as_ref ( ) {
1014+ match head {
1015+ RuleHead :: Compr { refr, .. } => {
1016+ let path = Parser :: get_path_ref_components ( refr) ?;
1017+ let paths: Vec < & str > = path. iter ( ) . map ( |s| s. text ( ) ) . collect ( ) ;
1018+
1019+ if paths. len ( ) == 2 && paths[ 0 ] == "parameters" {
1020+ // Todo: Fetch fields other than name from rego metadoc for the parameter
1021+ modifiers. push ( PolicyModifier {
1022+ name : paths[ 1 ] . to_string ( ) ,
1023+ } )
1024+ }
1025+ }
1026+ RuleHead :: Func { .. } => { }
1027+ RuleHead :: Set { .. } => { }
1028+ }
1029+ }
1030+ }
1031+
1032+ policy_parameter_definitions. push ( PolicyParameters {
1033+ source_file : m. package . span . source . file ( ) . to_string ( ) ,
1034+ parameters,
1035+ modifiers,
1036+ } ) ;
1037+ }
1038+
1039+ Ok ( policy_parameter_definitions)
1040+ }
1041+
9101042 fn make_parser < ' a > ( & self , source : & ' a Source ) -> Result < Parser < ' a > > {
9111043 let mut parser = Parser :: new ( source) ?;
9121044 if self . rego_v1 {
0 commit comments