Steel /stēl/ Verb: Mentally prepare (oneself) to do or face something difficult.


On $releasever and rpmdb

A few days ago a coworker inquired about an odd error: [Errno 14] HTTPS Error 404 - Not Found

The inclusion of the '%24relesever" in the URL was extremely weird, the question was how did it get there? The answer is a bit complicated.

As most folks who are reading this will probably be aware the yum.conf file can substitute certain variables listed in a repo defintion, from man yum.conf:

       Right side of every repo option can be enriched by the following  variables:

          Refers to the system’s CPU architecture e.g, aarch64, i586, i686 andx86_64.

          Refers to the base architecture of the system. For example, i686 and i586  machines  both have a base architecture of i386, and AMD64 and Intel64 machines have a base architecture of x86_64.

          Refers to the release version of operating system which DNF  derivesfrom information available in RPMDB.

But where exactly does releasever come from? It turns out the answer is this query:

rpm -q --provides $(rpm -q --whatprovides "system-release(releasever)") | grep "^system-release(releasever)"

So on a redhat 7.5 server system, system-release(releasever) is provided by the redhat-release-server package and the system-release(releasever) is set to 7Server.

After re-installing that package, RPM was again able to provide that information to YUM and the error went away since the variable had a value. It was certainly a strange error to run into...

Tagged as: , No Comments

On Password Protecting Kickstarts

Kickstarting a Red Hat Enterprise Linux (based or derivative) system is an extremely handy way to get a system off the ground quickly. Even in today's world of configuration management systems, it is  still an extremely handy tool for the initial bootstrapping.

However, one thing has bothered me for some time, the kickstarts may contain potentially sensitive information, As well, the kickstarts generally need to be available to your entire organization, or even worse the entire internet to be useful, and all of this seems to happen without any form of authentication to get to the kickstart file.

Yes it would be possible with advanced networking to mitigate this issue, as well kickstarts themselves try to mitigate this issue by, for instance, hashing the root and grub passwords.

However, if your organization is anything like mine, the left hand often doesn't even know the right hand exists, and so we must work with networking that is not that advanced. Further, outside of the hashed passwords for grub and root, there are other areas of the kickstart that can be sensitive, for instance your Red Hast Subscription Manager (RHSM) activation key, or perhaps you are doing something special in the %post section of your kickstart.

Wouldn't it be nice to at a minimum provide basic password authentication in front of your kickstart?

It turns out you can, it is just poorly documented (if at all, I couldn't find anything about this, I ended up guessing based off of an old bugzilla report).

Enabling Basic Authentication Using HTTPS with Kickstart:

Simple place your kickstart on an Apache server or equivalent, and configure Basic Authentication for the location of the kickstart.

Anaconda appears to rely in libcurl underneath and as such you can use curl's syntax for usernames and passwords from the kernel command line like so:


And that right there is really all there is to it, as long as your TLS certificate is recognized by the default trust store.

Filed under: Uncategorized No Comments

On Building a Quick TLS Server with Flask

I have the need, at the moment, to have a TLS site running from my local system, served only to my local system, for development purposes. This is needed for the OAuth flow so that I can gather the token returned, but that is another story...

I didn't want to deal with generating a CA, and server certs etc. I wanted the code to be fully portable and just work, ignoring of course the security implications of not having a 'legit' certificate.

It turns out setting up a quick TLS enabled site with Flask is ridiculously easy, this was one of those, 'thank the deity moments that someone had already thought of and implemented this particular use case'.

Anyway, on to the code:

from flask import Flask
app = Flask(__name__)

if __name__ == '__main__':, port=8443, ssl_context='adhoc')

Make sure you have pyOpenSSL installed, and that is it! Amazing really, clearly you don't need to set the port if you don't want to, it will default to 5000 if none is supplied.

