Tools for Troubleshooting and Working with SELinux

Due to my determination to keep SELinux in “enforcing” mode, I tend to run into issues that require troubleshooting the security system. While I can remember getenforce or setenforce, I tend to forget some of the other available tools.

How Apache Processes Access Requests


As you may have read in some of my previous posts, I’ve been changing the authentication datastore for many of my web-based apps to Kerberos based authentication. However, I recently needed to have certain hosts on my networks run automated scripts against some of these web apps without authentication. I found the “Satisfy” directive to allow this behavior. Setting this to “Any” allows the scripts to do their work without having to authenticate. If for no one else but myself, below are my notes.


<Directory /var/www/html>

    # 1. authentication datastore 
    AuthName "Kerberos"
    AuthType Kerberos
      # use a distinct service keytab for Apache
    Krb5Keytab /etc/krb5-HTTP.keytab
    KrbAuthRealm <DOMAIN.TLD>
      # require use of a TGT, not a password prompt from the web app
    KrbMethodK5Passwd off
      # don't allow the server to save creds, unless needed
    KrbSaveCredentials off
      # let's be explicit as to which principal we want to use
    KrbServiceName HTTP/<host.domain.tld>

    # 2. authentication requirements
    Require group app_<service>

    # 3. source host requirements
    Order allow,deny
    Allow from <hostname.domain.tld>

    # 4. which requirements (auth or host) need to be satisfied
    Satisfy Any


How This Works

  1. In the first section, we’re just setting up the authentication datastore. Nothing new here.
  2. In the second section, we establish an authentication requirement.
    • In LDAP, I create a new group for each web app. Users who need access to that web app are added to the appropriate group in LDAP. Again, nothing new.
  3. In the third section, I added an Order directive. Here’s how Order breaks down:
    • By specifying “allow,deny”, Apache will process any and all “Allow” statements followed by any and all “Deny” statements.
    • For anything not explicitly defined, Apache will deny access.
  4. If I were to have ended the Directory with section 3, Apache would require all connections to both a) be authenticated and b) come from a specific source. This is not what I wanted and why the “Satisfy” directive comes in handy. “Satisfy” here states that either auth or source is acceptable. So, if a connection comes from the specified host, it does not also have to be authenticated. If a connection comes from any other source, it will have to be authenticated. If neither of these requirements are satisfied, then access is denied.


Cannot Add Partition to OS X Disk

I recently ran into an issue which would not allow me to add a partition to a drive attached via USB. I don’t remember the history of this disk, but the buttons/widgets in OS X’s Disk Utility to add, remove, or resize a partition were grayed out. They worked, however, on other internal and external disks. Attempting the same task from the command line resulted in an error message, something along the lines of “diskutility had an error”; not much help there. A quick DuckDuckGo search turned up a StackExchange post regarding the same issue. The resolution is to erase the disk before using it.

diskutil eraseDisk JHFS+ [volumeName] [device]

Create an RSS Feed of Files in a Directory

I record some radio broadcasts for offline/on-demand listening. Coupled with an RSS feed, I can get these downloaded to my podcast player of choice. Below is an example of such a feed that I put together last night.


$files = glob("/path/to/directory/*");
$files = array_combine($files, array_map("filemtime", $files));


$files = array_keys($files);

echo '<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:itunes="" version="2.0">


    <title>Title of Your Feed</title>
    <description>Description of Your Feed</description>
    <link>A homepage for your feed</link>
    <itunes:image href="http://path/to/feed/icon.jpg"/>

