Automated compliance with Chef InSpec


Running InSpec Centrally

A central InSpec instance that can access target systems over SSH is useful. Unfortunately, the framework does not offer an inventory function for batch mode across multiple hosts. By running InSpec from a central location, you can easily automate and monitor it: If a check on a particular system outputs a compliance warning, it can be detected automatically by a check for the respective monitoring system. If someone tampers with systems and leaves them in a state that no longer meets compliance requirements, you'll quickly notice, and you can respond quickly.

Creating Resources

The list of compliance resources provided by InSpec is long. You should find the right template for most applications. One exception could be a program developed in-house that does not exist outside of your company. In such cases, you can add your own resources to InSpec. An example, such as an application that stores its metadata in a MySQL database in an unknown, proprietary table structure, clearly illustrates this option. You can rule out a resource being provided by InSpec for the application to check the configuration for certain parameters. If you still want to use checks, your only way out is the laborious process of creating your own.

Because the framework is based on the Ruby programming language, resources in InSpec are also standard classes in Ruby. Therefore, you need to be well versed in the programming language before you start to extend InSpec. The MySQL2 library [2] by Brian Lopez is included in the Ruby repository and makes it possible to establish MySQL connections and then read from MySQL databases. With this module and the usual functions in Ruby for reading and comparing strings, a check_database resource can be written for InSpec. Depending on the desired complexity, this resource can check whether certain keywords are present and what their values are. The template you write must use Inspec.resource(1) as its type.

For the sake of completeness, I should mentioned that InSpec comes with its own mysql_connection resource, with which it can establish a MySQL connection and which was designed for applications like this. The possibilities for building your own resource (Figure 2) or using existing ones (Figure 3) are manifold. As soon as the resource is ready, it needs to be stored in the libraries folder in the respective profile; then, it can be used in profiles in the usual way.

Figure 2: If you have to deal with special local circumstances for which InSpec does not provide ready-made controls, you need to add the required resources yourself – assuming you are confident with Ruby.
Figure 3: Several preconfigured examples of controls for compliance of Linux systems can be found online, like the one shown here for popular package managers.

Linking Profiles

In everyday life you might work with different classes of servers within a large environment – for example, a cloud based on OpenStack, which usually has at least controller nodes, compute nodes, and servers for distributed object storage with Ceph. These devices each have their own compliance requirements and require individual testing. At the same time, you need a number of basic tests that you have to run on all systems. One option would be to include the respective resource definitions of the profiles in each role individually. However, this would have the distinct disadvantage that code for the same task would be out there several times, and you would have to maintain it in several places.

To put a stop to this mess, InSpec allows you to connect profiles in series and make them dependent on each other to ensure a workflow with one profile per class, which loads a certain number of other common profiles but also uses profiles specific to itself. The keyword depends used for this purpose supports a multitude of possible sources of profiles to be included. The easiest example is probably path, which references a local directory:

- name: basics-profile
  path: /home/inspec/profiles/basics

Alternatively, depends can load profiles directly from Git, retrieve them as tarballs from the Internet, or fetch them from a connected Chef Compliance Server. However, the depends directive is not sufficient to ensure that the controls are executed. The control directive in profile 1 has to have an include_controls statement for the control directives from role 2 that are to be called there. If a remote role comprises several control directives, these must be added individually to the include role.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus