Thursday, March 5, 2015

Using Puppet to Ensure Compliance - Part I

Puppet is configuration management software available to you today for free (Puppet Open Source) and Puppet Enterprise (this author highly recommends PE).  For the sake of this article and others in this series we'll use Puppet Open Source.

A very common requirement for all operating systems and flavors is to set kernel parameters for IPv4 (and IPv6) by turning them off.  Below is a simple init.pp file for my class networkparams_rhel that uses augeas to update and enforce kernel parameters in RedHat's /etc/sysctl.conf as a permanent setting across system reboots.

class networkparams_rhel {

  file { '/etc/sysctl_conf':
    ensure       => 'present',
    owner        => 'root',
    group        => 'root',
    mode         => '0644',
  }

  augeas {'update_system':
    context      => '/files/etc/sysctl.conf',
    changes      => [
      'set net.ipv4.ip_forward 0',
      'set net.ipv4.conf.all.send_redirects 0',
      'set net.ipv4.conf.default.send_redirects 0',
      'set net.ipv4.conf.default.send_redirects 0',
      'set net.ipv4.conf.default.accept_source_route 0',
      'set net.ipv4.conf.all.accept_redirects 0',
      'set net.ipv4.conf.default.accept_redirects 0',
      'set net.ipv4.conf.all.secure_redirects 0',
      'set net.ipv4.conf.default.secure_redirects 0',
      'set net.ipv4.conf.all.log_martians 0',
      'set net.ipv4.conf.default.log_martians 0',
      'set net.ipv4.route.flush 1',
      'set net.ipv4.icmp_echo_ignore_broadcasts 1',
      'set net.ipv4.icmp_ignore_bogus_error_responses 1',
      'set net.ipv4.conf.all.rp_filter 1',
      'set net.ipv4.conf.default.rp_filter 1',
      'set net.ipv4.tcp_syncookies 1',
    ],
  }
}

To implement this change on the fly you would do this at the command line:

        /sbin/sysctl -w net.ipv4.conf.all.send_redirects=0
      /sbin/sysctl -w net.ipv4.conf.default.send_redirects=0
      /sbin/sysctl -w net.ipv4.conf.default.send_redirects=0
      /sbin/sysctl -w net.ipv4.conf.default.accept_source_route=0
      /sbin/sysctl -w net.ipv4.conf.all.accept_redirects=0
      /sbin/sysctl -w net.ipv4.conf.default.accept_redirects=0
      /sbin/sysctl -w net.ipv4.conf.all.secure_redirects=0
      /sbin/sysctl -w net.ipv4.conf.default.secure_redirects=0
      /sbin/sysctl -w net.ipv4.conf.all.log_martians=0
      /sbin/sysctl -w net.ipv4.conf.default.log_martians=0
      /sbin/sysctl -w net.ipv4.route.flush=1
      /sbin/sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
      /sbin/sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1
      /sbin/sysctl -w net.ipv4.conf.all.rp_filter=1
      /sbin/sysctl -w net.ipv4.conf.default.rp_filter=1
      /sbin/sysctl -w net.ipv4.tcp_syncookies=1

However, you want these parameters to be permanent across all system reboots.  Puppet does this very efficiently.  This is one of those classes that you can implement today and forget about these showing up in a future vulnerability scan.  What I like to call a 'fire and forget' class.   Let's break down the manifest for this class.

First, name your class.

class <class_name> {

}

class defines a new class.  The name is arbitrary - it could be anything.  Just don't name it with spaces between words.  <class_name> in this example is networkparams_rhel.  You must encapsulate your class with an open curly bracket { and close it with } for it to work.  Use 'puppet parser validate init.pp' to test the syntax of your Ruby code.  Or install puppet-lint and use 'puppet-lint init.pp' to validate your code.  Correct serious errors and warnings appropriately. 

Next let's look at the reference type 'file' to ensure the file is present, lives in the appropriate directory and has ownerships and permissions set from the factory. 

This reference type lives within the {curly backets} used for the class. 

class networkparams_rhel {

  file { '/etc/sysctl_conf':
    ensure       => 'present',
    owner        => 'root',
    group        => 'root',
    mode         => '0644',

  }
}


File reference types have many options you can find here

Ensure will make sure the file is present at all times.  Owner will be root and also the group. Mode - aka permissions will be -rw-r--r--

Use { curly brackets } to encapsulate file options.  If you are missing a ' single quote ' or , comma your validation will let you know.  Ensure all your ruby code is validated before running on a client to avoid failures. 


Augeas is a separate package dependency of puppet-noarch that I would highly recommend you install when you install puppet agent.  Below you will fine the augeas reference type. 

  augeas {'update_system':
    context       => '/files/etc/sysctl.conf',
    changes      => [
      'set net.ipv4.ip_forward 0',
      'set net.ipv4.conf.all.send_redirects 0',
      'set net.ipv4.conf.default.send_redirects 0',
      'set net.ipv4.conf.default.send_redirects 0',
      'set net.ipv4.conf.default.accept_source_route 0',
      'set net.ipv4.conf.all.accept_redirects 0',
      'set net.ipv4.conf.default.accept_redirects 0',
      'set net.ipv4.conf.all.secure_redirects 0',
      'set net.ipv4.conf.default.secure_redirects 0',
      'set net.ipv4.conf.all.log_martians 0',
      'set net.ipv4.conf.default.log_martians 0',
      'set net.ipv4.route.flush 1',
      'set net.ipv4.icmp_echo_ignore_broadcasts 1',
      'set net.ipv4.icmp_ignore_bogus_error_responses 1',
      'set net.ipv4.conf.all.rp_filter 1',
      'set net.ipv4.conf.default.rp_filter 1',
      'set net.ipv4.tcp_syncookies 1',
    ],

  }

'update_system' is simply the name of the action augeas will take.  It can be any name just as long as you surround it in single quotes and follow it with a semi-colon. 

context is the full path to the file to update.  Prefix the full path with '/files/ and end it with a single quote' and comma.

changes in this case will be a Ruby array since we have so many parameters to change. 
    set is the keyword that is followed by the parameter to change.
    net.ipv4.<parameter> is the kernel parameter to change. This item is unique.
    0 or 1 is the off or on option that follows the parameter.  Notice how there is NO equal = sign here. Because this is Ruby array it has parts to it.  Three parts.  The set command to ensure something happens. The parameter name itself and the on or off option to set.  Every set command is encapsulated in ' single quotes ' followed by a comma ,. [ square brackets ] encapsulate the Ruby array items.  Don't forget the comma after the closing square bracket ], or it will error.  Augeas uses { curly brackets } to encapsulates its options.

By default any Operating System is very insecure out of the box.  Puppet is the tool that can be a game changer for you and your servers.  When configured properly Puppet will always ensure configurations are set exactly as you wish.  If someone, or something changes a system file configuration Puppet will ensure the setting gets set back to the configuration you set within the manifest. When security operations runs vulnerability scans you can rest assured your servers will pass because Puppet is making sure configurations stay consistent.

In Part 2 we'll take a look at how Puppet on Solaris works for similar kernel settings.





No comments:

Post a Comment