# aa-scan3 **Repository Path**: mirrors_Orange-OpenSource/aa-scan3 ## Basic Information - **Project Name**: aa-scan3 - **Description**: aa-scan3 - an AppArmor profiles generator - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-11-10 - **Last Updated**: 2026-02-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README // vim: ft=asciidoc Introduction ------------ aa-scan3 is a tool to help generate AppArmor profiles by inspecting the executables to protect with AppArmor. aa-scan3 is a build-time tool, not a run-time tool; its intended usage is during build: it does not attempt to run the executable. Instead, it scans it to generate the profile. "Scanning" is a broad description. aa-scan3 is plugins-based, and all plugins are presented the executable. Each plugin has its own "scanning" method: inspecting the file for patterns, looking for associated files on the side, etc... Calling aa-scan3 ---------------- aa-scan3 takes a set of global options, plus the options specified by each plugins. Run `aa-scan3 -h` for the set of options. Writting a plugin ----------------- Plugins must be implemented in Python 3.5, and must work with Python 3.5 or later. [TBC: where to install plugins?] Plugins are named by their file name. E.g. a file named 'foo.py' will declare a plugin named 'foo'. Plugin names must consist of only letters, underscores and numbers. A plugin must contain a docstring at the module-level, that provides the help text for that plugin, help text that will be displayed in the output of `aa-scan3 --help` in a section dedicated to that plugin. The help text is reformatted to fit in the screen, existing paragraphs are retained, and lines starting with +*+ and +-+ are rendered as bullet lists and numbered lists, respectively. A plugin must declare a class named `Scanner`. The constructor for that class must accept a single parameter, `parser`, which is an object that exposes a `add_argument` method that behaves like https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_argument[ArgumentParser.add_argument]. The constructor may call `parser.add_argument()` to register options for that plugin, if needs to. Those options will be registered in the main `aa-scan3` argument parser, with the name of the plugin inserted at the begining of the option. The values for those options are then set as attributes to the single instance of that class. For example, if the plugin `foo` calls `parser.add_argument("--hello")`, then the option `--foo-hello` is registered, and the attribute `hello` is added to the instance of `foo.Scanner()`. Three extra attributes are also set: * `profile`, which represent the current profile to generate; see below for the methods exposed by that object; * `logger`, which exposes the same `debug()` through `critical()` functions that the Python https://docs.python.org/3/library/logging.html[logging module] would, with `critical()` additionally calling `sys.exit(1)` after printing the message; * `root_dir` and `staging_dir`, as set from the generic `aa-scan3` options. NOTE: The attributes are set after the `__init__()` method is called, so they are *not* available in `__init__()`; it is especially not possible to log from `__init__()`. The `profile` attribute added to the plugin instance exposes the following methods: * `get_path()`: returns the path of the input file * `add_path(path, mode)`: add a rule to allow the specified `path` to be accessed with https://gitlab.com/apparmor/apparmor/-/wikis/AppArmor_Core_Policy_Reference#file-permissions[`mode`]. * `add_capability(capability)`: add a rule to allow the specified `capability`, from the list of https://gitlab.com/apparmor/apparmor/-/wikis/AppArmor_Core_Policy_Reference#capability-rules[supported capabilities]. * `add_network(domain, protocol)`: add a rule to allow network access for the the specified https://gitlab.com/apparmor/apparmor/-/wikis/AppArmor_Core_Policy_Reference#network-rules[domain and protocol]. * `start_child_profile(path)`: start a child profile for program at `path`; subsequent calls to `add_path()`, `add_capability()`, or `add_network()` will apply to this child profile. Only one level of child profile nestign is supported. * `end_child_profile()`: end the current child profile; subsequent calls to `add_path()`, `add_capability()`, or `add_network()` will apply to the main profile. * `joinpath(*components)`: like `os.path.join()`, except components with a leading '/' do not ignore previous components. For example, `joinpath('/foo', '/bar')` will yield `/boo/bar`. The `logger` attribute is callable, which is equivalent to calling `logger.debug()`. There are two types of plugins: * +scan+ plugins, which are responsible for scanning a file and generating AppArmor rules (patterns, capabilities, network...); * +mangle+ plugins, which are responsible for transforming the path in the AppArmor pattern rules. A +scan+ plugin must implement either or both the following methods in its `Scanner` class: * `scan(path)`, called by +aa-scan3+ for each file it wants to scan, should return the list of addtional files to scan next to complete the profile; * `once(path)`, like `scan()`, but called only once before any `scan()` method of any plugin is ever called, and should return a list like `scan()` does. A +mangle+ plugin must implement either or both the following methods in its `Scanner` class: * `mangle(path)`, should return a new path with some tansformation applied (e.g. apply a transformation on the path of a rule, like replacing placeholders, etc...). The modified path must still be valid in the context of the parsing (for example, do not use `mangle()` to prepend a chroot path). If this returns an empty string (or `None`), the rule is dropped; * `emit(path)`, like `mangle()`, but only called when the profile rules are actually emitted. `emit()` can be used for example, to prepend a chroot path to the emitted paths. It is not allowed that the returned string be empty (or `None`). A plugin may be both a `scan` plugin and a `mangle` plugin if it implements adequate methods, but this is usually frowned upon.