foreach ( $files as $file) {
  // the filenames that I'm working with include the date in them
  // with a little slicing and dicing of the names, I can get what I need for the date variable
  // there are likely better ways of doing this, but this seemed the mostly reliable route to take in my case
  $date = preg_replace('/regex.of.junk/', '', $file);
  $date = preg_replace('/regex.of.more.junk/', '', $date);
  $date = date('D, j M Y H:i:s', strtotime($date));

  // remove the directory structure from the filename
  // again, there are likely better ways of doing this, but I was on a preg_replace roll
  $file = preg_replace('/.*Filename/', 'Filename', $file);

  echo "
      <title>Title " . $date . "</title>
      <guid>" . $file . "</guid>
      <pubDate>" . $date . "</pubDate>
      <enclosure url='http://download/link/path/" . $file . "' type='audio/mpeg'/>

  // let's stop after creating an RSS item for 10 files
  if (++$i == 9) break;

echo "



Kerberize FreePBX Admin Console

Continuing my quest to kerberize everything I can, I’ve added FreePBX web-based administration to the list. I hadn’t really looked into kerberizing FreePBX because I had just assumed it would involve source code patching and endless debugging to get it working. Turns out that support for HTTP auth is baked in! /var/www/html/admin/libraries/gui_auth.php contains a case statement which looks for a setting to define the authentication source as either “database” or “webserver”. I headed over to /etc/amportal.conf and made the change to “AUTHTYPE”, restarted amportal, but no dice. I opened /etc/amportal.conf again only to see my setting overwritten; the settings must be in the mysql database used by FreePBX. The following will let you see the current value, along with a useful description…

SELECT * FROM asterisk.freepbx_settings WHERE keyword="authtype";

Authentication type to use for web admin. If type set to “database”, the primary AMP admin credentials will be the AMPDBUSER/AMPDBPASS above. When using database you can create users that are restricted to only certain module pages. When set to “none”, you should make sure you have provided security at the Apache level. When set to “webserver”, FreePBX will expect authentication to happen at the Apache level, but will take the user credentials and apply any restrictions as if it were in database mode.

For my needs, I selected “none”…

UPDATE asterisk.freepbx_settings SET value="none" WHERE keyword="authtype";

I set my /var/www/html/admin/.htaccess file to allow my domainadmins and admins_phone LDAP groups to be required for access. I put a freshly baked keytab in place, verified my LDAP lookups were working and, voila, it worked! Hope this helps someone else.

Lighttpd and Kerberos Support

My home NAS has a web interface powered by Lighttpd. I set out to kerberize this service and started with a quick DuckDuckGo search thinking that should get me started. Alas, I was let down. There were a few blog posts regarding auth.backend and htpasswd. Interestingly enough, none of the top hits referenced Lighttpd’s website. I loaded up and searched through their docs. The ConfigurationOptions wiki page led me to the Mod_Auth docs. Neither of these mentioned Kerberos or GSSAPI. I searched the forum which led to the bug tracker for this issue. Looks as though this patch has been approved, but is unofficially targeted for a 1.5 release. Unfortunately I’m running a 1.4 release. Also, there look to be no final builds of v1.5. Is this project stalled? I’m not too worried as I’m looking to replace my NAS at some point with newer/different software. I guess I’ll have one more criteria when searching for a replacement.

Daily KB Articles

Just a little script I threw together to download a random KB article from Microsoft; set cron to run this daily.


$file = false;

// keep generating random article IDs until we hit a valid one
while($file == false):

  // create an array with random numbers
  for ($i=0; $i < 6; $i++)
    $random = (rand()%9);
    $array[$i] = $random;

  // let our array be used for the MS KB article ID
  $article_id = $array[0] . $array[1] . $array[2] . $array[3] . $array[4] . $array[5];
  $url = '' . $article_id;
  $file = @fopen($url,'r');

  // be a good netizen


// once the above loop exits with a valid URL, save the article to PDF
exec ('/usr/local/bin/wkhtmltopdf -q ' . $url . ' /path/to/dir/' . $article_id . '.pdf');


Technology Todo List

I keep hearing or reading about fascinating technologies but never have them, or have them often enough in my face that I sit down and fully iron them out in my head. I’ve listed them out below. I’ve dabbled a bit with a few of them (PHP, Python, Powershell, Puppet, Ansible), but the others will be completely or mostly new to me. Having a list of them to reference will hopefully help me chart a course, and potentially serve as a starting point for some notes as I dig into them. The list is already way more than I have time for, but I have to start somewhere. Hopefully it won’t get too out of control!

Configuration Management

Distributed Computing

Distributed File Systems



Using Kerberos Authentication with Tiny Tiny RSS


Now that I’ve started rolling out Kerberized services across my network, I suddenly (or not so suddenly) want everything to be Kerberized; and not just my network services - my car, my house, Netflix - everything! Kerberizing everything is more work than I’d like to tackle so I took on Tiny Tiny RSS instead. There was one unique thing about kerberizing TT-RSS when contrasted to the other web apps on my network: I already had a unique local account in TT-RSS that I wanted to continue to make use of its preferences, subscribed feeds, published and starred articles, article history, etc.

TT-RSS Config

TT-RSS has included an “auth_remote” plugin for awhile now. Its intent is to allow Apache Basic authentication - exactly what I needed. In order to make use of auth_remote, I had to make a couple of changes to the TT-RSS config.php file:

define('ALLOW_REMOTE_USER_AUTH', true); define('AUTH_AUTO_CREATE', true); define('AUTH_AUTO_LOGIN', true); define('PLUGINS', 'auth_internal, auth_remote');


Once I got logged in to TT-RSS via my TGT, I was presented with a fresh user account. I knew the back-end for TT-RSS was MySQL so I turned my attention there to get my old profile back. First, display your users. You should see an admin account, any other local accounts, and finally your SSO account:

select * from ttrss.ttrss_users;

| 1 | admin | MODE2... | 2 | another_local_user | MODE2... | 3 | username@DOMAIN.TLD | MODE2...

What I did was simply switch the “login” username:

update ttrss.ttrss_users set login='username@DOMAIN.TLD' where id='1'; update ttrss.ttrss_users set login='admin' where id='3';

My ttrss_users table now looked like this:

| 1 | username@DOMAIN.TLD | MODE2... | 2 | another_local_user | MODE2... | 3 | admin | MODE2...

Your admin password is borked an will need to be reset but you should now be able to log in to TT-RSS with your TGT and still have your old profile.

Monitoring Failed Backup2Go Log In Attempts


My company currently uses a workstation backup product called Backup2Go from Archiware, the makers of PresSTORE. Backup2Go give you an overview or dashboard of the status of your workstations’ backups; a nice little green dot for recent successful backups and a red dot for failed backups or backups which haven’t run in awhile. While this is nice, the dashboard doesn’t do a great job indicating to you the reason why a backup failed, of which there could be many. In most cases, a backup failed because a backup started just before the user packs up his/her laptop for the day which, of course, interrupts the backup; this is fine and expected. However, when users change their network password, they often neglect to update their password in their Backup2Go client (one’s network creds are used to initiate backups). When the creds in Backup2Go don’t match the user’s network creds, the backup can’t start and we get that little red dot in the admin console. Clicking on the red dot will give you an error message, but it’s usually not that obvious what the error message means, so I’ve stopped even looking at the messages.


In order to catch backups that are failing because of invalid credentials, I wrote a little launchd/bash script (our backup server will be one of the last systems to migrate off of an Xserve) to email us when this happens. I decided to make the output a daily email. It wouldn’t take much more work to make it a Nagios/Icinga check but my boss is fond of email reports. The script runs every morning at 5:00 and sends the list of users who had an invalid log in during the previous day. Mod as you wish.


<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ""> <plist version="1.0"> <dict> <key>AbandonProcessGroup</key> <true/> <key>Label</key> <string>tld.domain.InvalidBackup2GoLogin</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/InvalidBackup2GoLogin</string> </array> <key>RunAtLoad</key> <false/> <key>StartCalendarInterval</key> <array> <dict> <key>Hour</key> <integer>5</integer> <key>Minute</key> <integer>0</integer> </dict> </array> </dict> </plist>


#!/usr/bin/env bash email=address@domain.tld logfile=/usr/local/aw/lexxsrv.log grep invalid.username $logfile | awk '{print $1 " " $6}' | sed 's/[..............][-conn.lexxsrv.[0-9]*]//'| sort -u -t " " -k2 | grep $(date -v -1d +"%d/%b/%Y") | sed 's/...secret..//' | mail -s "Yesterday's Invalid Backup2Go Creds" $email