Skip to content
This repository has been archived by the owner. It is now read-only.

Commit

Permalink
Merge pull request #223 from HubbleStack/develop
Browse files Browse the repository at this point in the history
Merge develop to master
  • Loading branch information
basepi authored Aug 8, 2016
2 parents d52bb06 + d92ba75 commit 4bea33b
Show file tree
Hide file tree
Showing 68 changed files with 24,002 additions and 1,222 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@ target/

# Pycharm
.idea

# Mac files
.DS_STORE
.DS_Store
7 changes: 7 additions & 0 deletions FORMULA
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: hubblestack_nova
os: RedHat, CentOS, Debian, Ubuntu
os_family: RedHat, Debian
version: 2016.7.0_RC2
release: 1
summary: HubbleStack Nova
description: HubbleStack Nova
292 changes: 231 additions & 61 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,60 +1,96 @@
Nova
====
Introduction
============

Nova is designed to audit the compliance and security level of a system. It is
composed of multiple modules, which ingest YAML configuration profiles to run a
single or series of audits against a system.

Two different installation methods are outlined below. The first method is more
stable (and therefore recommended). This method uses Salt's package manager to
track versioned, packaged updates to Hubble's components.

Nova plugins are designed specifically for auditing the compliance and security level
of an existing system. These plugins are designed to alow an administrator to
run security checks or even groups of security checks within their SaltStack
installation. This allows for real-time insight into the compliance level of
running systems.
The second method installs directly from git. It should be considered bleeding
edge and possibly unstable.

Installation
============

Place `hubble.py <_modules/hubble.py>`_ in your ``_modules/`` directory in your Salt
fileserver (whether roots or gitfs) and sync it to the minion.
Each of the four HubbleStack components have been packaged for use with Salt's
Package Manager (SPM). Note that all SPM installation commands should be done
on the *Salt Master*.

Create a ``hubblestack_nova`` directory in the root of your Salt fileserver's
``base`` environment. Inside of this directory, create a directory tree to
organize your audit modules. Place any desired audit modules into this
directory tree, along with any supporting files (yaml files, etc). Nova audits
are targeted via this directory structure, with an optional filter on tags
**Required Configuration**

The directory/environment in which nova searches for audit modules are
configurable via pillar. The defaults are shown below:
Salt's Package Manager (SPM) installs files into ``/srv/spm/{salt,pillar}``.
Ensure that this path is defined in your Salt Master's ``file_roots``:

.. code-block:: yaml
hubblestack.nova.dir: salt://hubblestack_nova
hubblestack.nova.saltenv: base
file_roots:
- /srv/salt
- /srv/spm/salt
Usage
=====
.. note:: This should be the default value. To verify run: ``salt-call config.get file_roots``

There are three functions in the hubble.py module. ``hubble.sync`` will sync the
configured ``hubblestack_nova/`` directory to the minion. ``hubble.load`` will
load the synced audit modules and their yaml configuration files. Finally,
``hubble.audit`` will run the audits.
.. tip:: Remember to restart the Salt Master after making this change to the configuration.

