macaron.policy_engine package

Submodules

macaron.policy_engine.policy_engine module

This module handles invoking the souffle policy engine on a database.

macaron.policy_engine.policy_engine.get_generated(database_path)

Get generated souffle code from database specified by configuration.

Parameters:

database_path (os.PathLike | str) – The path to the database to generate imports and prelude for

Returns:

A program containing the declarations and relations for the schema of this database

Return type:

SouffleProgram

See also

souffle_code_generator.py

macaron.policy_engine.policy_engine.copy_prelude(database_path, sfl, prelude=None)

Generate and copy the prelude into the souffle instance’s include directory.

Parameters:
  • database_path (os.PathLike | str) – The path to the database the facts will be imported from

  • sfl (SouffleWrapper) – The souffle execution context object

  • prelude (SouffleProgram | None) – Optional, the prelude to use for the souffle program, if none is given the default prelude is generated from the database at database_path.

Return type:

None

macaron.policy_engine.policy_engine.run_souffle(database_path, policy_content)

Invoke souffle and report result.

Parameters:
  • database_path (str) – The path to the database to evaluate the policy on

  • policy_content (str) – The Souffle policy code to evaluate

Returns:

A dictionary containing all the relations returned by souffle mapping relation_name to the list of rows.

Return type:

dict

macaron.policy_engine.policy_engine.show_prelude(database_path)

Show the Datalog prelude for a database and exit.

Parameters:

database_path (str) – The SQLite database file to show the prelude for.

Return type:

None

macaron.policy_engine.policy_engine.run_policy_engine(database_path, policy_content)

Evaluate a policy based on configuration and exit.

Parameters:
  • database_path (str) – The SQLite database file to evaluate the policy against

  • policy_content (str) – The Souffle policy code to evaluate

Returns:

The policy engine result.

Return type:

dict

macaron.policy_engine.souffle module

Wrapper classes for invoking souffle by subprocess and getting the resulting tables.

Implements a context manager to create and clean up temporary directories.

exception macaron.policy_engine.souffle.SouffleError(command=None, message='An error occurred with calling Souffle.')

Bases: Exception

Occurs when the souffle program contains errors, or there is an error invoking souffle.

__init__(command=None, message='An error occurred with calling Souffle.')
class macaron.policy_engine.souffle.SouffleWrapper(souffle_full_path='souffle', output_dir=None, include_dir=None, fact_dir=None, library_dir='.')

Bases: object

Wrapper class for managing the temporary working directory of the souffle interpreter.

Examples

with SouffleWrapper(fact_dir=”facts”, output_dir=”output”) as sfl:

text = “<souffle program>” result = sfl.interpret_text(text) assert result == {“path”: [[“1”, “2”], [“1”, “3”], [“2”, “3”]]}

__init__(souffle_full_path='souffle', output_dir=None, include_dir=None, fact_dir=None, library_dir='.')

Create souffle wrapper object.

Parameters:
  • souffle_full_path (str) – The path to the souffle executable.

  • output_dir (str | None) – The path to the souffle program’s output directory.

  • include_dir (str | None) – The path to the directory to search for files when preprocessing the souffle program #include directives.

  • fact_dir (str | None) – The path to search for files to import facts from.

  • library_dir (str) – The path to the directory to search for shared object files when linking souffle functors.

copy_to_includes(filename, text)

Create a file with in the include directory.

Parameters:
  • filename (str) – The base name of the file

  • text (str) – The text of the file to create

Return type:

None

interpret_file(filename, with_prelude='')

Interpret a file.

Parameters:
  • filename (str the file to run.)

  • with_prelude (str string literal to append to the start of the file before running it.)

Return type:

dict

interpret_text(text)

Interpret a string literal.

Parameters:

text (str string literal to interpret)

Return type:

dict

load_csv_output()

Load and return all the csv files from the temporary working directory.

Return type:

dict

macaron.policy_engine.souffle_code_generator module

Generate souffle datalog for policy prelude.

class macaron.policy_engine.souffle_code_generator.SouffleProgram(declarations=None, directives=None, rules=None)

Bases: object

Class to store generated souffle datalog program.

Parameters:
  • declarations (None | set[str]) – Set of declaration souffle statements (begin with .decl token)

  • directives (None | set[str]) – Set of directives (begin with “.”, e.g. .input)

  • rules (None | set[str]) – Set of datalog rules (statements containing “:-” )

__init__(declarations=None, directives=None, rules=None)
rules: set[str]
directives: set[str]
declarations: set[str]
update(other)

Merge another program into this one.

Parameters:

other (SouffleProgram) – The program to merge into self

Returns:

self, after other has been merged into it

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.column_to_souffle_type(column)

Return a souffle type string for a SQLAlchemy Column.

Return type:

str