The ssl_context is the interesting bit. Adhoc means that new certificates will be generated on each app start. This is not secure, since the certs are not based off of any trusted CA, but it will get the job done. You can also supply the cert, key, and CA as an SSL Context object if you need to, more info here.

To reinforce this point, this is a quick setup using the development server built into flask. DO NOT use this in production, this is for testing only. The certs themselves should be secure, however you have no CA chain, thus no trust, again this should NEVER be used in production.

Filed under: Uncategorized No Comments

On Building the Gemalto .NET PKCS 11 Module for Linux

Gemalto manufactures a number of different smart cards. However, one that seems to be rather popular is the Gemalto IDPrime .NET series of cards. Gemalto has also kindly developed an LGPL licensed PKCS 11 module for this series of cards that can be used in Linux. However, tracking the module down can be a real pain.

Gemalto's website seems to be only sporadically maintained, lots of dead links, pointers to drivers and tools that no longer exist etc. As such I had to chase this down a little, and in the spirit of helping others, and myself, out in the future, here is what is needed to be done to find, compile, and install the module.

Get the Module Source Code:

I was able to locate the module source code here. Probably the simplest way to get the source is simply to click on the 'Zip Archive' link under 'Download in other formats:' this will give you a zip file of the entire archive at its current revision.

You can also use Subversion to pull down the repository if you like:

svn checkout

Build the Module:

If you downloaded the zip file you will have a file like '' the REVISION number will change as the repository changes. Unzip the file and you should end up with a 'trunk' folder. Now cd into the modules folder.

$ unzip
$ cd trunk/SmartCardServices/src/PKCS11dotNetV2/

If you used Subversion to checkout the repository you should have a 'smartcardservices' directory, inside of which are all the branches and the trunk, we will be working against the trunk only, and only building a very small part of that,.

$ cd smartcardservices/trunk/SmartCardServices/src/PKCS11dotNetV2/

At this point you need to run for the PKCS11dotNetV2 module in order to create the configure files etc.

$ chmod 755
$ ./

Hopefully everything goes smoothly, no we run through the general configure, make, make install steps. Note that you will need to build against the system boost libraries, so you need to pass a flag to configure for that.

$ ./configure --enable-system-boost
$ make

By default the module will be installed into /usr/local/lib/ if this is a problem, you will need to adjust your configure flags to set the location, read through './configure --help' for more information.

Now we install the module:

$ make install

The module is now installed in /usr/local/lib/pkcs11/, this is the location you will need to point programs like Thunderbird and Firefox at in order to use the module.

Filed under: Uncategorized No Comments

On Cisco ASA High Availability Remote Upgrades


One of the issues with setting up the Cisco ASA in a High Availability configuration is that, though most things are replicated, installation of the AnyConnect software, ASDM, and the ASA base software itself is not replicated. For folks sitting behind the ASA this is not a problem, you can just connect to one ASA and then the other to update the software. However, if you are connecting remotely via the VPN this is simply not possible. There is a feature request open with Cisco for this ability, but since it has been open for a few years I am not holding out hope.

So how does one upgrade the software on both the primary and secondary units remotely?


There are two generally accepted solutions to this conundrum.

Upgrade and Fail Over Method:

In this method you upgrade the primary using whatever means you usually use such as ASDM or via the CLI. However, after the ASDM and ASA software is installed on the system you do not choose to activate the software, instead you fail over to the secondary, reconnect using ASDM or SSH and do the install on the secondary system. You the fail back to the primary and activate the software and reboot the systems in whatever order you please.

Upgrade via TFTP Method:

Unfortunately in my particular circumstance I simply can't fail over as the fail over is not working due to IPv6 issues. IN order to do this you are going to need a TFTP server on a network segment that is accessible to the ASAs. I won't go through setting up a TFTP server as it is a pretty simple process.

The following is all done from the CLI on the primary:

Copy over the ASA software to the secondary:
failover exec standby copy /noconfirm tftp://asa-smp-<version>-k8.bin flash:/

