SaltStack Management

The REMnux distro uses SaltStack to automate the installation and configuration of the tools that comprise the distro. This is accomplished using Salt state files, each one describing the steps necessary to set up the software component. These files are stored in the REMnux/salt-states repository on Github, and are available for your review. Read on to learn how REMnux uses these State Files to manage the configuration of a REMnux system.

REMnux uses SaltStack for locally managing the configuration of the system where the distro is installed. It doesn't use other SaltStack capabilities, such as remote command execution.

A state file can direct SaltStack to install a tool by supporting a variety of formats in which such tools migh be packages, including Ubuntu packages, pip modules, Git repositories, Ruby gems, etc. Each state file represents one aspect of the state in which the system should be after SaltStack runs. The files follow the YAML markup language.

Salt State File to Install an Ubuntu Package

For example, here's the Salt state file edb-debgger.sls for installing edb, a powerful debugger for examining ELF binaries:

include:
- remnux.repos.remnux
- remnux.packages.xterm
edb-debugger:
pkg.installed:
- pkgrepo: remnux
- require:
- sls: remnux.packages.xterm

The line edb-debugger: specifies the name of the Ubuntu package that SaltStack should install. The pkgrepo: remnux line specifies that SaltStack will find this package in the Ubuntu package repository named "remnux." The require statement explains that this package depends on "xterm." The distro also includes state files that explain SaltStack should install the remnux repository and the xterm package.

Salt State File to Install a pip Package

Here's an example of a Salt state file pyzipper.sls to install pyzipper, a Python library for interacting with Zip file archives. SaltStack will use the Python 3 version of pip (pip3), which is installed using remnux.packages.python3-pip, to install pyzipper from the standard PyPI repository of Python software:

include:
- remnux.packages.python3-pip
- remnux.packages.python-pip
remnux-python-packages-pyzipper:
pip.installed:
- name: pyzipper
- bin_env: /usr/bin/pip3
- require:
- sls: remnux.packages.python3-pip

Even though the module will be installed using pip3, SaltStack needs that the Python 2 version of pip be specified in the include: statement (for some reason).

For another example, consider the state file peframe.sls for installing peframe, which helps with the analysis of Windows executables and Microsoft Office documents. In this case, SaltStack is directed to retrieve the latest version of peframe from its Github repository, because it's not available on PyPI. The GitHub repository includes the setup.py for this tool, which allows pip to install it. The State File explicitly specifies the need to install several dependencies when installing this tool.

include:
- remnux.packages.git
- remnux.packages.libssl-dev
- remnux.packages.swig
- remnux.packages.python3-pip
- remnux.packages.python-pip
remnux-pip-peframe:
pip.installed:
- name: git+https://github.com/guelfoweb/peframe.git@master
- bin_env: /usr/bin/python3
- require:
- sls: remnux.packages.git
- sls: remnux.packages.libssl-dev
- sls: remnux.packages.swig
- sls: remnux.packages.python3-pip
- sls: remnux.packages.python-pip

For a more in-depth look at the peframe.sls file, consider this:

  • remnux-pip-peframe is the name or description of the state.

  • pip.installed is the "Salt state function."

  • name and require are the parameters the pip.installed SaltStack function.

The state files listed using the require parameter ensure that SaltStack will install these dependencies in the specified order; it will only execute pip.installed if these the installation of these dependencees succeeds. Each of these dependencies has its own Salt State file.

In the peframe.sls example above, the reference to python-pip is needed for some reason even though the tool relies on python3-pip. Without it, SaltStack produces an error even as it attempts to install the tool using python3-pip.

Salt State File to Configure a Tool

REMnux also uses Salt state files configure the environment and the tools installed as part of the distro. For example, here's a short excerpt from the Salt state file that configures Ghidra, which is a reverse-engineering tool that includes a disassembler and debugger. (The installation of Ghira is handled using a separate ghidra.sls file.)

remnux-config-ghidra-file-preferences:
file.managed:
- name: {{ home }}/.ghidra/.ghidra_9.1.2_PUBLIC/preferences
- source: salt://remnux/config/ghidra/preferences
- replace: False
- user: {{ user }}
- group: {{ user }}
- makedirs: True
- require:
- user: remnux-user-{{ user }}
- watch:
- file: remnux-config-ghidra-gdt-owner

In the example above:

  • file.managed specifies the desired state of the Ghidra "preferences" file, located in the user's home directory.

  • source of the file is the version of "preferences" in the GitHub repository where this state file resides; this directs SaltStack to copy this file to the location specified by name.

  • replace directs SaltStack not to replace the file if it already exists.

  • user and group specify that the file should be owned by the user and the user's group.

  • makedirs direct SaltStack to create the directory structure so the file can be placed in the location specified by name.

The state file instructions above rely on the values home and user, which are set earlier in the file:

{%- set user = salt['pillar.get']('remnux_user', 'remnux') -%}
{%- if user == "root" -%}
{%- set home = "/root" -%}
{%- else %}
{%- set home = "/home/" + user -%}
{%- endif -%}

This excerpt from the Ghidra configuration state file uses the "pillars" feature of SaltStack, which gives SaltStack access to named values defined before the state file has a chance to run. In this case, the state file sets the user value by retrieving the pillar variable named remnux_user, which is normally set by the REMnux installer; if it's not available, SaltStack is directed to use the default value "remnux." Further, depending on the user value, the state file sets the home value to point to the user's home directory.