<?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>techslaves.org &#187; code</title>
	<atom:link href="http://techslaves.org/tag/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://techslaves.org</link>
	<description>Owned (and fascinated) by technology!</description>
	<lastBuildDate>Thu, 23 Feb 2012 04:55:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>wxPython is Kicking my Ass!</title>
		<link>http://techslaves.org/2010/10/14/wxpython-is-kicking-my-ass/</link>
		<comments>http://techslaves.org/2010/10/14/wxpython-is-kicking-my-ass/#comments</comments>
		<pubDate>Thu, 14 Oct 2010 21:53:14 +0000</pubDate>
		<dc:creator>rthomson</dc:creator>
				<category><![CDATA[Updates]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[wxPython]]></category>
		<category><![CDATA[wxWidgets]]></category>

		<guid isPermaLink="false">http://techslaves.org/?p=95</guid>
		<description><![CDATA[Let me preface by saying that I&#8217;m not a programmer nor software developer nor anything of the sorts. I&#8217;m a sysadmin with scripting skills to solve automation problems, for the most part. I took all the C++ classes in High School but I never pursued software development as a serious academic interest or career. I [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>Let me preface by saying that I&#8217;m not a programmer nor software developer nor anything of the sorts. I&#8217;m a sysadmin with scripting skills to solve automation problems, for the most part. I took all the C++ classes in High School but I never pursued software development as a serious academic interest or career. I know &#8220;about&#8221; software development and it&#8217;s practices but I don&#8217;t feel that I have any particularly interesting skills in the field.</p>
<p>Now that I want to write a site-specific GUI-based LDAP management tool as referenced in a <a href="/2010/10/05/ldap-user-management-tools-and-user-private-groups/">previous post</a>, I&#8217;m jumping back into software development a little bit. I&#8217;ve decided to use wxPython for a few reasons. We already use it within our group, we have in-house expertise in the form of an actual developer and the GUI-builder tools seem to work best with wxPython (wxGlade was producing bad wxPerl code, go figure).</p>
<p>Let me also say that I&#8217;ve never been a big python guy. I&#8217;m really a perl kind of dude, so this learning a new object oriented API while learning python at the same time is a challenge&#8230; but I&#8217;m making progress! Basically, wxPython seriously kicked my ass for about 3 days but now I&#8217;m gaining speed and things are moving faster than I expected. Python and wxPython are starting to make more sense and behave.</p>
<p>So far I have a frame with menubar, statusbar and a three-tabbed notebook with a grid on each tab of the notebook. The program is able to connect to an LDAP server (with TLS) and query the directory for all the users, groups and autofs information and then display that information in the grid&#8230; and that&#8217;s about it so far. I need to build in new user, group and autofs functionality as well as basic editing of existing entries (in place editing with wx.Grid looks really nice but I haven&#8217;t tried it yet!).</p>
<p>Although my ass has been kicked for the last few days, I&#8217;m actually feeling pretty optimistic about it now.</p>
<p>Hopefully I can share the kludge code at some point, though it will never be easily transportable to different environments since I&#8217;m not building this to be the end-all-be-all LDAP user/group/autofs management tool, just one tailored for our environment.</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://techslaves.org/2010/10/14/wxpython-is-kicking-my-ass/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cfengine 3 Snippets Part 1: DenyHosts</title>
		<link>http://techslaves.org/2010/05/18/cfengine-3-snippets-part-1-denyhosts/</link>
		<comments>http://techslaves.org/2010/05/18/cfengine-3-snippets-part-1-denyhosts/#comments</comments>
		<pubDate>Tue, 18 May 2010 22:02:09 +0000</pubDate>
		<dc:creator>rthomson</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[cfengine]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[denyhosts]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://techslaves.org/?p=63</guid>
		<description><![CDATA[I&#8217;ve recently begun looking into configuration management with cfengine 3. I&#8217;ve ignored this growing sub-field of system administration for too long and I just can&#8217;t ignore it anymore. After spending quite some time researching the philosophies, methods and different tools out there, I settled on starting out with cfengine 3. There&#8217;s no special reason that [...]
Related posts:<ol>
<li><a href='http://techslaves.org/2010/10/02/cfengine-3-snippets-part-2-sudo/' rel='bookmark' title='Cfengine 3 Snippets Part 2: sudo'>Cfengine 3 Snippets Part 2: sudo</a></li>
<li><a href='http://techslaves.org/2010/05/07/rhelcentos-nfs-and-firewalls/' rel='bookmark' title='RHEL/CentOS, NFS and Firewalls'>RHEL/CentOS, NFS and Firewalls</a></li>
<li><a href='http://techslaves.org/2010/03/29/nanorcs/' rel='bookmark' title='Nanorcs: Ultrasimplistic Configuration File Revision Control'>Nanorcs: Ultrasimplistic Configuration File Revision Control</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently begun looking into configuration management with <a href="http://cfengine.org">cfengine 3</a>. I&#8217;ve ignored this growing sub-field of system administration for too long and I just can&#8217;t ignore it anymore. After spending quite some time researching the philosophies, methods and different tools out there, I settled on starting out with cfengine 3. There&#8217;s no special reason that I chose cfengine instead of puppet, bcfg2, chef or AutomateIT. I haven&#8217;t used any of these tools and thus I cannot pass judgement on them or their methods. All these projects seem to have intelligent and highly motivated people behind them. I simply gravitated towards cfengine because of its strong academic background and the fact that version 3 now represents the most recent and modern research in the field by Mark Burgess et. al.</p>
<p>As part of my learning experience with cfengine, I&#8217;ve decided to start posting some of the code that I&#8217;ve begun developing in the hopes that by writing about it, I can learn better, faster and maybe even receive some helpful comments from readers along the way. Beware, I&#8217;m a cfengine newbie and so what I post here should NOT be copy and pasted into your environment unless you&#8217;re ok with the potential of wildly breaking things!</p>
<p>The first snippet of code I want to discuss is related to managing our <a href="http://denyhosts.sourceforge.net/">DenyHosts</a> configuration. As part of our &#8220;security policy&#8221;, I would like to ensure that every RedHat/CentOS system is running a properly configured DenyHosts instance. Here is what I&#8217;ve come up with so far.</p>
<p><span id="more-63"></span></p>
<pre>################################################################################
#
# FILE: denyhosts.cf
# DESC: Install, update, configure and ensure DenyHosts is running
# DATE: May 2010
#
#################################################################################

bundle agent denyhosts
{

packages:

  "denyhosts" -&gt; "Security policy"
    comment               =&gt; "Ensure denyhosts is installed once a week",
    package_policy        =&gt; "add",
    package_method        =&gt; yum,
    package_architectures =&gt; { "noarch" },
    action                =&gt; if_elapsed("10080");

  Night::

  "denyhosts" -&gt; "Security policy"
    comment               =&gt; "Check for update to denyhosts every 24 hours (and only at night)",
    package_policy        =&gt; "update",
    package_method        =&gt; yum,
    package_architectures =&gt; { "noarch" },
    action                =&gt; if_elapsed("1440");

files:

  "/etc/denyhosts.conf" -&gt; "Security policy"
    comment   =&gt; "Standard base DenyHosts configuration",
    copy_from =&gt; mycopy("$(g.confdir)/denyhosts/denyhosts.conf", "$(g.cfserver)"),
    classes   =&gt; cdefine("denyhosts_restart", "denyhosts_conf_copy_failed"),
    perms     =&gt; mo("400", "root"),
    action    =&gt; if_elapsed("1440");

processes:

  "python /usr/bin/denyhosts.py" -&gt; "Security policy"
    comment       =&gt; "Define denyhosts_restart class if denyhost is NOT running",
    restart_class =&gt; canonify("denyhosts_restart");

commands:

  "/sbin/service denyhosts restart" -&gt; "Security policy"
     comment    =&gt; "Restarting DenyHosts after configuration change or death",
     ifvarclass =&gt; canonify("denyhosts_restart");

}</pre>
<p>If you&#8217;re familiar with cfengine at all, you&#8217;ll quickly realize this is not a complete configuration. I am relying on the cfengine standard library for several body definitions as well as custom site variables defined in the common bundle named &#8220;g&#8221; (not shown). And of course, there are no control bodies, bundlesequence or many other things that make up a complete cfengine configuration, hence &#8220;snippet&#8221;.</p>
<p>Let&#8217;s ignore what&#8217;s lacking for now and focus on the meat of the promises.</p>
<h3>Packages</h3>
<p>The first part of the denyhosts bundle is dealing with packages. I&#8217;m making two promises regarding the &#8220;denyhosts&#8221; package. The first promise is that the package has been added to the system via yum and the second is that the package is up to date via yum. I&#8217;m not entirely clear on how to best manage promises like this yet so perhaps I&#8217;m missing some cute shorthand for both adding and keeping packages up to date. For now, I&#8217;ll stick with two separate promises.</p>
<p>You&#8217;ll also notice that I&#8217;m only checking to see if the package is installed once a week (via action =&gt; if_elapsed) and only checking to see if the package is up to date once every 24 hours (if_elapsed, again). The update promise is also subject to the Night class to ensure that package updates only occur at night and not during the work day. This is just a matter of preference. I&#8217;d prefer if updates occur at night, you may not.</p>
<p>Since I&#8217;m using a &#8220;smart&#8221; package manager to ensure that denyhosts is installed, I can count on having yum resolve any dependencies (such as python) for me automatically. I would loath to describe every dependency for every package I want control over by hand.</p>
<h3>Files</h3>
<p>There is only one file that I&#8217;m concerned with when it comes to denyhosts and that is the denyhosts configuration file in /etc/denyhosts.conf. Instead of doing file edits on the default denyhosts.conf file provided in the denyhosts packages that I&#8217;ve promised to install, I simply copy a pre-defined configuration from my cfengine server. This file has our site&#8217;s default denyhosts configuration all ready to go. If I needed to customize the configuration on a per-host or per-host-type basis, I could copy the base file to a temporary location then perform edits on the temp file and write out the changes to the final location of the default configuration file or simply maintain several pre-configured versions of denyhosts.conf and copy the appropriate file.</p>
<p>Also of note about files is that if the file promise must be repaired (if the file must be copied because it&#8217;s changed), I&#8217;m setting a class to be defined so that DenyHosts can be restarted. More on that later.</p>
<h3>Processes</h3>
<p>In this case, I&#8217;m only checking to see if the DenyHosts python process is running or not. If DenyHosts is running, we do nothing. If DenyHosts is not running, we define a class using the same name as the class we define if we have to copy the configuration file.</p>
<h3>Commands</h3>
<p>Finally, in the commands section we tell cfengine how and when to restart DenyHosts. If the &#8220;denyhosts_restart&#8221; class is defined, we instruct cfengine to restart DenyHosts with the &#8220;/sbin/service denyhosts restart&#8221; command. The canonify and cdefine special functions in cfengine provide a very powerful way of defining some rather complex relationships.</p>
<h3>What is Missing?</h3>
<p>Well, probably <em>a lot</em> of stuff. One obvious thing is that I&#8217;m not promising that DenyHosts is set to startup at boot time using the hosts&#8217; native init system. Of course, this shouldn&#8217;t be a big deal because cfengine will start it up if it&#8217;s not running at the next cf-agent run, but perhaps it would be nice to make that promise anyways.</p>
<p>I&#8217;m also not using many (or any!) classes to limit the scope of where (to what hosts) these promises will apply. Right now, I&#8217;m just working with a test environment so it&#8217;s easy to get away with that but I&#8217;m learning that it&#8217;s good to be as explicit at possible from the start when building promises.</p>
<p><strong>UPDATE:</strong> Ah, how could I forget.. Reporting is totally missing! I knew I was setting some of those classes for a reason. In the next installment, I&#8217;ll include the most basic of reporting functionality.</p>
<p>I think that&#8217;s all for now. Please critique my amateur use of cfengine 3 in the comments, I want to hear from you!</p>
<p>Related posts:<ol>
<li><a href='http://techslaves.org/2010/10/02/cfengine-3-snippets-part-2-sudo/' rel='bookmark' title='Cfengine 3 Snippets Part 2: sudo'>Cfengine 3 Snippets Part 2: sudo</a></li>
<li><a href='http://techslaves.org/2010/05/07/rhelcentos-nfs-and-firewalls/' rel='bookmark' title='RHEL/CentOS, NFS and Firewalls'>RHEL/CentOS, NFS and Firewalls</a></li>
<li><a href='http://techslaves.org/2010/03/29/nanorcs/' rel='bookmark' title='Nanorcs: Ultrasimplistic Configuration File Revision Control'>Nanorcs: Ultrasimplistic Configuration File Revision Control</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://techslaves.org/2010/05/18/cfengine-3-snippets-part-1-denyhosts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RHEL/CentOS, NFS and Firewalls</title>
		<link>http://techslaves.org/2010/05/07/rhelcentos-nfs-and-firewalls/</link>
		<comments>http://techslaves.org/2010/05/07/rhelcentos-nfs-and-firewalls/#comments</comments>
		<pubDate>Fri, 07 May 2010 18:01:20 +0000</pubDate>
		<dc:creator>rthomson</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[vendor]]></category>

		<guid isPermaLink="false">http://techslaves.org/?p=61</guid>
		<description><![CDATA[I recently decided that it&#8217;s about time to setup consistent, explicit and tight firewall policy across our Linux (mostly RHEL/CentOS) servers. One of the initial issues I faced was NFS. NFS implementations are very well known to make use of the portmapper and dynamically assigned port for rpc.mountd and because of this dynamic assignment, firewalling [...]
Related posts:<ol>
<li><a href='http://techslaves.org/2011/05/13/browsing-automounted-nfs-with-nautilus/' rel='bookmark' title='Browsing Automounted NFS with Nautilus'>Browsing Automounted NFS with Nautilus</a></li>
<li><a href='http://techslaves.org/2010/05/18/cfengine-3-snippets-part-1-denyhosts/' rel='bookmark' title='Cfengine 3 Snippets Part 1: DenyHosts'>Cfengine 3 Snippets Part 1: DenyHosts</a></li>
<li><a href='http://techslaves.org/2010/03/30/opengear-cm4116-review/' rel='bookmark' title='OpenGear CM4116 Review'>OpenGear CM4116 Review</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I recently decided that it&#8217;s about time to setup consistent, explicit and tight firewall policy across our Linux (mostly RHEL/CentOS) servers. One of the initial issues I faced was NFS. NFS implementations are very well known to make use of the portmapper and dynamically assigned port for rpc.mountd and because of this dynamic assignment, firewalling NFS can be challenging.</p>
<p>Luckily, RedHat&#8217;s <em>/etc/sysconfig/nfs</em> configuration file read by  various &#8220;nfs&#8221;, &#8220;nfslock&#8221; and RPC services init scripts provides an easy means of locking down specific ports for all the NFS-related services so that one doesn&#8217;t have to work around the dynamic port assignment problem when it comes to firewalling.</p>
<p><span id="more-61"></span></p>
<p>In <em>/etc/sysconfig/nfs</em> there are six different options relating to port assignment:</p>
<ol>
<li>RQUOTAD_PORT</li>
<li>LOCKD_TCPPORT</li>
<li>LOCKD_UDPPORT</li>
<li>MOUNTD_PORT</li>
<li>STATD_PORT</li>
<li>STATD_OUTGOING_PORT</li>
</ol>
<p>These options do not represent all the ports that will be used by the entire NFS service but it includes the most important option for eliminating the uncertainty of rpc.mountd.</p>
<p>I&#8217;ve set the port options as follows:</p>
<ol>
<li>RQUOTAD_PORT=875</li>
<li>LOCKD_TCPPORT=4045</li>
<li>LOCKD_UDPPORT=4045</li>
<li>MOUNTD_PORT=861</li>
<li>STATD_PORT=865</li>
<li>STATD_OUTGOING_PORT=866</li>
</ol>
<p>After making the changes, restart the &#8220;nfs&#8221; and &#8220;nfslock&#8221; services and check to make sure the configured ports are now in fact in use with the &#8220;rpcinfo -p&#8221; command:</p>
<pre># rpcinfo -p
program vers proto   port  service
100000    4   tcp    111  portmapper
100000    3   tcp    111  portmapper
100000    2   tcp    111  portmapper
100000    4   udp    111  portmapper
100000    3   udp    111  portmapper
100000    2   udp    111  portmapper
100011    1   udp    875  rquotad
100011    2   udp    875  rquotad
100011    1   tcp    875  rquotad
100011    2   tcp    875  rquotad
100021    1   udp   4045  nlockmgr
100021    3   udp   4045  nlockmgr
100021    4   udp   4045  nlockmgr
100021    1   tcp   4045  nlockmgr
100021    3   tcp   4045  nlockmgr
100021    4   tcp   4045  nlockmgr
100003    2   tcp   2049  nfs
100003    3   tcp   2049  nfs
100003    4   tcp   2049  nfs
100003    2   udp   2049  nfs
100003    3   udp   2049  nfs
100003    4   udp   2049  nfs
100005    1   udp    861  mountd
100005    1   tcp    861  mountd
100005    2   udp    861  mountd
100005    2   tcp    861  mountd
100005    3   udp    861  mountd
100005    3   tcp    861  mountd
100024    1   udp    865  status
100024    1   tcp    865  status</pre>
<p>Now, the entire NFS-related firewall rules must allow the following ports from the applicable client address range(s):</p>
<ul>
<li>Incoming and Outgoing ICMP type 3</li>
<li>Incoming TCP and UDP ports 111, 861, 865, 875, 2049, 4045</li>
<li>Outgoing TCP and UDP ports 111, 861, 865, 866, 875, 2049, 4045</li>
</ul>
<p>These rules can easily be configured with your favorite firewalling software (I&#8217;m using fwbuilder to manage iptables rules). Often times firewalls will be configured to allow all outgoing connections, so if that&#8217;s the case with your firewalls, don&#8217;t worry about specific outgoing rules. I&#8217;ve been testing this configuration for two days now and all seems well.</p>
<p>Related posts:<ol>
<li><a href='http://techslaves.org/2011/05/13/browsing-automounted-nfs-with-nautilus/' rel='bookmark' title='Browsing Automounted NFS with Nautilus'>Browsing Automounted NFS with Nautilus</a></li>
<li><a href='http://techslaves.org/2010/05/18/cfengine-3-snippets-part-1-denyhosts/' rel='bookmark' title='Cfengine 3 Snippets Part 1: DenyHosts'>Cfengine 3 Snippets Part 1: DenyHosts</a></li>
<li><a href='http://techslaves.org/2010/03/30/opengear-cm4116-review/' rel='bookmark' title='OpenGear CM4116 Review'>OpenGear CM4116 Review</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://techslaves.org/2010/05/07/rhelcentos-nfs-and-firewalls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>POSIX Default ACLs, umask and Project Directories</title>
		<link>http://techslaves.org/2010/04/23/posix-default-acls-umask-and-project-directories/</link>
		<comments>http://techslaves.org/2010/04/23/posix-default-acls-umask-and-project-directories/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 22:32:42 +0000</pubDate>
		<dc:creator>rthomson</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[acl]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://techslaves.org/?p=48</guid>
		<description><![CDATA[I&#8217;ve recently come across a situation where the inherent design of POSIX ACLs has left me scratching my head for a solution to the problem of setting up a &#8220;project&#8221; or &#8220;group share&#8221; directory on Linux. The problem is as follows: We have several different projects or groups that desire a directory where any and [...]
Related posts:<ol>
<li><a href='http://techslaves.org/2010/05/18/cfengine-3-snippets-part-1-denyhosts/' rel='bookmark' title='Cfengine 3 Snippets Part 1: DenyHosts'>Cfengine 3 Snippets Part 1: DenyHosts</a></li>
<li><a href='http://techslaves.org/2011/08/24/freeipa-and-samba-3-integration/' rel='bookmark' title='FreeIPA and Samba 3 Integration'>FreeIPA and Samba 3 Integration</a></li>
<li><a href='http://techslaves.org/2010/09/01/when-using-syncrepl/' rel='bookmark' title='When using Syncrepl&#8230;'>When using Syncrepl&#8230;</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently come across a situation where the inherent design of POSIX ACLs has left me scratching my head for a solution to the problem of setting up a &#8220;project&#8221; or &#8220;group share&#8221; directory on Linux. The problem is as follows: We have several different projects or groups that desire a directory where any and every file created, copied or moved to said directory will become owned by a particular group and have group read/write permissions set automatically.</p>
<p>Most of the problem is solved through age-old UNIX techniques. For group ownership, all we need to do is setup the top-level directory to be owned by the &#8220;project&#8221; or &#8220;group share&#8221; group and setgid the directory:</p>
<pre>$ mkdir project1
$ chown .projgroup project1
$ chmod g+s project1</pre>
<p>This effectively forces every file created, moved or copied into the &#8220;project1&#8243; directory to be owned by group &#8220;projgroup&#8221;. So far, so good. The difficulties begin when we attempt to use default ACLs to enforce the permissions of any files created, moved or copied into the directory.</p>
<p>The POSIX ACL standard defines &#8220;default&#8221; ACLs which can be applied to a directory, which are in turn inherited by newly created/copied/moved child files and directories. While the default ACLs are inherited properly, the ACL mask when applied to files copied into the group share directory WITHOUT previous group write set prevents the files from being group writable!</p>
<pre>$ getfacl project1
# file: project1
# owner: root
# group: projgroup
user::rwx
group::rwx
other::r--
default:user::rw-
default:group::rw-
default:group:projgroup:rw-
default:mask::rwx
default:other::r--</pre>
<p>So far so good, right?</p>
<pre>$ ls -alh test
-rw-r--r--  1 user1 user 0 Apr 23 15:10 test
$ cp test project1
$ ls -alh project1/test
-rw-r--r--+ 1 user1 projgroup 0 Apr 23 15:10 project1/test</pre>
<p>What the&#8230; ?!?! No group write? Noooooo!</p>
<pre>$ getfacl project1
# file: project1/test
# owner: user1
# group: projgroup
user::rw-
group::rw-			#effective:r--
group:projgroup:rw-		#effective:r--
mask::r--
other::r--</pre>
<p>And so we have the great POSIX ACL mask problem, which is by design in fact. Still looking for a complete solution that doesn&#8217;t involve global trying to force a specific umask on every account&#8230; It would be nice if I could ensure that every file had group write set before it was copied into the group share directory but alas, I cannot. Telling users to manually check and change permissions is also a pain. Cron jobs to change group write recursively is also ugly. Please, someone provide me with the solution.</p>
<p>Related posts:<ol>
<li><a href='http://techslaves.org/2010/05/18/cfengine-3-snippets-part-1-denyhosts/' rel='bookmark' title='Cfengine 3 Snippets Part 1: DenyHosts'>Cfengine 3 Snippets Part 1: DenyHosts</a></li>
<li><a href='http://techslaves.org/2011/08/24/freeipa-and-samba-3-integration/' rel='bookmark' title='FreeIPA and Samba 3 Integration'>FreeIPA and Samba 3 Integration</a></li>
<li><a href='http://techslaves.org/2010/09/01/when-using-syncrepl/' rel='bookmark' title='When using Syncrepl&#8230;'>When using Syncrepl&#8230;</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://techslaves.org/2010/04/23/posix-default-acls-umask-and-project-directories/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>l2c.pl &#8211; Lines to Columns</title>
		<link>http://techslaves.org/2010/03/30/l2c-pl/</link>
		<comments>http://techslaves.org/2010/03/30/l2c-pl/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 02:23:09 +0000</pubDate>
		<dc:creator>rthomson</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://techslaves.org/?p=32</guid>
		<description><![CDATA[Here is a little perl script I wrote some time back for converting a text file&#8217;s contents from lines to columns. I&#8217;d like to present this script and then psuedo-challenge other visitors of this site to write a more efficient algorithm in the language of their choice. Unfortunately, any way (that I know of) for [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>Here is a little perl script I wrote some time back for converting a text file&#8217;s contents from lines to columns.</p>
<p>I&#8217;d like to present this script and then psuedo-challenge other visitors of this site to write a more efficient algorithm in the language of their choice. Unfortunately, any way (that I know of) for measuring the efficiency of two or more algorithms across different languages is going to be skewed due to differences in efficiency of compilers, interpreters and what not.</p>
<p><span id="more-32"></span></p>
<p>The script converts a file in the format:</p>
<p>1 2 3 4 5 6 7 8 9 10<br />
11 12 13 14 15 16 17 19 19 20</p>
<p>to:</p>
<p>1 11<br />
2 12<br />
3 13<br />
4 14<br />
5 15<br />
6 16<br />
7 17<br />
8 18<br />
9 19<br />
10 20</p>
<p>I should add that the program must be able to handle unequal number of items in each line, too.</p>
<pre>#!/usr/bin/perl
#
# l2c.pl - lines to columns
#
# http://techslaves.org/

# variables
my @lines;
my @columns;
my $iter = 0;
my $linesize = 0;

# if num of command line arguments is 2
if (($#ARGV + 1) == 2) {

  # open input file for reading
  open(INFILE, $ARGV[0]);

  # read input file into an array of arrays
  # an array of "lines" and each "line" is an array of it's "elements" (based on space or tab)
  while()  { push @lines, [ split(/\s+/, $_) ]; }

  # close input file
  close(INFILE);

  # find the longest line (so we know how many times to loop below)
  foreach $line (@lines) {
    if(@$line &gt; $linesize) { $linesize = @$line; }
  }

  # open output file
  open(OUTFILE, "&gt;$ARGV[1]");  

  # $iter = line element counter
  # loop while the line element counter is less than the longest line
  while ($iter &lt; $linesize) {
    # loop through every line in the array of lines
    foreach $line (@lines) {
      # if a line element at position $iter exists...
      if( @$line-&gt;[$iter] ) {
        # print the line element + a tab to the output file
        print OUTFILE @$line-&gt;[$iter], "\t";
      }
      # advance the line element counter
    } $iter++; print OUTFILE "\n";
  }

  # close output file
  close(OUTFILE);

# if num of command line arguments is NOT 2 print usage
} else { print("usage: $0 inputfile outputfile\n"); }</pre>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://techslaves.org/2010/03/30/l2c-pl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nanorcs: Ultrasimplistic Configuration File Revision Control</title>
		<link>http://techslaves.org/2010/03/29/nanorcs/</link>
		<comments>http://techslaves.org/2010/03/29/nanorcs/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 23:52:44 +0000</pubDate>
		<dc:creator>rthomson</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://techslaves.org/?p=28</guid>
		<description><![CDATA[I present to you nanorcs, my ultrasimplistic configuration file revision control method. It&#8217;s nothing significant but at least it&#8217;s something to post about. What is nanorcs? It&#8217;s a very simple bash script wrapper around the nano, the cute GNU version of pico and RCS, a basic but functional revision control software package. The script is [...]
Related posts:<ol>
<li><a href='http://techslaves.org/2010/08/05/time-navigator-ha-cluster-agent-configuration/' rel='bookmark' title='Time Navigator HA Cluster Agent Configuration'>Time Navigator HA Cluster Agent Configuration</a></li>
<li><a href='http://techslaves.org/2010/03/30/l2c-pl/' rel='bookmark' title='l2c.pl &#8211; Lines to Columns'>l2c.pl &#8211; Lines to Columns</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I present to you nanorcs, my ultrasimplistic configuration file revision control method. It&#8217;s nothing significant but at least it&#8217;s something to post about.</p>
<p>What is nanorcs? It&#8217;s a very simple bash script wrapper around the nano, the cute GNU version of pico and RCS, a basic but functional revision control software package. The script is used in place of a call to &#8216;nano&#8217; when editing a file and it automates the tasks related to change management of configuration files including tasks such as check in/out, and prompting the user when a discrepancy between the current file version and the RCS version exist.</p>
<h3><span id="more-28"></span>Basic Prerequisites</h3>
<p>While few prerequisites exist for nanorcs, most of them should be quite simple to satisfy on any Linux system:</p>
<div id="_mcePaste">
<ul>
<li>nano is installed</li>
<li>RCS is installed</li>
</ul>
</div>
<p>Nanorcs also makes some assumptions regarding the path to certain executables: it assumes the required executables are in your path!. I know I could have made it &#8220;cleaner&#8221; by providing a variable in which to set the paths, but this script was 99% written for me, on my systems&#8230; where the RCS and nano commands are in my path&#8230; and besides, if you&#8217;re reading this you can probably figure out how to edit it to suit you anyways! This is just an example of how this might be done, not necessarily a working solution for your systems.</p>
<h3>Functionality</h3>
<div id="_mcePaste">Nanorcs does a few &#8220;nice&#8221; things.</div>
<div id="_mcePaste">
<ul>
<li>The script checks to see if the file you are editing already exists in RCS and if not, does the initial check in before any changes are made.</li>
<li>The script will notify you if the local copy of the file you are editing is different from the latest revision in RCS. It then provides a mechanism to check in the local version to RCS so you do not clobber any changes made that may have not been commited to RCS. If you do not wish to commit the current changes, the script asks if you instead want to pull down the latest version from RCS and work with that one. Summed up, if the local version is different from RCS you have the option to clobber the local version or commit the local version to RCS.</li>
<li>After you are done editing the file with nano, you are asked if you wish to commit the changes. If you answer yes, the changes are commited and the script exits. If you do not wish to commit the edits to RCS, you are asked if you want to pull down the latest version from RCS again or if you want to leave the changes. Leaving the changes without committing them is bad form but there could be a good reason to do so (you realize after exiting the editor that you didn&#8217;t make all the changes you wanted or the changes were only slightly incorrect and it would be easier to update the current version than to pull down the last version from RCS and start over).</li>
</ul>
</div>
<h3>Using nanorcs</h3>
<p>Using nanorcs is easy, but you always have to remember the key point that it must be invoked against a file that is in your current working directory! The basic calling convention is (assing the script is in your path!):</p>
<pre>root@box:/etc/ssh
# nanorcs sshd_config</pre>
<h3>The Script</h3>
<p>And finally, the script itself:</p>
<pre>#!/bin/bash
#
# Name: 	nanorcs
# Desc: 	RCS wrapper around nano for editing config files
#

# Check if file exists in RCS
#
if [ ! -e $1,v ]; then
  echo "First time editing, checking file into RCS..."
  ci -l $1,v $1
else
  # Check if RCS version is different from local version
  rcsdiff $1,v $1 &amp;&gt; /dev/null
  if [ "$?" -eq 1 ]; then
    echo -n "File $1 is not the same as RCS version, clobber it (y/n)? "
    read clobber
    if [ "$clobber" = "y" ]; then
      co -l $1,v $1
    else
      echo -n "Commit current version to RCS (y/n)? "
      read commitfirst
      if [ "$commitfirst" = "y" ]; then
        rcs -l $1,v
        ci -l $1,v $1
      else
        echo "Nothing left to do, exiting..."
        exit
      fi
    fi
  else
    co -l $1,v $1
  fi
fi

nano $1

echo -n "Commit changes to RCS (y/n)? "
read commitfinal
if [ "$commitfinal" = "y" ]; then
  echo "Committing changes..."
  ci -u $1,v $1
else
  rcsdiff $1,v $1 &amp;&gt; /dev/null
  if [ "$?" ]; then
    echo -n "Do you want to revert to RCS version of $1 (y/n)? "
    read revert
    if [ "$revert" = "y" ]; then
      echo "Reverting to RCS version..."
      co -u $1,v $1
    else
      echo "Changes made have NOT been committed!"
    fi
  else
    echo "File unchanged from RCS version, BYE!"
  fi
fi

#
# END
#</pre>
<p>That is all. Nanorcs is my ultra-simplistic solution to the minor hassle of managing configuration file revision. For more advanced users and admins, things like cfengine and pikt are certainly light years ahead of this in every way imaginable, but for those of you who don&#8217;t necessarily need or want a configuration engine, this type of solution seems to be suitable enough.</p>
<p>Related posts:<ol>
<li><a href='http://techslaves.org/2010/08/05/time-navigator-ha-cluster-agent-configuration/' rel='bookmark' title='Time Navigator HA Cluster Agent Configuration'>Time Navigator HA Cluster Agent Configuration</a></li>
<li><a href='http://techslaves.org/2010/03/30/l2c-pl/' rel='bookmark' title='l2c.pl &#8211; Lines to Columns'>l2c.pl &#8211; Lines to Columns</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://techslaves.org/2010/03/29/nanorcs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

