Upgrading from Subversion 1.7 to 1.8

I recently worked with an organization to upgrade their Subversion repository from 1.7 to 1.8.  The steps involved, if everything goes according to plan, are:

1. Dump the repository:

   svnadmin dump repo1_7 > repo1_7.dump

   Or you can reduce the dump size and calculate the deltas between revisions and only dump them:

   svnadmin dump --deltas repo1_7 > repo1_7.dump

2. Create the new repository, which by default uses the fsfs file system:

   svnadmin create repo1_8

3. If you need to transfer the dump file to a new host you should take care of that first but then you need load the dump:

   svnadmin load repo1_8 < repo1_7.dump

Now that would generally be it as far as the repository itself is concerned, unless you get errors.  I got errors and it is not uncommon when upgrading.  I ran into issue on step 3, loading the dump file.  It ran for about 2,000+ revisions and then stopped with these errors:

   Cannot accept non-LF line endings in 'svn:log' property

   Cannot accept non-LF line endings in 'svn:ignore' property

This occurred because the repository contained the older ^M carriage return.  This is no longer allowed after version 1.6 but the previous upgrades used the"--bypass-prop-validation" option when loading the repository which just delayed dealing with the issue.  The fix for this is to replace the ^M line endings found in the repository.  To do this you take your dump file you created in step 1 and use the following sed command to replace the ^M line endings.

   sed -e '/^svn:log$/,/^PROPS-END$/ s/^M/ /' -e '/^svn:ignore$/,/^PROPS-END$/ s/^M/\n/' repo1_7.dump > repo1_7-fix.dump

Now I want to make note that the ^M in the command above is not created with Shift+6 and Shift+M.  The ^M character is a carriage return control character that means 0D in hex.  In order to create the character you can either type CTRL+V and CTRL+M or reference it as \x0D in the sed command as shown below.

   sed -e '/^svn:log$/,/^PROPS-END$/ s/\x0D/ /' -e '/^svn:ignore$/,/^PROPS-END$/ s/\x0D/\n/' repo1_7.dump > repo1_7-fix.dump

Once that command finishes you will have repaired copy of the dump file which should load now.


Configuring Jenkins to use HTTPS on CentOS 6.6

These instructions are using Jenkins 1.595 from the Jenkins Yum repository http://pkg.jenkins-ci.org/redhat/
  1. Create certificate for host with whatever tool you choose.  Personally I like XCA but I don't have a PKI system in place.

  2. Export PKCS12 certificate with chain.

  3. Convert PKCS12 certifcate to java keystore using the following command:
    keytool -importkeystore -srckeystore certificate.p12 -srcstoretype PKCS12 -destkeystore jenkinsstore

  4. Copy the keystore to a permanent location (ex. /var/lib/jenkins).

  5. Import your CA certificate into Java cacerts keystore:
    keytool -import -file CA.crt -keystore /usr/java/latest/jre/lib/security/cacerts

  6. Configure /etc/sysconfig/jenkins with the following settings:
    JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Xrs -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m"

  7. Configure iptables to redirect 443 to 8843 and to block tcp 8080 if you want to use the standard port 443:
    -A INPUT -i eth0 -p tcp -m tcp --dport 8080 -j DROP
    -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8843

  8. Start Jenkins:
    service jenkins start