Copy over the ASDM software to the secondary:
failover exec standby copy /noconfirm tftp://asdm-<version>.bin flash:/

If necessary copy over the new versions of the AnyConnect client to the secondary:
failover exec standby copy /noconfirm tftp://anyconnect-<platform>-<architecture>-<version>.pkg flash:/

Your secondary/standby unit is now prepped up for the upgrade. At this point repeat the same steps for the primary unit:

Copy over the ASA software to the primary:
copy /noconfirm tftp://asa-smp-<version>-k8.bin flash:/

Copy over the ASDM software to the primary:
copy /noconfirm tftp://asdm-<version>.bin flash:/

If necessary copy over the new versions of the AnyConnect client to the primary:
copy /noconfirm tftp://anyconnect-<platform>-<architecture>-<version>.pkg flash:/

Now issue the command on the primary to configure the ASA, ASDM, and AnyConnect (if needed) images as the defaults. Because these commands are replicated automatically to the secondary execution is only required on the primary:

On the primary set the system to boot using the new ASA software:
boot system disk0:/asa-smp-<version>.bin

On the primary set the new version of ASDM to be used:
asdm image disk0:/asdm-<version>.bin

If necessary on the primary set the new version of AnyConnect to be used:
anyconnect image disk0:/anyconnect-win-<architecture>-<version>.pkg 1 regex "Windows NT"
anyconnect image disk0:/anyconnect-macosx-i386-<architecture>-<version>.pkg 2 regex "Intel Mac OS X"

At this point your configuration is set for the new versions of the software on both the primary and secondary, all that is left is to write it to memory and reboot either the primary or the secondary depending on how you like to gamble. I prefer to reboot the secondary first and then the primary:

Write the configuration to memory on the primary:
write mem

Reboot the secondary:
failover reload-standby

After the secondary unit reboots (assuming nothing goes wrong) check its status:
show failover state

Reboot the primary:
reload noconfirm save-config

You should now have the latest version of the software installed on both the primary and secondary units.


On Python, LDAP, and Kerberos

Currently I am working on a program that needs to bind to an LDAP server, of course I want to do this securely, and I need to authenticate using Kerberos in the process to have the appropriate right to extract the information I need.

Below is a very simple (as in no exception checking), program to securely bind and authenticate to an LDAP server using TLS. Examples like this are a bit few and far between so I figured another one could help. This was created on a Fedora 18 system using Python 2.7 and python-ldap version 2.4.6.

[sourcecode lang="python"]
import ldap
import ldap.sasl

#Initialize your connection and force it to use TLS
con = ldap.initialize('ldap://')
con.set_option(ldap.OPT_X_TLS_DEMAND, True)

#Configure auth to use GSSAPI
auth = ldap.sasl.gssapi("")

#Actually make the connection
con.sasl_interactive_bind_s("", auth)

#Your operation here

This assumes of course that you have a Kerberos infrastructure in place, as well as having a TGT. In addition, OpenLDAP will need to be configured with the appropriate Certificate Authority in order to securely bind to the LDAP server.

Filed under: Uncategorized No Comments

On Bacula and Enabling IPv6

There is a fair bit of information out there about how to get Bacula to listen on IPv6 that is either wrong or confusing. In order to clear things up, here is what you need to do for each daemon:

FDAddresses = {
ipv6 = { addr = :: ; }

Substitute DirAddresses and SDAddresses as applicable to the daemon configuration you are working on.

This will allow Bacula to listen on all interface both IPv6 and IPv4. I know it doesn't look like it, but it does, test it out using telnet, it will work. However, using "ss -l -4 -n" will not show Bacula as listening.

This was implemented using Bacula 5.2.12, your mileage may vary on older versions.

Filed under: Uncategorized No Comments

On Selenium Grid and Init Scripts

I received a request to configure selenium grid on a system, sadly by default there does not seem to be an init script available for this program, so I hacked on together, borrowing heavily from Eugene Zakharchenko, which I cleaned up heavily.

Here is the init script:

[sourcecode language="bash"]

#Selenium Grid init script
#Version: 1.1
#Created: 2011-02-22
#Author: Eugene Zakharchenko
#Revised: 2011-09-22
#Revised by: Erinn Looney-Triggs
#Revision history:
#1.1 Large cleanups to better utilize functions, simplified.
#1.0 Initial Release

##Chkconfig lines for redhat systems
# chkconfig: 345 85 15
# processname: selenium
# description: Selenium Grid is test distribution broker

# Provides: selenium
# Required-Start: $remote_fs $syslog $network
# Required-Stop: $remote_fs $syslog $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop Selenium Grid daemon
# Description: Selenium Grid is test distribution broker

# Source function library.
. /etc/init.d/functions

# You will probably only need to edit the following variables:

# The selenium user and group must be created before running
# The Selenium Grid Version
# Selenium Grid home directory
# Java interpreter

# You probably will not need to edit below this line
# Location for pid file
# Log file location
# Class path for Selenium Grid
# Options for running Selenium Grid
PARAMS="-classpath ${SELENIUM_GRID_HOME_CLASSPATH} com.thoughtworks.selenium.grid.hub.HubServer"

case "$1" in
echo -n "Starting ${PROG}: "

# Ensure that we have a directory for the logs
if [ ! -f ${LOG_FILE} ]; then
mkdir -m 750 $(dirname ${LOG_FILE})
chown ${USER}:${GROUP} $(dirname ${LOG_FILE})

# Start the process
daemon --user ${USER} --pidfile ${PID_FILE} ${EXEC_REDIRECT}
if [ ${RETVAL} -eq 0 ]; then
touch ${LOCK_FILE}
PID="$(pgrep -f "$(echo ${EXEC})")"
echo ${PID} > ${PID_FILE}
status -p ${PID_FILE} ${PROG}
echo -n "Stopping ${PROG}: "
killproc -p ${PID_FILE} ${PROG}
[ $RETVAL = 0 ] && rm -f ${LOCK_FILE} ${PID_FILE}
$0 stop
$0 start
echo "Usage: $0 {start|stop|status|restart}"
exit 1

Filed under: Uncategorized No Comments

On PostgreSQL and Changing Table Ownership

Yesterday, due to a snafu from the original creation of tables in PostgreSQL to allow Bacula to function, I had to change the permission of a bunch of tables in a database. This turns out to not be as straightforward as it probably should be, however, I found this nice post on stackoverflow that summarized the steps nicely. I am copying the code here for my posterity, this is designed to be run as the PostgreSQL superuser via the bash prompt.

To change the permissions for tables:

for tbl in `psql -qAt -c "select tablename from pg_tables where schemaname = 'public';" YOUR_DB` ; do psql -c "alter table $tbl owner to NEW_OWNER" YOUR_DB ; done

To change the permissions for sequences:

for tbl in `psql -qAt -c "select sequence_name from information_schema.sequences where sequence_schema = 'public';" YOUR_DB` ; do psql -c "alter table $tbl owner to NEW_OWNER" YOUR_DB ; done

The change the permissions for views:

for tbl in `psql -qAt -c "select table_name from information_schema.views where table_schema = 'public';" YOUR_DB` ; do psql -c "alter table $tbl owner to NEW_OWNER" YOUR_DB ; done

Simply change "YOUR_DB" and "NEW_OWNER" in each of the aforementioned bits of code, and you will change the owner for each and every table/sequence/view in the named DB. Brilliant!

Filed under: Uncategorized No Comments

On Bacula and TLS

Just a quick note that the documentation that bacula includes about TLS support is terrible, a much better reference can be found here.

Tagged as: , No Comments
This work by Erinn Looney-Triggs is licensed under a Creative Commons Attribution-ShareAlike 3.0 United States.