macaron.policy_engine.souffle_code_generator.table_to_declaration(table)

Return the souffle datalog declaration for an SQLAlchemy table.

Examples

>>> from sqlalchemy import Column, MetaData, Table
>>> from sqlalchemy.sql.sqltypes import Boolean, Integer, String, Text
>>> metadata = MetaData()
>>> tbl = Table("_example", metadata, Column("id", Integer, nullable=False), Column("hello", String))
>>> assert table_to_declaration(tbl) == '.decl example (id: number, hello: symbol)'
Parameters:

table (Table) – The sqlalchemy Table to generate a .decl statement for

Returns:

Datalog declaration corresponding to table

Return type:

str

macaron.policy_engine.souffle_code_generator.get_fact_declarations(metadata)

Get declarations for all mapped tables with names beginning with an underscore and therefore importable by souffle.

Parameters:

metadata (MetaData) – SqlAlchemy orm metadata object

Returns:

The set of fact declaration statements, in its declaration field, for all the mapped tables (known to metadata) whose names begin with an ‘_’.

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.get_fact_input_statements(db_name, metadata)

Return a list of input directives for all the mapped tables beginning with an ‘_’.

Parameters:
  • db_name (os.PathLike | str) – The database path to import the data from into souffle (absolute path recommended).

  • metadata (MetaData) – The SQLAlchemy MetaData object containing the table definitions to generate input statements for.

Returns:

Program containing the set of .input statements, in the directive field, for all tables known to metadata that with an ‘_’.

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.get_souffle_import_prelude(db_name, metadata)

Return souffle datalog code to import all relevant mapped tables.

Parameters:
  • db_name (os.PathLike | str) – The path to the database the souffle program will import facts from (absolute path recommended)

  • metadata (MetaData) – SQLAlchemy MetaData object containing table information

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.project_join_table_souffle_relation(rule_name, left_table, left_common_fields, right_table, right_common_fields, right_ignore_fields, prefix_table_name_to_key=True)

Generate souffle datalog to join two tables together.

This creates a relation that will appear as

rule_name(left, common, fields, “right_column_name”, right_column_value) :-

left_relation(left, common, _, fields, _), right_relation(right_column_value, _ …).

rule_name(left, common, fields, “right_column_name_2”, right_column_value) :-

left_relation(left, common, _, fields, _), right_relation(_, right_column_value, …).

Parameters:
  • rule_name (str) – The name of the rule to generate

  • left_table (Table) – The table to appear on the left of the relation (the “subject”)

  • left_common_fields (dict[str, str]) – The columns to include on the left of the relation, mapped to the names they should have in the declaration

  • right_table (Table) – The table on the right hand side of the relation (the “predicate”)

  • right_common_fields (dict[str, str]) – The columns from the right table that should appear on the left of the relation

  • right_ignore_fields (list[str]) – The columns that should not appear in the relation

  • prefix_table_name_to_key (bool) – Should the key field of the relation be prefixed with the table name: so that it appears as “tableName.columnName”

Returns:

A program containing rules to declare and derive the relations containing the fields:
(left_common_fields UNION right_common_fields)

PRODUCT ((right_table.columns - right_ignore_fields - right_table.foreign_key_columns) + (foreign_columns where foreign_columns in right_table.foreign_key_columns.tables, and foreign_columns not primary keys))

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.get_table_rules_per_column(rule_name, table, common_fields, ignore_columns)

Generate datalog rules to create subject-predicate relations from a set of columns of a table.

Parameters:
  • rule_name (str) – The name of the resulting souffle rule

  • table (Table) – The sqlalchemy table to read from

  • common_fields (dict[str, str]) – The table columns to be included in the relation (as the subject) key: the column name value: the corresponding relation field name

  • ignore_columns (list[str]) – List of column names to be excluded from the relation

Returns:

Program to declare and construct the rules

common_fields PRODUCT (table.columns - common_fields - ignore_columns)

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.project_with_fk_join(table)

Create attribute relations joining on foreign keys.

For each foreign key in this table, creates a relation for the reference table which receives this table’s values. See: project_join_table_souffle_relation

Parameters:

table (Table) – The table to create the projected rules for

Returns:

The program containing declarations and rules to derive subject-predicate “attribute” relations from the importable tables (tables beginning with ‘_’).

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.project_table_to_key(relation_name, table)

Create rules to convert a table to an attribute that maps its primary keys to its columns.

Return type:

SouffleProgram

macaron.policy_engine.souffle_code_generator.restrict_to_analysis(analyses)

Create relations to restrict the policy analysis to a specific analysis instance (an invocation of souffle).

Parameters:

analyses (list[int]) – The list of analysis IDs (the primary key of the _analysis table) to evaluate the policy for.

Return type:

SouffleProgram