By default, ``hubble.audit`` will call ``hubble.load`` (which in turn calls
``hubble.sync``) (in order to ensure that it is auditing with the most up-to-date
information. These operations are fairly fast, but if you want to avoid the
additional overhead, you can disable these behaviors via pillar (defaults are
shown, change to False to disable behaviors):
Installation (Packages)
-----------------------

.. code-block:: yaml
Installation is as easy as downloading and installing a package. (Note: in
future releases you'll be able to subscribe directly to our HubbleStack SPM
repo for updates and bugfixes!)

.. code-block:: shell
wget https://spm.hubblestack.io/2016.7.0/hubblestack_nova-2016.7.0-1.spm
spm local install hubblestack_nova-2016.7.0-1.spm
You should now be able to sync the new modules to your minion(s) using the
``sync_modules`` Salt utility:

.. code-block:: shell
salt \* saltutil.sync_modules
Once these modules are synced you are ready to run a HubbleStack Nova audit.

Skip to [Usage].

hubblestack.nova.autosync: True
hubblestack.nova.autoload: True
Installation (Manual)
---------------------

Place ``_modules/hubble.py`` into your ``salt/_modules/`` directory, and sync
it to the minions.

.. code-block:: shell
git clone https://github.com/hubblestack/nova.git hubblestack-nova.git
cd hubblestack-nova.git
mkdir -p /srv/salt/_modules/
cp _modules/hubble.py /srv/salt/_modules/
cp -a hubblestack_nova /srv/salt/
salt \* saltutil.sync_modules
salt \* hubble.sync
Usage
=====

There are four primary functions in the hubble.py module:

1. ``hubble.sync`` will sync the ``hubblestack_nova/`` directory to the minion(s).
2. ``hubble.load`` will load the synced audit modules and their yaml configuration files.
3. ``hubble.audit`` will audit the minion(s) using the YAML profile(s) you provide as comma-separated arguments
4. ``hubble.top`` will audit the minion(s) using the ``top.nova`` configuration.

``hubble.audit`` takes two optional arguments. The first is a comma-separated
list of paths. These paths can be files or directories. If a path is a
directory, all modules below that directory will be run. If it is a file, that
file will be run.
list of paths. These paths can be files or directories within the
``hubblestack_nova`` directory. The second argument allows for toggling Nova
configuration, such as verbosity, level of detail, etc.

The second argument is a glob pattern, against which audit tags will be
matched. All audits have an accompanying tag. Nova modules are designed to take
this argument, compare it to each tag that module handles, and only run those
which match the argument (using ``fnmatch``).
If ``hubble.audit`` is run without targeting any audit configs or directories,
it will instead run ``hubble.top`` with no arguments.

``hubble.audit`` will return a list of audits which were successful, and a list
of audits which failed.
Expand All @@ -63,17 +99,136 @@ Here are some example calls:

.. code-block:: bash
# Run all yaml configs and tags under salt://hubblestack_nova/
salt '*' hubble.audit
# Run the cve scanner and the CIS profile:
salt \* hubble.audit cve.scan-v2,cis.centos-7-level-1-scored-v1
# Run all yaml configs and tags under salt://hubblestack_nova/foo/
# Will also run salt://hubblestack_nova/foo.yaml if it exists
salt '*' hubble.audit modules=foo
# Run hubble.top with the default topfile (top.nova)
salt \* hubble.top
# Run all yaml configs and tags under salt://hubblestack_nova/foo/ and
# salt://hubblestack_nova/bar, but only run audits with tags starting
# with "CIS"
salt '*' hubble.audit modules=foo,bar tags='CIS*'
salt \* hubble.audit foo,bar tags='CIS*'
Nova Topfiles
-------------

Nova topfiles look very similar to saltstack topfiles, except the top-level
key is always ``nova``, as nova doesn't have environments.

.. code-block:: yaml
nova:
'*':
- cve.scan-v2
- network.ssh
- network.smtp
'web*':
- cis.centos-7-level-1-scored-v1
- cis.centos-7-level-2-scored-v1
'G@os_family:debian':
- network.ssh
- cis.debian-7-level-1-scored: 'CIS*'
Additionally, all nova topfile matches are compound matches, so you never
need to define a match type like you do in saltstack topfiles.

Each list item is a string representing the dot-separated location of a
yaml file which will be run with hubble.audit. You can also specify a
tag glob to use as a filter for just that yaml file, using a colon
after the yaml file (turning it into a dictionary). See the last two lines
in the yaml above for examples.

Examples:

.. code-block:: bash
salt '*' hubble.top
salt '*' hubble.top foo/bar/top.nova
salt '*' hubble.top foo/bar.nova verbose=True
Compensating Control Configuration
----------------------------------

In some cases, your organization may want to skip certain audit checks for
certain hosts. This is supported via compensating control configuration.

You can skip a check globally by adding a ``control: <reason>`` key to the check
itself. This key should be added at the same level as ``description`` and
``trigger`` pieces of a check. In this case, the check will never run, and will
output under the ``Controlled`` results key.

Nova also supports separate control profiles, for more fine-grained control
using topfiles. You can use a separate YAML top-level key called ``control``.
Generally, you'll put this top-level key inside of a separate YAML file and
only include it in the top-data for the hosts for which it is relevant.

For these separate control configs, the audits will always run, whether they
are controlled or not. However, controlled audits which fail will be converted
from ``Failure`` to ``Controlled`` in a post-processing operation.

The control config syntax is as follows:

.. code-block:: yaml
control:
- CIS-2.1.4: This is the reason we control the check
- some_other_tag:
reason: This is the reason we control the check
- a_third_tag_with_no_reason
Note that providing a reason for the control is optional. Any of the three
formats shown in the yaml list above will work.

Once you have your compensating control config, just target the yaml to the
hosts you want to control using your topfile. In this case, all the audits will
still run, but if any of the controlled checks fail, they will be removed from
``Failure`` and added to ``Controlled``, and will be treated as a Success for
the purposes of compliance percentage.


Schedule
--------

In order to run the audits once daily, you can use the following schedule:

.. code-block:: yaml
schedule:
nova_day:
function: hubble.top
seconds: 86400
Configuration
=============

Under the Hood
==============

1. The directory/environment in which nova searches for audit modules are
configurable via pillar. The defaults are shown below:

.. code-block:: yaml
hubblestack:
nova:
saltenv: base
dir: salt://hubblestack_nova
2. By default, ``hubble.audit`` will call ``hubble.load`` (which in turn calls
``hubble.sync``) in order to ensure that it is auditing with the most up-to-date
information. These operations are fairly fast, but if you want to avoid the
additional overhead, you can disable these behaviors via pillar (defaults are
shown, change to False to disable behaviors):

.. code-block:: yaml
hubblestack:
nova:
autosync: True
autoload: True
Development
===========
Expand Down Expand Up @@ -114,14 +269,17 @@ include full documentation
return True
def audit(data_list, tag, verbose=False):
def audit(data_list, tag, verbose=False, show_profile=False, debug=False):
__tags__ = []
for data in data_list:
for profile, data in data_list:
# This is where you process the dictionaries passed in by hubble.py,
# searching for data pertaining to this audit module. Modules which
# require no data should use yaml which is empty except for a
# top-level key, and should only do work if the top-level key is
# found in the data
# if show_profile is True, then we need to also inject the profile
# in the data for each check so that it appears in verbose output
pass
ret = {'Success': [], 'Failure': []}
Expand All @@ -137,17 +295,29 @@ All Nova plugins require a ``__virtual__()`` function to determine module
compatibility, and an ``audit()`` function to perform the actual audit
functionality

The ``audit()`` function must take three arguments, ``data_list``, ``tag`` and
``verbose``. The ``data_list`` argument is a list of dictionaries passed in by
``hubble.py``. ``hubble.py`` gets this data from loading the specified yaml for
the audit run. Your audit module should only run if it finds its own data in
this list. The ``tag`` argument is a glob expression for which tags the audit
function should run. It is the job of the audit module to compare the ``tag``
glob with all tags supported by this module and only run the audits which
match. The ``verbose`` argument defines whether additional information should
be returned for audits, such as description and remediation instructions.

The return value should be a dictionary, with two keys, "Success" and
"Failure". The values for these keys should be a list of tags as strings, or a
list of dictionaries containing tags and other information for the audit (in
the case of ``verbose``).
The ``audit()`` function must take four arguments, ``data_list``, ``tag``,
``verbose``, ``show_profile``, and ``debug``. The ``data_list`` argument is a
list of dictionaries passed in by ``hubble.py``. ``hubble.py`` gets this data
from loading the specified yaml for the audit run. Your audit module should
only run if it finds its own data in this list. The ``tag`` argument is a glob
expression for which tags the audit function should run. It is the job of the
audit module to compare the ``tag`` glob with all tags supported by this module
and only run the audits which match. The ``verbose`` argument defines whether
additional information should be returned for audits, such as description and
remediation instructions. The ``show_profile`` argument tells whether the
profile should be injected into the verbose data for each check. The ``debug``
argument tells whether the module should log additional debugging information
at debug log level.

The return value should be a dictionary, with optional keys "Success",
"Failure", and "Controlled". The values for these keys should be a list of
one-key dictionaries in the form of ``{<tag>: <string_description>}``, or a
list of one-key dictionaries in the form of ``{<tag>: <data_dict>}`` (in the
case of ``verbose``).

Contribute
==========

If you are interested in contributing or offering feedback to this project feel
free to submit an issue or a pull request. We're very open to community
contribution.
Loading

0 comments on commit 4bea33b

Please sign in to comment.