Quick OpenLDAP Setup on CentOS 6.6

  1. Install the necessary files:
    yum install openldap openldap-clients openldap-servers
  2. Modify the following options in the /etc/openldap/slapd.d/cn\=config.ldif configuration file:
    #olcAllows: bind_v2  
    olcIdleTimeout: 60
  3. Generate the SSHA hash for the admin user:
    slappasswd -s password
    (example output: {SSHA}abunchofhash)
  4. Modify the following configuration options in /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}bdb.ldif. The domain will be test.com
    olcSuffix: dc=test,dc=com
    olcRootDN: cn=admin,dc=test,dc=com
    olcRootPW: {SSHA}abunchofhash
  5. Modify the olcAccess option in /etc/openldap/slapd.d/cn\=config/olcDatabase={1}monitor.ldif so the dn is correct:
    olcAccess: {0}to *  by/ dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth"/
    read  by dn.base="cn=admin,dc=test,dc=com" read  by * none
  6. Start the OpenLDAP server and configure it to start at boot time:
    chkconfig slapd on
    service slapd start
  7. Create an LDIF (LDAP Interchange Format) file with the configuration for our organization LDAP tree. Here we will create two organizational units one called People, where all users be a member of this ou, and another ou called Groups, which will be used to create groups for our organization. At the end of the file specify who is the RootDN for this LDAP tree (cn=admin,dc=example,dc=com).  I named this file ldapconfig.ldif:
    dn: dc=test,dc=com
    objectclass: dcObject
    objectclass: organization
    o: Test Org
    dc: test
    dn: ou=Users,dc=test,dc=com
    objectClass: organizationalUnit
    objectClass: top
    ou: Users
    dn: ou=Groups,dc=test,dc=com
    objectClass: organizationalUnit
    objectClass: top
    ou: Groups
    dn: cn=admin,dc=test,dc=com
    objectclass: organizationalRole
    cn: admin
  8. Apply our LDIF file and test if the LDAP tree is ready with the ldapsearch command:
    ldapadd -x -D "cn=admin,dc=test,dc=com" -W -f ldapconfig.ldif
    ldapsearch -x -b 'dc=test,dc=com' '(objectclass=*)'
  9. Create an ldap user by adding the below to an ldif file and running ldapadd as above:
    dn: uid=user1,ou=Users,dc=test,dc=com
    objectclass: top
    objectclass: person
    objectclass: inetOrgPerson
    objectclass: organizationalPerson
    uid: user1
    cn: User 1
    sn: 1
    givenName: User 1
  10. Assign a password for the user:
    ldappasswd -S -x -D "cn=admin,dc=test,dc=com" -W/ uid=user1,ou=People,dc=test,dc=com
  11. Create a group in the Groups organizational unit by adding the below to an ldif file and running ldapadd as above:
    dn: cn=group1,ou=Groups,dc=test,dc=com
    cn: group1

    objectclass: groupofnames
    member: uid=user1,ou=Users,dc=test,dc=com
  12. To add a newly created user to the group after the initial creation create another ldif file and add the below text to it.  Then modify the group with ldapmodify:
    dn: cn=group1,ou=Groups,dc=test,dc=com
    changetype: modify
    add: member
    member: uid=user2,ou=Users,dc=test,dc=com

    ldapmodify -x -D "cn=admin,dc=test,dc=com" -W -f addto_group1.ldif
  13. To remove a user from a group create another ldif file and add the below text.  Use ldapmodify to again modify the group:
    dn: cn=group1,ou=Groups,dc=test,dc=com
    changetype: modify
    delete: member
    member: uid=user2,ou=Users,dc=test,dc=com

    ldapmodify -x -D "cn=admin,dc=test,dc=com" -W -f removefrom_group1.ldif


Generating GPG Keys on CentOS 6

I recently ran into an issue where I was having problems creating a new set of GPG keys on a CentOS host that I was using.  Here is the process that eventually worked for me.

1. Run the following gpg-agent command:

gpg-agent --daemon --use-standard-socket --pinentry-program /usr/bin/pinentry-curses

2. Run the following rngd command to ensure there is enough entropy being generated:

sudo rngd -r /dev/urandom

3. Finally run the gpg command to generate the key:

gpg --gen-key

If you are running the gpg-agent as root you may run into other issue that prevent you from completing the process.  It is best to run as a non-root user.



Java Keystore Import Error

When trying I started recieveing the following error:

keytool error: java.lang.Exception: Input not an X.509 certificate

My certificate was in the .pem format and all that I had to do was convert the certificate using the following command:

openssl x509 -outform der -in mycert.pem -out mycert.der

Then I was able to import the certificate using:

keytool -keystore /location/of/keystore -import -alias mycertalias -file mycert.der


XCA Certificate Authority

After much searching and testing various Linux GUI certificate authority applications I finally found one that works consistently and gives me all of the options that I need.  I am not exactly sure how I missed it as it has been out for some time but XCA has turned out to be exactly what I was looking for.  The biggest issue I had was creating certificates for Windows Servers in order to setup LDAPS.  I had used TinyCA2, GnoMint, and various others.  Both were either limited in their capabilities or failed to work consistently.  I even tried to go setup full PKI systems like EJBCA and Windows Certificate Services but found them to be to difficult to pick up in the limited amount of time I had to learn how to use it.

XCA uses a Qt based GUI interface that is well organized and full featured.  I found the ability to create templates a great time saver when you have to crank out lots of certificates. Plus the ability to export to any format is also very handy as sometimes I never know what I need and I can never remember the correct openssl commands to convert to different formats.

Importing Key and Certificate into Java Keystore

For whatever reason I had a hell of a time trying to import the key and certificate from a third party CA into a Java keystore (JKS) that was used by a java web application.  I just kept finding incorrect steps on how to do it and then after about 3 days of monkeying around with it I finally found what worked.  

The first step was to export the key and certificate into PKCS12 format (either .pfx or .p12 file extension).  The keytool treats the PKCS12 file as a keystore.  If you are using Tomcat or some other Java application server you can actually use the file as a keystore without importing it into a JKS. The keytool gives you the ability to merge keystores which is what I ended up doing.  After several attempts the below command was what I ended up with.

keytool -importkeystore -destkeystore /certs/my.javakeystore -srckeystore certAndKey.p12  -srcstoretype PKCS12

I tried several times with the -alias option and it kept failing giving this error:

keytool error: java.lang.Exception: Alias <alias1> does not exist

I found that the alias that is used initially is in the PKCS12 file.  If the alias you are using does not match up to the alias, which I am assuming is the internal or friendly name, then it will fail.  So if you leave the alias option off then it will import using the default alias that is sees in the PKCS12 file.  In my case it was identical to one I had in my keystore already and it let me change the alias name during the import process.