EJBCA auf Odroid XU3 installieren

Submitted by admin on So, 11.12.2016 - 11:10

1455958538385-ejbca_pki_by_primekey_logo.png

EJBCA ist eine sehr leistungsfähige PKI Lösung, die auch für sehr große Installationen geeignet ist. Es spricht allerdings nichts dagegen, diese Lösung auf einem Odroid XU3 zu installieren. Mit einem Raspberry wird es dagegen bei der Performace schon etwas eng.

Exkurs: Smartcard-HSM

Da ein Utimaco[1] HSM zu teuer war, wurde Smartcard-HSM verwendet, das für dieses Projekt durchaus ausreichend war. Ein Reiner SCT Cyberjack, der irgendwo einmal übrig geblieben ist, dient als Interface zur Smartcard, weil der auch Extended-APDUs unterstützt. Der Odroid XU3 hat eine zu schwache Stromversorgung auf dem USB Port, daher wurde zwischen Cyberjack und dem Odroid XU3 ein aktiver USB Hub zwischengeschaltet.

Damit die Smartcard als HSM arbeiten kann, müssen folgende Pakete installiert werden:

  • libifd-cyberjack6
  • opensc

EJBCA kann als HSM praktisch alles verwenden, was von OpenSC unterstützt wird und stabil läuft. Von dem FEITIAN ePass2003 muss aus diesem Grund dringend abgeraten werden, das Ding produziert ständig Hänger. Die Smartcard-HSM läuft dagegen absolut stabil. Der SmartCard-HSM USB Stick ist für den Odroid XU3 ebenfalls nicht zu empfehlen, er wird schlicht und einfach nicht erkannt, was aber offenbar an dem Odroid liegt.

Damit Auto Activation in EJBCA funktioniert, muss in der Datei /etc/opensc/opensc.conf enable_pinpad = false; gesetzt werden, sonst fragt der Cyberjack nach der PIN Eingabe über das Pinpad. In entsprechenden Fällen kann das natürlich erwünscht sein.

Java

Damit EJBCA funktionieren kann sind folgende Pakete zu installieren:

  • oracle-java8-jdk
  • ant
  • mysql-server

was mit aptitude install oracle-java8-jdk ant mysql-server schnell erledigt ist.

Ansonsten ist nach https://www.ejbca.org/docs/installation.html zu verfahren. Die Anleitung muss peinlich genau befolgt werden, sonst funktioniert die Installation nicht.

In der web.properties muss OpenSC/Smartcard-HSM noch bekannt gemacht werden, beim Odroid Linux mit

cryptotoken.p11.lib.60.name=OpenSC
cryptotoken.p11.lib.60.file=/usr/lib/arm-linux-gnueabihf/opensc-pkcs11.so

Nützliche Skripte

Zunächst sollte im Homeverzeichnis des ejbca Users das Verzeichnis ejbca-custom mit den Unterverzeichnissen

  • conf
  • modules
  • p12

erstellt werden. Zunächst muss nur das Verzeichnis conf davon befüllt werden. Dort finden die ganzen EJBCA Config Files ihren Platz. Im Rahmen der Installation werden diese Configs dann in das ejbca/config Verzeichnis kopiert. Sehr praktisch, wenn man die Installation wiederholen muss.

setup.mysql.sh

Dieses Skript installiert nicht nur das mysql Modul in JBoss, sondern nimmt noch ein paar nützliche Einstellung, wie z.B. AJP vor.

#!/bin/sh

MYSQL_JBOSS_DIR="modules/com/mysql/main"

cd jboss || exit 1
mkdir -p "$MYSQL_JBOSS_DIR"
cd "$MYSQL_JBOSS_DIR" || exit 1

cp "/home/ejbca/Download/mariadb-java-client-1.2.3.jar" .
cat <<EOF > module.xml
<?xml version="1.0" encoding="UTF-8"?>
 
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
  <resources>
    <resource-root path="mariadb-java-client-1.2.3.jar"/>
  </resources>
  <dependencies>
    <module name="javax.api"/>
  </dependencies>
