1- Nova
2- ====
1+ Introduction
2+ ============
3+
4+ Nova is designed to audit the compliance and security level of a system. It is
5+ composed of multiple modules, which ingest YAML configuration profiles to run a
6+ single or series of audits against a system.
7+
8+ Two different installation methods are outlined below. The first method is more
9+ stable (and therefore recommended). This method uses Salt's package manager to
10+ track versioned, packaged updates to Hubble's components.
311
4- Nova plugins are designed specifically for auditing the compliance and security level
5- of an existing system. These plugins are designed to alow an administrator to
6- run security checks or even groups of security checks within their SaltStack
7- installation. This allows for real-time insight into the compliance level of
8- running systems.
12+ The second method installs directly from git. It should be considered bleeding
13+ edge and possibly unstable.
914
1015Installation
1116============
1217
13- Place `hubble.py <_modules/hubble.py >`_ in your ``_modules/ `` directory in your Salt
14- fileserver (whether roots or gitfs) and sync it to the minion.
18+ Each of the four HubbleStack components have been packaged for use with Salt's
19+ Package Manager (SPM). Note that all SPM installation commands should be done
20+ on the *Salt Master *.
1521
16- Create a ``hubblestack_nova `` directory in the root of your Salt fileserver's
17- ``base `` environment. Inside of this directory, create a directory tree to
18- organize your audit modules. Place any desired audit modules into this
19- directory tree, along with any supporting files (yaml files, etc). Nova audits
20- are targeted via this directory structure, with an optional filter on tags
22+ **Required Configuration **
2123
22- The directory/environment in which nova searches for audit modules are
23- configurable via pillar. The defaults are shown below :
24+ Salt's Package Manager (SPM) installs files into `` /srv/spm/{salt,pillar} ``.
25+ Ensure that this path is defined in your Salt Master's `` file_roots `` :
2426
2527.. code-block :: yaml
2628
27- hubblestack.nova.dir : salt://hubblestack_nova
28- hubblestack.nova.saltenv : base
29+ file_roots :
30+ - /srv/salt
31+ - /srv/spm/salt
2932
30- Usage
31- =====
33+ .. note :: This should be the default value. To verify run: ``salt-call config.get file_roots``
3234
33- There are three functions in the hubble.py module. ``hubble.sync `` will sync the
34- configured ``hubblestack_nova/ `` directory to the minion. ``hubble.load `` will
35- load the synced audit modules and their yaml configuration files. Finally,
36- ``hubble.audit `` will run the audits.
35+ .. tip :: Remember to restart the Salt Master after making this change to the configuration.
3736
38- By default, ``hubble.audit `` will call ``hubble.load `` (which in turn calls
39- ``hubble.sync ``) (in order to ensure that it is auditing with the most up-to-date
40- information. These operations are fairly fast, but if you want to avoid the
41- additional overhead, you can disable these behaviors via pillar (defaults are
42- shown, change to False to disable behaviors):
37+ Installation (Packages)
38+ -----------------------
4339
44- .. code-block :: yaml
40+ Installation is as easy as downloading and installing a package. (Note: in
41+ future releases you'll be able to subscribe directly to our HubbleStack SPM
42+ repo for updates and bugfixes!)
43+
44+ .. code-block :: shell
45+
46+ wget https://spm.hubblestack.io/2016.7.0/hubblestack_nova-2016.7.0-1.spm
47+ spm local install hubblestack_nova-2016.7.0-1.spm
48+
49+ You should now be able to sync the new modules to your minion(s) using the
50+ ``sync_modules `` Salt utility:
51+
52+ .. code-block :: shell
53+
54+ salt \* saltutil.sync_modules
55+
56+ Once these modules are synced you are ready to run a HubbleStack Nova audit.
57+
58+ Skip to [Usage].
4559
46- hubblestack.nova.autosync : True
47- hubblestack.nova.autoload : True
60+ Installation (Manual)
61+ ---------------------
62+
63+ Place ``_modules/hubble.py `` into your ``salt/_modules/ `` directory, and sync
64+ it to the minions.
65+
66+ .. code-block :: shell
67+
68+ git clone https://github.com/hubblestack/nova.git hubblestack-nova.git
69+ cd hubblestack-nova.git
70+ mkdir -p /srv/salt/_modules/
71+ cp _modules/hubble.py /srv/salt/_modules/
72+ cp -a hubblestack_nova /srv/salt/
73+
74+ salt \* saltutil.sync_modules
75+ salt \* hubble.sync
76+
77+ Usage
78+ =====
79+
80+ There are four primary functions in the hubble.py module:
81+
82+ 1. ``hubble.sync `` will sync the ``hubblestack_nova/ `` directory to the minion(s).
83+ 2. ``hubble.load `` will load the synced audit modules and their yaml configuration files.
84+ 3. ``hubble.audit `` will audit the minion(s) using the YAML profile(s) you provide as comma-separated arguments
85+ 4. ``hubble.top `` will audit the minion(s) using the ``top.nova `` configuration.
4886
4987``hubble.audit `` takes two optional arguments. The first is a comma-separated
50- list of paths. These paths can be files or directories. If a path is a
51- directory, all modules below that directory will be run. If it is a file, that
52- file will be run .
88+ list of paths. These paths can be files or directories within the
89+ `` hubblestack_nova `` directory. The second argument allows for toggling Nova
90+ configuration, such as verbosity, level of detail, etc .
5391
54- The second argument is a glob pattern, against which audit tags will be
55- matched. All audits have an accompanying tag. Nova modules are designed to take
56- this argument, compare it to each tag that module handles, and only run those
57- which match the argument (using ``fnmatch ``).
92+ If ``hubble.audit `` is run without targeting any audit configs or directories,
93+ it will instead run ``hubble.top `` with no arguments.
5894
5995``hubble.audit `` will return a list of audits which were successful, and a list
6096of audits which failed.
@@ -63,17 +99,136 @@ Here are some example calls:
6399
64100.. code-block :: bash
65101
66- # Run all yaml configs and tags under salt://hubblestack_nova/
67- salt ' * ' hubble.audit
102+ # Run the cve scanner and the CIS profile:
103+ salt \* hubble.audit cve.scan-v2,cis.centos-7-level-1-scored-v1
68104
69- # Run all yaml configs and tags under salt://hubblestack_nova/foo/
70- # Will also run salt://hubblestack_nova/foo.yaml if it exists
71- salt ' *' hubble.audit modules=foo
105+ # Run hubble.top with the default topfile (top.nova)
106+ salt \* hubble.top
72107
73108 # Run all yaml configs and tags under salt://hubblestack_nova/foo/ and
74109 # salt://hubblestack_nova/bar, but only run audits with tags starting
75110 # with "CIS"
76- salt ' *' hubble.audit modules=foo,bar tags=' CIS*'
111+ salt \* hubble.audit foo,bar tags=' CIS*'
112+
113+
114+ Nova Topfiles
115+ -------------
116+
117+ Nova topfiles look very similar to saltstack topfiles, except the top-level
118+ key is always ``nova ``, as nova doesn't have environments.
119+
120+ .. code-block :: yaml
121+
122+ nova :
123+ ' * ' :
124+ - cve.scan-v2
125+ - network.ssh
126+ - network.smtp
127+ ' web* ' :
128+ - cis.centos-7-level-1-scored-v1
129+ - cis.centos-7-level-2-scored-v1
130+ ' G@os_family:debian ' :
131+ - network.ssh
132+ - cis.debian-7-level-1-scored : ' CIS*'
133+
134+ Additionally, all nova topfile matches are compound matches, so you never
135+ need to define a match type like you do in saltstack topfiles.
136+
137+ Each list item is a string representing the dot-separated location of a
138+ yaml file which will be run with hubble.audit. You can also specify a
139+ tag glob to use as a filter for just that yaml file, using a colon
140+ after the yaml file (turning it into a dictionary). See the last two lines
141+ in the yaml above for examples.
142+
143+ Examples:
144+
145+ .. code-block :: bash
146+
147+ salt ' *' hubble.top
148+ salt ' *' hubble.top foo/bar/top.nova
149+ salt ' *' hubble.top foo/bar.nova verbose=True
150+
151+
152+ Compensating Control Configuration
153+ ----------------------------------
154+
155+ In some cases, your organization may want to skip certain audit checks for
156+ certain hosts. This is supported via compensating control configuration.
157+
158+ You can skip a check globally by adding a ``control: <reason> `` key to the check
159+ itself. This key should be added at the same level as ``description `` and
160+ ``trigger `` pieces of a check. In this case, the check will never run, and will
161+ output under the ``Controlled `` results key.
162+
163+ Nova also supports separate control profiles, for more fine-grained control
164+ using topfiles. You can use a separate YAML top-level key called ``control ``.
165+ Generally, you'll put this top-level key inside of a separate YAML file and
166+ only include it in the top-data for the hosts for which it is relevant.
167+
168+ For these separate control configs, the audits will always run, whether they
169+ are controlled or not. However, controlled audits which fail will be converted
170+ from ``Failure `` to ``Controlled `` in a post-processing operation.
171+
172+ The control config syntax is as follows:
173+
174+ .. code-block :: yaml
175+
176+ control :
177+ - CIS-2.1.4 : This is the reason we control the check
178+ - some_other_tag :
179+ reason : This is the reason we control the check
180+ - a_third_tag_with_no_reason
181+
182+ Note that providing a reason for the control is optional. Any of the three
183+ formats shown in the yaml list above will work.
184+
185+ Once you have your compensating control config, just target the yaml to the
186+ hosts you want to control using your topfile. In this case, all the audits will
187+ still run, but if any of the controlled checks fail, they will be removed from
188+ ``Failure `` and added to ``Controlled ``, and will be treated as a Success for
189+ the purposes of compliance percentage.
190+
191+
192+ Schedule
193+ --------
194+
195+ In order to run the audits once daily, you can use the following schedule:
196+
197+ .. code-block :: yaml
198+
199+ schedule :
200+ nova_day :
201+ function : hubble.top
202+ seconds : 86400
203+
204+ Configuration
205+ =============
206+
207+ Under the Hood
208+ ==============
209+
210+ 1. The directory/environment in which nova searches for audit modules are
211+ configurable via pillar. The defaults are shown below:
212+
213+ .. code-block :: yaml
214+
215+ hubblestack :
216+ nova :
217+ saltenv : base
218+ dir : salt://hubblestack_nova
219+
220+ 2. By default, ``hubble.audit `` will call ``hubble.load `` (which in turn calls
221+ ``hubble.sync ``) in order to ensure that it is auditing with the most up-to-date
222+ information. These operations are fairly fast, but if you want to avoid the
223+ additional overhead, you can disable these behaviors via pillar (defaults are
224+ shown, change to False to disable behaviors):
225+
226+ .. code-block :: yaml
227+
228+ hubblestack :
229+ nova :
230+ autosync : True
231+ autoload : True
77232
78233 Development
79234===========
@@ -114,14 +269,17 @@ include full documentation
114269 return True
115270
116271
117- def audit (data_list , tag , verbose = False ):
272+ def audit (data_list , tag , verbose = False , show_profile = False , debug = False ):
118273 __tags__ = []
119- for data in data_list:
274+ for profile, data in data_list:
120275 # This is where you process the dictionaries passed in by hubble.py,
121276 # searching for data pertaining to this audit module. Modules which
122277 # require no data should use yaml which is empty except for a
123278 # top-level key, and should only do work if the top-level key is
124279 # found in the data
280+
281+ # if show_profile is True, then we need to also inject the profile
282+ # in the data for each check so that it appears in verbose output
125283 pass
126284
127285 ret = {' Success' : [], ' Failure' : []}
@@ -137,17 +295,29 @@ All Nova plugins require a ``__virtual__()`` function to determine module
137295compatibility, and an ``audit() `` function to perform the actual audit
138296functionality
139297
140- The ``audit() `` function must take three arguments, ``data_list ``, ``tag `` and
141- ``verbose ``. The ``data_list `` argument is a list of dictionaries passed in by
142- ``hubble.py ``. ``hubble.py `` gets this data from loading the specified yaml for
143- the audit run. Your audit module should only run if it finds its own data in
144- this list. The ``tag `` argument is a glob expression for which tags the audit
145- function should run. It is the job of the audit module to compare the ``tag ``
146- glob with all tags supported by this module and only run the audits which
147- match. The ``verbose `` argument defines whether additional information should
148- be returned for audits, such as description and remediation instructions.
149-
150- The return value should be a dictionary, with two keys, "Success" and
151- "Failure". The values for these keys should be a list of tags as strings, or a
152- list of dictionaries containing tags and other information for the audit (in
153- the case of ``verbose ``).
298+ The ``audit() `` function must take four arguments, ``data_list ``, ``tag ``,
299+ ``verbose ``, ``show_profile ``, and ``debug ``. The ``data_list `` argument is a
300+ list of dictionaries passed in by ``hubble.py ``. ``hubble.py `` gets this data
301+ from loading the specified yaml for the audit run. Your audit module should
302+ only run if it finds its own data in this list. The ``tag `` argument is a glob
303+ expression for which tags the audit function should run. It is the job of the
304+ audit module to compare the ``tag `` glob with all tags supported by this module
305+ and only run the audits which match. The ``verbose `` argument defines whether
306+ additional information should be returned for audits, such as description and
307+ remediation instructions. The ``show_profile `` argument tells whether the
308+ profile should be injected into the verbose data for each check. The ``debug ``
309+ argument tells whether the module should log additional debugging information
310+ at debug log level.
311+
312+ The return value should be a dictionary, with optional keys "Success",
313+ "Failure", and "Controlled". The values for these keys should be a list of
314+ one-key dictionaries in the form of ``{<tag>: <string_description>} ``, or a
315+ list of one-key dictionaries in the form of ``{<tag>: <data_dict>} `` (in the
316+ case of ``verbose ``).
317+
318+ Contribute
319+ ==========
320+
321+ If you are interested in contributing or offering feedback to this project feel
322+ free to submit an issue or a pull request. We're very open to community
323+ contribution.
0 commit comments