<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>divisionbyzero &#187; cfengine</title>
	<atom:link href="http://divisionbyzero.net/blog/tag/cfengine/feed/" rel="self" type="application/rss+xml" />
	<link>http://divisionbyzero.net/blog</link>
	<description>question . authority</description>
	<lastBuildDate>Tue, 06 Jul 2010 16:43:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>From cfEngine to Puppet:  A retrospective</title>
		<link>http://divisionbyzero.net/blog/2009/01/18/from-cfengine-to-puppet-a-retrospective/</link>
		<comments>http://divisionbyzero.net/blog/2009/01/18/from-cfengine-to-puppet-a-retrospective/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 02:06:57 +0000</pubDate>
		<dc:creator>brad</dc:creator>
				<category><![CDATA[Article]]></category>
		<category><![CDATA[cfengine]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[puppet]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://divisionbyzero.net/blog/?p=74</guid>
		<description><![CDATA[For several years I&#8217;ve managed to bend cfEngine 2.0&#8242;s architecture to my will.  Being an experienced Perl programmer, I was able to abuse the configuration language snytax in order to accomplish a number of strange things including Copy Back and automated management of OSSEC-HIDS.  However, there comes a point when the managing the cfengine configs [...]]]></description>
			<content:encoded><![CDATA[<p>For several years I&#8217;ve managed to bend <a href="http://www.cfengine.org/" target="_blank">cfEngine</a> 2.0&#8242;s architecture to my will.  Being an experienced Perl programmer, I was able to abuse the configuration language snytax in order to accomplish a number of strange things including <a href="http://divisionbyzero.net/blog/2007/05/03/copy-back-with-cfengine/" target="_blank">Copy Back</a> and <a href="http://www.ossec.net/wiki/index.php/Integration_%26_Deployment_with_cfengine">automated management of</a><a href="http://www.ossec.net/" target="_blank"> OSSEC-HIDS</a>.  However, there comes a point when the managing the cfengine configs becomes a burdensome and incredibly unmanageable.   I mean, sure, I know what they do.  How will any of my co-workers understand them?</p>
<p>After several colleagues recommending <a href="http://puppet.reductivelabs.com">Puppet</a>, I hesitantly began the slow, brain fscking process of:</p>
<ol>
<li>Understanding exactly what I had accomplished with cfEngine.</li>
<li>Understanding Ruby (ugh, I&#8217;m so thankful for Perl)</li>
<li>Understanding how to express my cfengine feelings in a way Puppet will understand without hurting it&#8217;s feelings</li>
<li>&#8230;</li>
<li>Profit.</li>
</ol>
<p><span id="more-74"></span>cfEngine makes some things incredibly easy to manage.  Nearly every command allows you to &#8220;define&#8221; new classes based on various conditions.  This allows to modify a configuration file, and then tell the daemon associated with that config file to restart.  However, when I needed to do something highly specialized, I had to create a shell script, copy the shell script to the server and then run the shell script.  Passing data back to do something was possible, though it seemed a bit hacky.  It separated the customized actions being performed from the dependent actions in the cfEngine configs.  If I had to go back later and make changes, I had to look at both the .cf file and the custom shell script in a completely different directory.</p>
<p>With Puppet, these things can be done relatively simply inside the same class file.  Also, Puppet can be extended simply through the use of defines (think macros) or complexly through the use of modules.  Additionally, Puppet supports templating, classes, inheritance, and explicit order.  Where with cfengine I&#8217;d have to do something like this:</p>
<pre style="padding-left: 30px; ">copy:
  s_snmpd.dc_has_snmp::
     $(distribute)/snmpd.conf	dest=/etc/snmp/snmpd.conf mode=644</pre>
<pre style="padding-left: 30px; ">				server=$(policyhost)
				type=sum
				define=dc_restart_snmpd</pre>
<pre style="padding-left: 30px; ">shellcommands:
   s_snmpd.dc_restart_snmpd::
	"/sbin/service snmpd restart"</pre>
<div>Utilizing the intermediary &#8220;dc_restart_snmpd&#8221; class.   With Puppet I can explicitly define the relationship with the config file and service:</div>
<pre>
<div style="padding-left: 30px; ">class ssh {</div>
<div style="padding-left: 30px; ">    package {</div>
<div style="padding-left: 30px; ">        [ "openssh-clients", "openssh-server" ]:</div>
<div style="padding-left: 30px; ">        ensure =&gt; latest</div>
<div style="padding-left: 30px; ">    }</div>
<div style="padding-left: 30px; ">    file { "/etc/ssh/sshd_config":
        mode  =&gt; 0600,
        owner =&gt; root,
        group =&gt; root,
        mode =&gt; 644,
        require =&gt; Package["openssh-server"],
        content =&gt; template("sshd_config.erb")
    }</div>
<div style="padding-left: 30px; ">    service { sshd:
        subscribe =&gt; File["/etc/ssh/sshd_config"],
        ensure    =&gt; running,
        enable    =&gt; true
    }
}</div>

 </pre>
<p>With this syntax it&#8217;s easy to read that the file /etc/ssh/sshd_config is dependent on the openssh-server package and that the sshd service is dependent on that file.  Puppet also feels more &#8220;cross-platform&#8221; as the &#8220;service&#8221; directive allows me to abstractly describe the service without having to hard code a call to /sbin/service.</p>
<p>Puppet is not without it&#8217;s drawbacks.  The first of which is that it is Ruby.  If you&#8217;re not using Ruby on your systems, this means more package installations on those servers.  If you&#8217;ve been programming in another language, like Perl or Python, it&#8217;s another language you have to fight with.  The memory usage is much higher than I expected.  On some virtual servers, this may be a huge drawback. Consider:</p>
<div id="attachment_85" class="wp-caption alignnone" style="width: 312px"><img class="size-full wp-image-85 " title="puppetmasterd" src="http://divisionbyzero.net/blog/wp-content/uploads/2009/01/puppetmasterd.png" alt="puppetmasterd" width="302" height="209" /><p class="wp-caption-text">Memory usage for puppetmasterd</p></div>
<p>Not too bad, but this is shocking:</p>
<div id="attachment_84" class="wp-caption alignnone" style="width: 312px"><img class="size-full wp-image-84 " title="puppetd" src="http://divisionbyzero.net/blog/wp-content/uploads/2009/01/puppetd.png" alt="Memory Usage at 300 MB prior to restart" width="302" height="209" /><p class="wp-caption-text">Memory Usage at ~250 MB prior to restart</p></div>
<p>Compare this to cfegine:</p>
<p> </p>
<div id="attachment_82" class="wp-caption alignnone" style="width: 311px"><img class="size-full wp-image-82 " title="cfservd" src="http://divisionbyzero.net/blog/wp-content/uploads/2009/01/cfservd.png" alt="Memory Usage for cfservd, Yes, Memory Leak." width="301" height="208" /><p class="wp-caption-text">Memory Usage for cfservd, Yes, Memory Leak.</p></div>
<p>and:</p>
<div id="attachment_81" class="wp-caption alignnone" style="width: 312px"><img class="size-full wp-image-81 " title="cfexed" src="http://divisionbyzero.net/blog/wp-content/uploads/2009/01/cfexed.png" alt="Memory Usage for cfexecd" width="302" height="210" /><p class="wp-caption-text">Memory Usage for cfexecd</p></div>
<p>Hell, even a long running Perl program using POE and Net::Pcap to decode all packets on our uplink at work (which bursts to ~75mb/sec) isn&#8217;t using that much memory:</p>
<div id="attachment_83" class="wp-caption alignnone" style="width: 313px"><img class="size-full wp-image-83 " title="perl-poe" src="http://divisionbyzero.net/blog/wp-content/uploads/2009/01/perl-poe.png" alt="Memory Usage for PoCo::Pcap based Traffic Inspector" width="303" height="208" /><p class="wp-caption-text">Memory Usage for PoCo::Pcap based Traffic Inspector</p></div>
<p>Ultimately, RAM is cheap and my time is expensive.  After kludging together configuration management in cfengine for the past three years, I&#8217;ve decided to ditch it in favor of a more sane and extensible configuration with Puppet.  I&#8217;ve got a lot to learn about Puppet still, so as I learn new and more exciting things and Puppet grows, I&#8217;ll be sure to share how it&#8217;s helping.</p>
]]></content:encoded>
			<wfw:commentRss>http://divisionbyzero.net/blog/2009/01/18/from-cfengine-to-puppet-a-retrospective/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Copy Back with cfengine</title>
		<link>http://divisionbyzero.net/blog/2007/05/03/copy-back-with-cfengine/</link>
		<comments>http://divisionbyzero.net/blog/2007/05/03/copy-back-with-cfengine/#comments</comments>
		<pubDate>Thu, 03 May 2007 22:01:02 +0000</pubDate>
		<dc:creator>brad</dc:creator>
				<category><![CDATA[Article]]></category>
		<category><![CDATA[cfengine]]></category>
		<category><![CDATA[management]]></category>

		<guid isPermaLink="false">http://divisionbyzero.net/blog/2007/05/03/copy-back-with-cfengine/</guid>
		<description><![CDATA[I love cfengine. There are tons of resources out there for managing all kinds of common and uncommon system administration tasks. Rather than regurgitate all that information I wanted to share how I worked around what has been noted as a short coming of cfengine, clients copying information back to the master server. Configuring the [...]]]></description>
			<content:encoded><![CDATA[<p>I love <a href="http://www.cfengine.org/">cfengine</a>.  There are tons of resources out there for managing all kinds of common and uncommon system administration tasks.  Rather than regurgitate all that information I wanted to share how I worked around what has been noted as a short coming of cfengine, clients copying information back to the master server.</p>
<p><span id="more-32"></span></p>
<h3>Configuring the cfengine master server, with cfegine!</h3>
<p>The easiest way to do secure file transfer without passwords would be ssh + public key authentication.  This will grant us a reasonable level of security, which we can fine tune with products like <a href="http://sublimation.org/scponly/wiki/index.php/Main_Page">scponly</a>.  For now, we&#8217;ll just play around with basics.</p>
<p>The first thing to do is to setup a user on your cfengine server to accept the file transfers.  Make this user unprivileged and make sure they are allowed to login with ssh.  I restrict ssh connectivity using groups.  I have a special group for utility accounts on my servers called &#8216;localssh&#8217;.  I&#8217;m going to create a user named &#8216;util&#8217; to handle this setup.</p>
<p><code>cfmaster# adduser -n -g localssh -h /home/util util</code></p>
<p>We need passwordless authentication, so we&#8217;re using ssh-keys.  However, we don&#8217;t want to generate those keys as they will be too much work.  We also want to make sure we keep that key under lock and barrel to ensure it&#8217;s safety.  I&#8217;ll use cfengine to configure the master server, and regenerate a utility key everyday.  This will ensure limited exposure of the key on the network.</p>
<p>Here&#8217;s the master section of our cfengine copyback.cf:</p>
<pre>
groups:
  hg_cfmaster     = ( cfmaster.domain.com )

control:
  any::
    util_keydir     = ( /usr/local/cfkeys )
    util_privkey   = ( /usr/local/cfkeys/util.dsa )
    util_pubkey   = ( /usr/local/cfkeys/util.dsa.pub )
    util_updir       = ( /home/util/cfin )
    actionsequence = ( directories tidy shellcommands )

directories:
  any::
    $(util_keydir)        mode=700 owner=root group=root fix=all

  hg_cfmaster::
    /home/util              mode=700 owner=util group=localssh fix=all
    $(util_updir)           mode=700 owner=util group=localssh fix=all

tidy:
  hg_cfmaster::
     $(util_keydir)   pattern=util.dsa age=1 r=0 define=dc_util_genkey

shellcommands:
  dc_util_genkey::
     "/usr/bin/ssh-keygen -t dsa -b 1024 -N '' -C 'util@domain.com' -f $(util_privkey)"

copy:
  hg_cfmaster::
    $(util_pubkey)      dest=/home/util/.ssh/authorized_keys mode=600 owner=util group=localssh type=sum</pre>
<p>What have we done!?@?!@?</p>
<p>Well, the control and groups sections setup our variables.  The &#8216;directories&#8217; section creates the directories and makes sure the permissions are nice and tight.  This ensures that cfengine keeps it that way.</p>
<p>The neat trick is my use of &#8220;dynamic classes&#8221; to take care of key regeneration.  The tidy section looks in the $(util_keydir) for anything matching &#8220;util.dsa&#8221; and removes it if it&#8217;s older than 1 day old.  The &#8220;define&#8221; section defines a dynamic class for the tidy statement if and only if files were deleted.</p>
<p>Then in shellcommands, if our dynamic class &#8220;dc_util_genkey&#8221; is active, we issue the ssh-keygen command to create our new key.</p>
<p>Last, the copy section moves the generated public_key into the ~/.ssh/authorized_keys file for our util user.  This enables the key for logging in without a password.  We can get fancier, but like I said, for now, its simple.</p>
<h3>Distributing the private key to the clients</h3>
<p>The cfengine clients are going to need the private key to be able to authenticate to our cfmaster server.  This is a quick addition in the aforementioned &#8216;copy&#8217; block so it looks like this:</p>
<pre>
copy:
  hg_cfmaster::
    $(util_pubkey)      dest=/home/util/.ssh/authorized_keys mode=600 owner=util group=localssh type=sum

  !hg_cfmaster::
     $(util_privkey)     dest=$(util_keydir) mode=0600 owner=root group=root type=sum server=$(policyhost)</pre>
<p>That&#8217;s it.  Now all the clients will decide if they need the key based on the checksum and replace it as a newer copy becomes available.  So, now we have an account that we can use to send files back to our cfengine master server.</p>
<h3>Sending a file to our cfengine master server</h3>
<p>What do we do now?  Well, I used this technique to issue a certificate request to my cfengine master server for a security tool called <a href="http://www.ossec.net">OSSEC-HIDS</a>.  This meant cfengine could manage the configurations and keys from my clients, making deployment completely automated.  Here&#8217;s an example using the key to scp a file back:</p>
<pre>
shellcommands:
  !hg_cfmaster::
    "/usr/bin/scp -i $(util_privkey) /tmp/somefilewithinformation.txt util@$(policyhost):~/$(host).txt"</pre>
<p>There ya go!  I&#8217;ll be putting up a page on the <a href="http://www.ossec.net/wiki/index.php/OSSEC">OSSEC-HIDS Wiki</a> on how I used this technique to manage all my clients configurations relatively soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://divisionbyzero.net/blog/2007/05/03/copy-back-with-cfengine/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