</module>
EOF

cd "/home/ejbca/jboss/standalone/configuration" || exit 1

cat <<EOF | patch -p0
--- standalone.xml.XXX	2015-03-27 14:26:24.000000000 +0100
+++ standalone.xml	2016-02-16 10:37:55.537404590 +0100
@@ -136,6 +136,7 @@
                     </security>
                 </datasource>
                 <drivers>
+                    <driver name="com.mysql" module="com.mysql"/>
                     <driver name="h2" module="com.h2database.h2">
                         <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                     </driver>
@@ -289,6 +290,7 @@
             <coordinator-environment default-timeout="300"/>
         </subsystem>
         <subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false">
+            <connector name="ajp" protocol="AJP/1.3" scheme="http" socket-binding="ajp"/>
             <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
             <virtual-server name="default-host" enable-welcome-root="true">
                 <alias name="localhost"/>
@@ -338,4 +340,4 @@
             <remote-destination host="localhost" port="25"/>
         </outbound-socket-binding>
     </socket-binding-group>
-</server>
\ No newline at end of file
+</server>
EOF

Dieses Skript muss vor der Installation von EJBCA ausgeführt werden.

/etc/init.d/ejbca

Spätestens, wenn man EJBCA produktiv nutzen will, ist ein Start-/Stop-Skript nützlich. Das Skript muss je nach EJBCA Installation noch angepasst werden.

#! /bin/sh
### BEGIN INIT INFO
# Provides:          ejbca
# Required-Start:    $network $remote_fs $syslog $mysql
# Required-Stop:     $network $remote_fs $syslog $mysql
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: ejbca
# Description:       ejbca pki
### END INIT INFO

# Author: Foo Bar <foobar@baz.org>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="ejbca pki"

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started
	cd /home/ejbca || return 2
	#start-stop-daemon --start --quiet --user ejbca --group ejbca --startas /home/ejbca \
	#	--background --exec /home/ejbca/jboss/bin/standalone.sh -- -b 127.0.0.1 || return 2
	start-stop-daemon --start --user ejbca --group ejbca --chdir /home/ejbca \
		--background --exec /home/ejbca/jboss/bin/standalone.sh -- -b 127.0.0.1 || return 2
	# Add code here, if necessary, that waits for the process to be ready
	# to handle requests from services started subsequently which depend
	# on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   2 if daemon could not be stopped
	#   other if a failure occurred
	cd /home/ejbca || return 2
	su -c "jboss/bin/jboss-cli.sh --connect 'command=:shutdown'" ejbca
	RETVAL="$?"
	return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
	#
	# If the daemon can reload its configuration without
	# restarting (for example, when it is sent a SIGHUP),
	# then implement that here.
	#
	RETVAL=0
	cd /home/ejbca || return 2
	su -c "jboss/bin/jboss-cli.sh --connect 'command=:reload'" ejbca
	if [ $? -ne 0 ]; then
		RETVAL=2
	fi
	return $RETVAL
}

do_status() {
	RETVAL=0
	cd /home/ejbca || return 2
	su -c "jboss/bin/jboss-cli.sh --connect 'command=:read-attribute(name=server-state)'" ejbca | grep -E 'success|$'
	if [ $? -ne 0 ]; then
		RETVAL=2
	fi
	return $RETVAL
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "ejbca"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "ejbca"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  status)
	log_daemon_msg "Status $DESC" "ejbca"
	do_status
	log_end_msg $?
	;;
  reload|force-reload)
	#
	# If do_reload() is not implemented then leave this commented out
	# and leave 'force-reload' as an alias for 'restart'.
	#
	log_daemon_msg "Reloading $DESC" "ejbca"
	do_reload
	log_end_msg $?
	;;
  restart|force-reload)
	#
	# If the "reload" option is implemented then remove the
	# 'force-reload' alias
	#
	log_daemon_msg "Restarting $DESC" "ejbca"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;; # Old process is still running
			*) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
		# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
	exit 3
	;;
esac

:

[1] stellt auch Produkte für lawful interception her.