solj

May 042018
 

I recently ran into an issue where I needed to update the SSH host keys on a machine which was running NoMachine. In the process, I came across the following annoying error which was not at all indicative of the actual issue

-- NX SERVER START: -c /usr/bin/nxserver - ORIG_COMMAND=
-- NX SERVER START:  - ORIG_COMMAND=                    
Info: Using fds #4 and #3 for communication with nxnode.
HELLO NXSERVER - Version 3.2.0-74-SVN OS (GPL, using backend: not detected)
NX> 105 hello NXCLIENT - Version 3.2.0
NX> 134 Accepted protocol: 3.2.0
NX> 105 SET SHELL_MODE SHELL                            
NX> 105 SET AUTH_MODE PASSWORD  
NX> 105 login
NX> 101 User: awesomeuser
NX> 102 Password:
Info: Closing connection to slave with pid 6424.
NX> 404 ERROR: wrong password or login          
NX> 999 Bye

I verified repeatedly that other methods for logging in were working properly. This problem was due to us using the SSH protocol for NoMachine logins. Unfortunately, this error is also not at all useful because it doesn’t show the actual problem. The problem was that the “nxserver” user had a known_hosts file containing the old ssh host key and for some reason it wouldn’t allow me to accept the new one. I simply removed the old key.

# rm /var/lib/nxserver/home/.ssh/known_hosts
rm: remove regular file `/var/lib/nxserver/home/.ssh/known_hosts'? y

Once the old key was removed, I was once again able to login successfully. Curiously, the known_hosts file was not regenerated. I’m not exactly sure how it wound up there to begin with since this setup was created before I arrived.

 Posted by at 14:29
Feb 192016
 

I was receiving this error when trying to build an RPM containing a very large number of files. The files contained USPS zip code data for the entire United States. When building the RPM, I would receive the following error:

error: Unable to create immutable header region

I tried searching for a solution and came across this bug: http://rpm.org/ticket/862. So, basically, this is an arbitrary limit imposed by RPM which doesn’t appear to have a clean workaround.

My method for bypassing the limit was to use the suggestion at https://bugzilla.redhat.com/show_bug.cgi?id=913099#c8. I built an RPM which split the zip code data by the first digit. The resulting spec file looks something like this.

Name:           usps-zipdata
Version:        0.1
Release:        1%{?dist}
Summary:        USPS zip code data

License:        custom license
URL:            https://example.com/uspsdata
Source0:        %{name}-%{version}.tar.bz2

BuildArch:      noarch
BuildRequires:  coreutils, bzip2
Requires:       usps-zipdata-0 = %{version}-%{release}
Requires:       usps-zipdata-1 = %{version}-%{release}
Requires:       usps-zipdata-2 = %{version}-%{release}
Requires:       usps-zipdata-3 = %{version}-%{release}
Requires:       usps-zipdata-4 = %{version}-%{release}
Requires:       usps-zipdata-5 = %{version}-%{release}
Requires:       usps-zipdata-6 = %{version}-%{release}
Requires:       usps-zipdata-7 = %{version}-%{release}
Requires:       usps-zipdata-8 = %{version}-%{release}
Requires:       usps-zipdata-9 = %{version}-%{release}

%description
Static USPS zip code data.

%package 0
Summary:        USPS zip code data 0*

%description 0
Static USPS zip code data for zip codes starting with the number zero.

%package 1
Summary:        USPS zip code data 1*

%description 1
Static USPS zip code data for zip codes starting with the number one.

%package 2
Summary:        USPS zip code data 2*

%description 2
Static USPS zip code data for zip codes starting with the number two.

%package 3
Summary:        USPS zip code data 3*

%description 3
Static USPS zip code data for zip codes starting with the number three.

%package 4
Summary:        USPS zip code data 4*

%description 4
Static USPS zip code data for zip codes starting with the number four.

%package 5
Summary:        USPS zip code data 5*

%description 5
Static USPS zip code data for zip codes starting with the number five.

%package 6
Summary:        USPS zip code data 6*

%description 6
Static USPS zip code data for zip codes starting with the number six.

%package 7
Summary:        USPS zip code data 7*

%description 7
Static USPS zip code data for zip codes starting with the number seven.

%package 8
Summary:        USPS zip code data 8*

%description 8
Static USPS zip code data for zip codes starting with the number eight.

%package 9
Summary:        USPS zip code data 9*

%description 9
Static USPS zip code data for zip codes starting with the number nine.

%prep
%setup -q

%build

%install
rm -rf $RPM_BUILD_ROOT
install -d $RPM_BUILD_ROOT/var/usps
tar xvf zip.tar.bz2
mv zip $RPM_BUILD_ROOT/var/usps/

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
%dir /var/usps/zip
%dir /var/usps/zip/MSS
/var/usps/zip/MSS/[a-z]*

%files 0
/var/usps/zip/MSS/0*

%files 1
/var/usps/zip/MSS/1*

%files 2
/var/usps/zip/MSS/2*

%files 3
/var/usps/zip/MSS/3*

%files 4
/var/usps/zip/MSS/4*

%files 5
/var/usps/zip/MSS/5*

%files 6
/var/usps/zip/MSS/6*

%files 7
/var/usps/zip/MSS/7*

%files 8
/var/usps/zip/MSS/8*

%files 9
/var/usps/zip/MSS/9*

%changelog
* Thu Feb 18 2016 Sol Jerome  - 0.1-1
- create new RPM for USPS zip code data
 Posted by at 11:10
Oct 062015
 

When using Citrix XenCenter 6.5, I was suddenly unable to connect to a XenServer instance running 6.2. The following was in the XenCenter Event log.

Failed to connect to foo.example.com
The request was aborted: Could not create SSL/TLS secure channel.

This was not due solely to the version mismatch but, seemingly, to an update in XenCenter which forces stricter SSL checks. The only difference I found was that the XenServer instance I was unable to connect to had a cert containing an old IP address.

The first thing I did was update the parameters used to generate the SSL certificate

vim /opt/xensource/libexec/generate_ssl_cert

Then I was able to simply regenerate the certificate using the new parameters (and giving the resulting certificate the new IP address)

/opt/xensource/libexec/generate_ssl_cert /etc/xensource/xapi-ssl.pem $(hostname -f) && /etc/init.d/xapi start

Once completed, I was able to connect successfully.

 Posted by at 12:18
Jan 122013
 

In this post, I will describe how to setup incremental database propagation as described in the MIT documentation. Unfortunately, the instructions at the preceding link are incomplete (as of this writing). The aim of this post is to completely describe how to setup incremental propagation.

For the purposes of this tutorial, I will assume you have 2 KDCs (referred to here as kdc1.example.com and kdc2.example.com). Installing the KDCs is out of the scope of this post. In this post, I will use the default filesystem paths as they exist on Debian for illustration purposes.

First, you need to add kiprop principals for kdc1 and kdc2.

kdc1 # kadmin.local 
Authenticating as principal solj/admin@EXAMPLE.COM with password.
kadmin.local:  addprinc -policy service -randkey kiprop/kdc1.example.com
Principal "kiprop/kdc1.example.com@EXAMPLE.COM" created.
kadmin.local:  addprinc -policy service -randkey kiprop/kdc2.example.com
Principal "kiprop/kdc2.example.com@EXAMPLE.COM" created.

Once you have done this, you will need to dump the database on kdc1 and load it on kdc2.

kdc1 # kdb5_util dump principal

Use a secure method (e.g. scp) to transfer the principal database to kdc2 and load the database there.

kdc2 # kdb5_util load principal

Add the following options in the appropriate [realms] section of /etc/krb5kdc/kdc.conf on both KDCs.

iprop_enable = true
iprop_port = 2121

The actual port you use is up to you. Note that there are other iprop_ options you can use and they are already documented on the MIT page.

Next, you need to allow the kiprop principals the access they need to propagate the database. On kdc1, add the following to /etc/krb5kdc/kadm5.acl.

kiprop/krb1.example.com p
kiprop/krb2.example.com p

Extract kdc1’s kiprop keytab to /etc/krb5kdc/kadm5.keytab.

kdc1 # kadmin.local 
Authenticating as principal solj/admin@EXAMPLE.COM with password.
kadmin.local: ktadd -k /etc/krb5kdc/kadm5.keytab kiprop/kdc1.example.com
Entry for principal kiprop/kdc1.example.com with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab.
Entry for principal kiprop/kdc1.example.com with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab.
Entry for principal kiprop/kdc1.example.com with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab.
Entry for principal kiprop/kdc1.example.com with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab.

You also need to extract kdc2’s kiprop keytab, however, it should go to the default keytab file (DEFKTNAME).

kdc2 # kadmin -p solj/admin
Authenticating as principal solj/admin with password.
Password for solj/admin@EXAMPLE.COM: 
kadmin: addprinc -policy service -randkey kiprop/kdc2.example.com
Principal "kiprop/kdc2.example.com@SIRIAD.COM" created.
kadmin:  ktadd kiprop/kdc2.example.com
Entry for principal kiprop/kdc2.example.com with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal kiprop/kdc2.example.com with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal kiprop/kdc2.example.com with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal kiprop/kdc2.example.com with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/etc/krb5.keytab.

You should now be able to restart kadmind on kdc1 and run kpropd on kdc2 to successfully propagate the database. Note that you can debug this process by watching the kadmind logs as well as running kpropd in the foreground (kpropd -S -d).

 Posted by at 16:25
Jan 022013
 

For those who are using IPv6, you will likely also want to setup iptables rules similar to those used for IPv4 traffic. There are some slight differences between the two and this post is meant to point out just a couple.

I have a very basic iptables template that looks like the following.

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
# allow incoming ssh connections
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
# reject everything else
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

Here is the equivalent ip6tables template.

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
# allow incoming ssh connections
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
# reject everything else
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
COMMIT

Here you can see that the icmp protocol is now referred to as ipv6-icmp. Also, there is no icmp-host-prohibited qualifier. The equivalent qualifier for IPv6 is icmp6-adm-prohibited. These are the only two I have encountered (so far). Please feel free to leave a list of more in the comments and I will update the post.

 Posted by at 20:45
Sep 052012
 

This post will guide you through a simple setup to confine users defined in LDAP using Security-Enhanced Linux. SELinux on RHEL6/Debian Wheezy comes with confined user roles which allows quick and easy setup for restricting users who are given access to your machines.

# semanage login -l

Login Name                SELinux User              MLS/MCS Range            

__default__               unconfined_u              s0-s0:c0.c1023           
root                      unconfined_u              s0-s0:c0.c1023           
system_u                  system_u                  s0-s0:c0.c1023

Looking at these default roles, you can see that not a whole lot is restricted on a cleanly-installed machine. Unfortunately, this means that any users you add will be logging in with an unconfined_r role which essentially delegates access controls to systems other than SELinux.

Depending on the role that this machine will play in your organization, you probably want to set the default to something other than unconfined_u. The various default SELinux users can be found in /etc/selinux/targeted/contexts/users/.

# ls -l /etc/selinux/targeted/contexts/users/
total 24
-rw-r--r--. 1 root root 253 Jun 18 09:01 guest_u
-rw-r--r--. 1 root root 389 Jun 18 09:01 root
-rw-r--r--. 1 root root 514 Jun 18 09:01 staff_u
-rw-r--r--. 1 root root 578 Jun 18 09:01 unconfined_u
-rw-r--r--. 1 root root 353 Jun 18 09:01 user_u
-rw-r--r--. 1 root root 307 Jun 18 09:01 xguest_u

For our purposes, we’ll go ahead and set the __default__ selinux user to user_u. To do this, you simply run semanage login -m -s user_u -r s0 __default__. You can see the change below.

# semanage login -l

Login Name                SELinux User              MLS/MCS Range            

__default__               user_u                    s0                       
root                      unconfined_u              s0-s0:c0.c1023           
system_u                  system_u                  s0-s0:c0.c1023

Now, any user who does not have an explicit entry in the output above will be confined to user_u. Great! So, what about potential privileged users who may need sudo access? The user_u profile is inadequate for these types of users as it’s very restrictive. A more appropriate role would be something like staff_u. My user account only exists in LDAP.

# grep -c solj /etc/passwd
0
# getent passwd solj
solj:*:1000:2000:Sol Jerome:/home/solj:/bin/bash

This is okay. The first thing to do is add a login mapping for the user.

semanage login -a -s staff_u solj

Now, logging in as that user should give you the proper security context.

$ id
uid=1000(solj) gid=2000(sysadmin) groups=2000(sysadmin) context=staff_u:staff_r:staff_t:s0-s0:c0.c1023

Okay, now the last part is to give this person sudo access. My sudo configuration resides in LDAP. Therefore, I will need to add 2 new sudoOptions in order to allow my user to transition properly to sysadm_r:sysadm_t. The following is an example of the type of errors you will see if these options are not present.

$ sudo -i
-bash: /root/.bash_profile: Permission denied
-bash-4.1#

The correct sudoers entry should look like the following.

cn=solj,ou=sudoers,dc=example,dc=com
cn: solj
objectClass: sudoRole
objectClass: top
sudoHost: ALL
sudoRunAs: ALL
sudoUser: solj
sudoCommand: ALL
sudoOption: role=sysadm_r
sudoOption: type=sysadm_t

And now when I run sudo, I am able to transition no problem.

$ sudo -i
# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=staff_u:sysadm_r:sysadm_t:s0-s0:c0.c1023
 Posted by at 18:03
Jul 142012
 

We have a Brother HL-2140 laser printer that we bought on sale to replace an older ink jet printer. So far, it’s been great. The only issue we’ve had is that the software used to determine when you need to replace the toner is either intentionally or unintentionally _very_ wrong.

The reason we got the laser printer was because we were constantly having to refill the ink cartridge on the ink jet printer. So far, we have yet to finish using a single toner cartridge on the new printer (despite what the software would have you believe).

An easy way to tell when you are out of toner is that the printouts will start to look faded. This wasn’t the case the first time the software told us we were out of toner. An unfortunate “feature” of this software is that if it thinks you are low on toner, you have no choice but to replace the toner before it will let you print.

Therefore, we had to “trick” the printer into thinking that the toner was fine (which it was). The first step in doing this was to grab a post-it note and a piece of tape. Fold the post-it note into a tiny square and situate it over the opening in the toner cartridge. This is what the printer uses to check the toner level.

Cover the sensor with a post-it note and some tape.

I had previously simply covered the opening with a piece of tape and colored it black with a sharpie. While that lasted a while, the software soon went back to thinking that the toner cartridge was empty and prevented me from printing.

Next, you need to insert the toner cartridge back into the printer, being careful to make sure that the post-it + tape stay in place.

Make sure that the post-it note and tape stay in place.

Once inserted back into the printer, you should be able to turn it on and notice that the Toner light is no longer lit. The software will then let you print regardless of how much toner is left.

No more error light for the Toner

 Posted by at 10:40
May 032012
 

This post will cover post-installation steps necessary to go from a completely unmanaged machine to a machine that is setup to be an LDAP server with a basic DIT. This will also setup phpldapadmin for web-based administration of your LDAP directory.

Note: I use nginx here simply because I find it easier to deal with. There’s no requirement for it and you may find it easier to use apache.

The post-install script used to setup the LDAP server is below. The reason this is used is because there are a lot of one time things that happen during the installation of an LDAP server and I have not yet been able to represent some of these events in bcfg2. The script below depends on some files that are hosted on another web server. I will provide the necessary files needed below.

The custom php packages are available from http://blog.famillecollet.com/pages/Config-en. The reason for using these packages is that php-fpm is not available from the stock RHEL repositories or from EPEL. Since I am already familiar with php-fpm and I prefer to use it, I decided to simply download only the necessary packages rather than use the entire repository.

#!/bin/bash

# ssl settings
WEBCERT="/etc/pki/tls/certs/phpldapadmin.crt"
WEBKEY="/etc/pki/tls/private/phpldapadmin.key"
SLAPDCERT="/etc/openldap/cacerts/slapd.crt"
SLAPDMASTERCERT="/etc/openldap/cacerts/slapd-master.crt"
SLAPDKEY="/etc/pki/tls/private/slapd.key"
SSLSUBJ="/C=Country Code/ST=Some State/L=City/O=Organization Name/OU=Organizational Unit Name/CN=${HOSTNAME}"

# misc settings
LDAPDIR="/root/ldap-setup"
HTTPDIR="http://web.server/ldap"
LDIFDIR="${HTTPDIR}/ldif"
RPMS="${HTTPDIR}/rpms/php-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-cli-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-common-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-fpm-5.3.8-5.el6.remi.x86_64.rpm
${HTTPDIR}/rpms/php-ldap-5.3.8-5.el6.remi.x86_64.rpm
openldap-clients
openldap-servers
autofs"

PASSWD="changeme"
SLAPPASSWD=""
BCFG2PASSWD=""

selinux-disable()
{
    #FIXME: remove when bcfg2 selinux policy works properly
    setenforce 0
}

selinux-enable()
{
    #FIXME: remove when bcfg2 selinux policy works properly
    setenforce 1
}

inst-packages()
{
    echo -n "Installing custom php packages for phpldapadmin..."
    yum -y --nogpgcheck install ${RPMS} >/dev/null
    # FIXME: update the kernel (kernel panics when not done here)
    yum -y update kernel >/dev/null
    echo "done"
}

gen-ssl-certs()
{
    /usr/bin/openssl req -batch -new -x509 -nodes \
        -subj "${SSLSUBJ}" \
        -out ${WEBCERT} \
        -keyout ${WEBKEY} -days 3600 >/dev/null
    /usr/bin/openssl req -batch -new -x509 -nodes \
        -subj "${SSLSUBJ}" \
        -out ${SLAPDCERT} \
        -keyout ${SLAPDKEY} -days 3600 >/dev/null

    cacertdir_rehash /etc/openldap/cacerts
}

get-passwds()
{
    # setup ldap admin password
    echo -n "Please enter a new ldap admin password: "
    read -s PASSWD
    # get bcfg2 password
    echo -n "Please enter the bcfg2 password (can be found in /etc/bcfg2.conf on an existing client): "
    read -s BCFG2PASSWD
    echo
}

gen-slappasswd()
{
    if [ -x /usr/sbin/slappasswd ]
    then
        SLAPPASSWD=$(/usr/sbin/slappasswd -s ${PASSWD})
    else
        echo "Failed to find slappasswd. Aborting."
        exit 1
    fi
}

setup-ldap()
{
    /usr/bin/curl -o ${LDAPDIR}/fix-admin-account.ldif ${LDIFDIR}/fix-admin-account.ldif
    /usr/bin/curl -o ${LDAPDIR}/new-ldap-setup.ldif ${LDIFDIR}/new-ldap-setup.ldif
    /usr/bin/curl -o ${LDAPDIR}/base.ldif ${LDIFDIR}/base.ldif
    sed -i "s|PWREPLACE|${SLAPPASSWD}|" ${LDAPDIR}/fix-admin-account.ldif ${LDAPDIR}/new-ldap-setup.ldif
    # this seems wrong. if someone knows how to do this better, please inform me.
    echo "olcRootPW: ${SLAPPASSWD}" >> /etc/openldap/slapd.d/cn=config/olcDatabase={0}config.ldif
    /bin/cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
    chown -R ldap. /var/lib/ldap
    /sbin/service slapd start && sleep 1 # FIXME: how do you do this properly?
    ldapadd -w ${PASSWD} -x -D "cn=config" -f ${LDAPDIR}/fix-admin-account.ldif
    ldapadd -w ${PASSWD} -x -D "cn=admin,cn=config" -f ${LDAPDIR}/new-ldap-setup.ldif
    ldapadd -w ${PASSWD} -x -D "cn=Manager,dc=uh,dc=edu" -f ${LDAPDIR}/base.ldif
}

add-sudo()
{
    /usr/bin/curl -o ${LDAPDIR}/sudo-index.ldif ${LDIFDIR}/sudo-index.ldif
    cp /usr/share/doc/$(rpm -q sudo --qf "%{NAME}"-"%{VERSION}")/schema.OpenLDAP /etc/openldap/schema/sudo.schema
    restorecon -F -R -v /etc/openldap/schema
    mkdir ${LDAPDIR}/sudo-ldap
    echo "include /etc/openldap/schema/sudo.schema" > ${LDAPDIR}/sudo-ldap/sudoschema.conf
    slapcat -f ${LDAPDIR}/sudo-ldap/sudoschema.conf -F /tmp \
            -n0 -s "cn={0}sudo,cn=schema,cn=config" > ${LDAPDIR}/sudo-ldap/sudo-tmp.ldif
    sed -i 's/{0}sudo/sudo/' ${LDAPDIR}/sudo-ldap/sudo-tmp.ldif
    head -n-8 ${LDAPDIR}/sudo-ldap/sudo-tmp.ldif > ${LDAPDIR}/sudo-ldap/sudo.ldif
    echo -e "\n$(cat ${LDAPDIR}/sudo-index.ldif)" >> ${LDAPDIR}/sudo-ldap/sudo.ldif # add in our sudo index
    rm ${LDAPDIR}/sudo-index.ldif
    ldapadd -w ${PASSWD} -x -D "cn=admin,cn=config" -f ${LDAPDIR}/sudo-ldap/sudo.ldif
}

add-autofs()
{
    cp /usr/share/doc/$(rpm -q autofs --qf "%{NAME}"-"%{VERSION}")/autofs.schema /etc/openldap/schema/autofs.schema
    restorecon -F -R -v /etc/openldap/schema
    mkdir ${LDAPDIR}/autofs
    echo "include /etc/openldap/schema/core.schema" > ${LDAPDIR/autofs/autofs.conf
    echo "include /etc/openldap/schema/cosine.schema" >> ${LDAPDIR/autofs/autofs.conf
    echo "include /etc/openldap/schema/autofs.schema" >> ${LDAPDIR/autofs/autofs.conf
    slapcat -f ${LDAPDIR}/autofs/autofs.conf -F /tmp \
            -n0 -s "cn={2}autofs,cn=schema,cn=config" > ${LDAPDIR}/autofs/autofs-tmp.ldif
    sed -i 's/{2}autofs/autofs/' ${LDAPDIR}/autofs/autofs-tmp.ldif
    head -n-8 ${LDAPDIR}/autofs/autofs-tmp.ldif > ${LDAPDIR}/autofs/autofs.ldif
    ldapadd -w ${PASSWD} -x -D "cn=admin,cn=config" -f ${LDAPDIR}/autofs/autofs.ldif
}

import-db()
{
    while true; do
        echo -n "Is this machine a master or a slave? [m/s] "
        read status
        case $status in
            m*|M*)
                /usr/bin/curl -o ${LDAPDIR}/olcaccess.ldif ${LDIFDIR}/olcaccess.ldif
                /usr/bin/curl -o ${LDAPDIR}/syncprov-module.ldif ${LDIFDIR}/syncprov-module.ldif
                /usr/bin/curl -o ${LDAPDIR}/syncprov.ldif ${LDIFDIR}/syncprov.ldif
                ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/olcaccess.ldif
                ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/syncprov-module.ldif
                ldapadd -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/syncprov.ldif
                break
            ;;
            s*|S*)
                # grab master SSL certificate
                /usr/bin/curl -o ${SLAPDMASTERCERT} ${HTTPDIR}/slapd-master.crt
                cacertdir_rehash /etc/openldap/cacerts

                /usr/bin/curl -o ${LDAPDIR}/olcaccess-slave.ldif ${LDIFDIR}/olcaccess-slave.ldif
                /usr/bin/curl -o ${LDAPDIR}/syncrepl.ldif ${LDIFDIR}/syncrepl.ldif
                ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/olcaccess-slave.ldif
                ldapmodify -w ${PASSWD} -D "cn=admin,cn=config" -f ${LDAPDIR}/syncrepl.ldif
                break
            ;;
            *)
                echo "Invalid response."
            ;;
        esac
    done
}

run-bcfg2()
{
    /usr/sbin/bcfg2 -vqe -S https://bcfg2.server:6789 -x ${BCFG2PASSWD} --ca-cert=/etc/bcfg2.ca -r packages
    /usr/sbin/bcfg2 -vqer packages
}

selinux-disable
mkdir -p ${LDAPDIR}
get-passwds
inst-packages
gen-ssl-certs
gen-slappasswd
setup-ldap
add-sudo
import-db
run-bcfg2
selinux-enable
echo "Setup complete. Please reboot."

Here are the accompanying ldif files needed.

fix-admin-account.ldif

# Set password for cn=admin,cn=config
dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: PWREPLACE
-
replace: olcRootDN
olcRootDN: cn=admin,cn=config

ldif/new-ldap-setup.ldif

# create modules area
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib64/openldap

# set access for the monitor db.
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="cn=Manager,dc=yourcompany,dc=com" read by * none

# change LDAP domain, password and access rights.
dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=yourcompany,dc=com
-
replace: olcRootDN
olcRootDN: cn=Manager,dc=yourcompany,dc=com
-
replace: olcRootPW
olcRootPW: PWREPLACE

# setup SSL
dn: cn=config
changetype:modify
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/pki/tls/private/slapd.key
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/cacerts/slapd.crt
-
replace: olcTLSCipherSuite
olcTLSCipherSuite: HIGH:MEDIUM:-SSLv2

base.ldif

# setup basic tree
dn: dc=yourcompany,dc=com
dc: uh
objectClass: top
objectClass: domain

dn: ou=People,dc=yourcompany,dc=com
ou: People
objectClass: top
objectClass: organizationalUnit

dn: ou=Group,dc=yourcompany,dc=com
ou: Group
objectClass: top
objectClass: organizationalUnit

dn: cn=replicator,dc=yourcompany,dc=com
cn: replicator
objectClass: organizationalRole
objectClass: simpleSecurityObject
objectClass: top
description: LDAP replication user
userPassword: changeme

ldif/sudo-index.ldif

# add sudo index
dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: sudoUser eq

These can be changed to match your needs. In this case, anyone in the group cn=ldapadmin,ou=yourorganizationalunit,dc=yourcompany,dc=com is given full access to the LDAP directory (UPDATE: Please note that the ldapadmin cn is a groupOfNames objectClass [_not_ a posixGroup]).
ldif/olcaccess.ldif

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to * by dn.base="cn=replicator,dc=yourcompany,dc=com" read by * break
olcAccess: {1}to * by group.exact="cn=ldapadmin,ou=yourorganizationalunit,dc=yourcompany,dc=com" write by * break
olcAccess: {2}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {3}to attrs=shadowLastChange by self write by * read
olcAccess: {4}to * by * read
-

ldif/syncprov-module.ldif

# setup syncprov module
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: {1}syncprov

You will want to modify these settings according to your replication needs.

ldif/syncprov.ldif

dn: olcOverlay={0}syncprov,olcDatabase={2}bdb,cn=config
objectClass: olcSyncProvConfig
olcOverlay: {0}syncprov
olcSpCheckpoint: 100 10
olcSpSessionlog: 100

ldif/olcaccess-slave.ldif

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to * by group.exact="cn=ldapadmin,ou=yourorganizationalunit,dc=yourcompany,dc=com" write by * break
olcAccess: {1}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {2}to * by * read
-

ldif/syncrepl.ldif

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcSyncrepl
olcSyncrepl: {0}rid=000 provider=ldaps://ldap-master-server searchbase=dc=yourcompany,dc=com type=refreshAndPersist retry="5 5 300 +" bindmethod=simple binddn="cn=re
plicator,dc=yourcompany,dc=com" credentials="changeme" tls_cacertdir=/etc/openldap/cacerts                                                                              -

Here are the relevant bits from the ldap bundle in the bcfg2 repository

<Bundle name='ldap'>
        <Group name='ldap-server'>
                <BoundPath name='/etc/openldap/cacerts/slapd.crt' type='permissions' owner='ldap' group='ldap' perms='0600'/>
                <BoundPath name='/etc/pki/tls/private/slapd.key' type='permissions' owner='ldap' group='ldap' perms='0600'/>
                <Package name='ldapvi'/>
                <Package name='openldap-clients'/>
                <Package name='openldap-servers'/>
                        <Path name='/etc/sysconfig/ldap'/>
                        <BoundPath name='/etc/openldap/slapd.d' type='directory' owner='ldap' group='ldap' perms='0700'/>

                <Service name='slapd'/>

                <!-- phpLDAPadmin settings -->
                <Package name='php'/>
                        <BoundPath name='/var/lib/php/session' type='directory' owner='root' group='nginx' perms='0770'/>
                <Package name='php-fpm'/>
                        <Path name='/etc/php-fpm.d/www.conf'/>
                <Package name='php-ldap'/>
                <Package name='nginx'/>
                <Package name='phpldapadmin'/>
                <Service name='php-fpm'/>
                <Service name='nginx'/>
                <Path name='/etc/nginx/conf.d/phpldapadmin.conf'/>
                <Path name='/etc/openldap/ldap.conf'/>
                <Path name='/etc/phpldapadmin/config.php'/>
                <BoundPath name='/var/www/html/phpldapadmin' type='symlink' to='/usr/share/phpldapadmin/htdocs'/>
                <Path name='/usr/share/phpldapadmin/templates/creation/custom_uh.xml'/>
        </Group>
</Bundle>

The /etc/sysconfig/ldap file needs to be modified to allow LDAPS by uncommenting SLAPD_LDAPS=yes. In /etc/php-fpm.d/www.conf, you need to make sure the user/group are set to nginx (if you are using nginx as your web server).

My nginx configuration for /etc/nginx/conf.d/phpldapadmin.conf looks like this.

server {
        listen          80;
        server_name     ldap-server-hostname;
        rewrite         ^/(.*) https://ldap-server-hostname/$1 permanent;
}

server {
        listen                  443; # listen also for IPv4 traffic on "regular" IPv4 sockets
        server_name             ldap-server-hostname;
        access_log              /var/log/nginx/ssl-access.log;
        error_log               /var/log/nginx/ssl-error.log;
        root                    /var/www/html/phpldapadmin;

        ssl                     on;
        ssl_certificate         /etc/pki/tls/certs/phpldapadmin.crt;
        ssl_certificate_key     /etc/pki/tls/private/phpldapadmin.key;

        index           index.php index.html;

        location ~ \.php$ {
                fastcgi_pass    localhost:9000;
                fastcgi_index   index.php;
                fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include         fastcgi_params;
                fastcgi_param   HTTPS on;
        }
}

I needed the following lines in /etc/openldap/ldap.conf to get phpldapadmin working properly.

URI             ldaps://localhost/
TLS_CACERTDIR   /etc/openldap/cacerts
TLS_REQCERT     never

Lastly, you will need to modify /etc/phpldapadmin/config.php with appropriate values for your site.

 Posted by at 13:16
Mar 162012
 

The first thing you need to do is install all the required packages. The following is my rt.xml bundle for use with Bcfg2. It details the Packages, Services, and Paths that need to be setup for RT to work properly (the fetchmail configuration is not detailed below).

Note: There are some packages explicitly listed below due to the fact that I configure apt not to install recommended packages by default. You may or may not need to install them in order for your request tracker installation to work properly (the libfcgi-perl is required in order to use the rt4-fcgi method).

<Bundle name='rt'>
        <Package name="mysql-server"/>
        <Service name="mysql"/>
        <!-- rt configuration -->
        <Package name="request-tracker4"/>
                <Package name="libmime-tools-perl"/>
                <Package name="libmouse-perl"/>
                <Package name="libterm-readline-perl-perl"/>
                <Package name="libxml-libxml-perl"/>
                <Package name="rt4-fcgi"/>
                        <Path name="/etc/default/rt4-fcgi"/>
                        <Package name="libfcgi-perl"/>
                <Package name="rt4-db-mysql"/>
                        <Package name="mysql-client"/>
                <Package name="ttf-dejavu-core"/>
        <Service name="request-tracker4"/>
        <Package name="nginx-full"/>
                <Path name="/etc/nginx/sites-available/rt"/>
        <Service name="nginx"/>
        <Service name="rt4-fcgi"/>
        <Path name="/etc/request-tracker4/RT_SiteConfig.d/50-debconf"/>
        <Path name="/etc/request-tracker4/RT_SiteConfig.d/51-dbconfig-common"/>
        <!-- fetchmail configuration -->
        <Package name="fetchmail"/>
        <Path name="/etc/default/fetchmail"/>
        <Path name="/etc/fetchmailrc"/>
        <Service name="fetchmail"/>
</Bundle>

You will want to install the mysql-server package first and setup the RT database.

root@rt:~# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 43
Server version: 5.1.61-2 (Debian)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database rtdb;
Query OK, 1 row affected (0.00 sec)

mysql> grant all privileges on rtdb.* to 'rt'@'localhost' identified by 'SECRETPASSWORD';
Query OK, 0 rows affected (0.03 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

Next, modify /etc/request-tracker4/RT_SiteConfig.d/50-debconf to suit your custom environment. You also need to reconfigure /etc/request-tracker4/RT_SiteConfig.d/51-dbconfig-common to use mysql with the appropriate values for the database that was created.

# THE DATABASE:
# generated by dbconfig-common

# map from dbconfig-common database types to their names as known by RT
my %typemap = (
    mysql   => 'mysql',
    pgsql   => 'Pg',
    sqlite3 => 'SQLite',
);
    
Set($DatabaseType, $typemap{mysql} || "UNKNOWN");

Set($DatabaseHost, 'localhost');
Set($DatabasePort, '3306');

Set($DatabaseUser , 'rt');
Set($DatabasePassword , 'SECRETPASSWORD');

# SQLite needs a special case, since $DatabaseName must be a full pathname
#my $dbc_dbname = ''; if ( "" eq "sqlite3" ) { Set ($DatabaseName, '' . '/' . $dbc_dbname); } else { Set ($DatabaseName, $dbc_dbname); }
Set($DatabaseName, 'rtdb');

By default, the RT install uses an sqlite database. The above tells it to use the mysql database that was created in the previous step. Once that is complete, you need to update the SiteConfig by running update-rt-siteconfig. Then you can move on to configuring nginx.

The following nginx configuration works for configuring RT with fcgi (probably not optimal, suggestions for improvement are welcome):

server {
        listen                  80;
        server_name             rt.siriad.com;

        access_log              /var/log/nginx/rt.siriad.com/access_log;
        error_log               /var/log/nginx/rt.siriad.com/error_log;
        root                    /usr/share/request-tracker4/html;
        client_max_body_size    20M;

        location /NoAuth/images/ {
                try_files local/html$uri
                        share/html$uri
                        @main
                        ;
                expires 1M;
        }
        location / {
                fastcgi_pass    unix:/var/run/rt4-fcgi.sock;
                include         /etc/nginx/fastcgi_params;
                fastcgi_param   SCRIPT_NAME     "";
                fastcgi_param   PATH_INFO       $uri;
        }
        location @main {
                fastcgi_pass    unix:/var/run/rt4-fcgi.sock;
                include         /etc/nginx/fastcgi_params;
                fastcgi_param   SCRIPT_NAME     "";
                fastcgi_param   PATH_INFO       $uri;
        }
}

The above nginx configuration expects the following in /etc/default/rt4-fcgi (to enable the rt4-fcgi init script).

# Defaults for request-tracker4 initscript
# sourced by /etc/init.d/rt4-fcgi

#
# This is a POSIX shell fragment
#

enabled=1

# number of RT workers:
workers=2

You should now be able to start the rt4-fcgi init script and nginx and login with the default RT username and password.

 Posted by at 17:17
Dec 172011
 

Update: Post updated to allow for generation of multiple mirrors of varying versions of RHEL as shown at http://brandonhutchinson.com/mrepo_configuration.html.

The latest version of mrepo available in EPEL (mrepo-0.8.7-2.el6.noarch.rpm at the time of this writing) won’t allow you to mirror RHN without some slight modifications. This is a brief howto that will highlight exactly what is needed to allow mrepo to mirror RHN on RHEL6.

NOTE: This howto is loosely based on the RHEL5 mrepo howto available at http://ln-s.net/9SlN.

You will need to install the following packages:

pyOpenSSL
rhn-client-tools
rhpl
mrepo

Next, you need to setup mrepo.conf with your RHN login credentials by adding the following to the [main] section:

rhnlogin = <username>:<password>

Set a silly default for up2date

echo "up2date default" > /etc/sysconfig/rhn/sources

Set your machine’s UUID

UUID=$(uuidgen) ; /bin/echo -e "uuid[comment]=Universally Unique ID for this server\nrhnuuid=$UUID" \
 > /etc/sysconfig/rhn/up2date-uuid

Set up additional repositories (RHEL5 in this case). Note that the path will differ depending on your srcdir as specified in mrepo.conf.

gensystemid -u RHN_username -p RHN_password --release=5Server --arch=x86_64 /srv/mrepo/src/5Server-x86_64/

Make sure the proper certificate is in use

cp `cat /etc/sysconfig/rhn/up2date|grep ^sslCACert=|cut -d= -f2` /usr/share/rhn/RHNS-CA-CERT

Add your RHEL6 (and any additional platforms) mrepo configuration (e.g.):
/etc/mrepo.conf.d/6Server.conf

### Name: Red Hat Enterprise Server v6
### URL: http://www.redhat.com/

[6Server]
name = Red Hat Enterprise Server $release ($arch)
release = 6
arch = x86_64
metadata = yum repomd

### RHEL6 repositories
updates = rhns://<your satellite server>/rhel-$arch-server-$release
optional = rhns://<your satellite server>/rhel-$arch-server-optional-$release
rhn-tools = rhns://<your satellite server>/$repo-rhel-$arch-server-$release
supplementary = rhns://<your satellite server>/rhel-$arch-server-$repo-$release

/etc/mrepo.conf.d/5Server.conf

### Name: Red Hat Enterprise Server v5
### URL: http://www.redhat.com/

[5Server]
name = Red Hat Enterprise Server $release ($arch)
release = 5
arch = x86_64
metadata = repomd

### RHEL5 repositories
updates = rhns://<your satellite server>/rhel-$arch-server-$release
vt = rhns://<your satellite server>/rhel-$arch-server-$repo-$release
supplementary = rhns://<your satellite server>/rhel-$arch-server-$repo-$release
fastrack = rhns://<your satellite server>/rhel-$arch-server-$repo-$release
hts = rhns://<your satellite server>/rhel-$arch-server-$repo-$release
rhn-tools = rhns://<your satellite server>/$repo-rhel-$arch-server-$release

Lastly, you need to fix a couple bugs in the current mrepo release so that it will run successfully on RHEL6. The first file to change is /usr/share/mrepo/up2date_client/up2dateUtils.py:

--- /usr/share/mrepo/up2date_client/up2dateUtils.py     2008-08-14 19:14:47.000000000 -0500
+++ /var/lib/bcfg2/Cfg/usr/share/mrepo/up2date_client/up2dateUtils.py/up2dateUtils.py   2011-12-02 09:27:07.500138609 -0600
@@ -13,7 +13,7 @@
 import time
 import rpm
 import string
-import md5
+import hashlib

 sys.path.insert(0, "/usr/share/rhn/")
 sys.path.insert(1,"/usr/share/rhn/up2date_client")
@@ -158,7 +158,7 @@

 def md5sum(fileName):
-    hashvalue = md5.new()
+    hashvalue = hashlib.md5()

     try:
         f = open(fileName, "r")

The second file to change is /usr/share/mrepo/rhn/transports.py

--- /usr/share/mrepo/rhn/transports.py  2008-08-14 19:14:47.000000000 -0500
+++ /var/lib/bcfg2/Cfg/usr/share/mrepo/rhn/transports.py/transports.py  2011-12-13 15:04:19.236104253 -0600
@@ -33,6 +33,7 @@

 class Transport(xmlrpclib.Transport):
     user_agent = "rhn.rpclib.py/%s" % __version__
+    _use_datetime = False

     def __init__(self, transfer=0, encoding=0, refreshCallback=None,
             progressCallback=None):

That should do it. You should then be able to run mrepo -ugv and update your local mrepo mirror with the latest from RHN.

 Posted by at 21:57