diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..41681b7
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,101 @@
+FROM bigfleet/shibboleth_sp
+
+# Define args and set a default value
+ARG registry=docker.io
+ARG maintainer=tier
+ARG imagename=comanage
+ARG version=1.0.5
+
+MAINTAINER $maintainer
+LABEL Vendor="Internet2"
+LABEL ImageType="COmanage"
+LABEL ImageName=$imagename
+LABEL ImageOS=centos7
+LABEL Version=$version
+
+LABEL Build docker build --rm --tag $registry/$maintainer/$imagename .
+
+# Install deps
+RUN yum -y install --setopt=tsflags=nodocs \
+ httpd \
+ mariadb \
+ mysql-devel \
+ mysql-libs \
+ mod_ssl \
+ php \
+ php-openssl \
+ php-cli \
+ php-ldap \
+ php-mbstring \
+ php-mcrypt \
+ php-mysql \
+ php-pear-MDB2-Driver-mysqli \
+ php-pecl-memcached \
+ php-xml \
+ vim && yum -y clean all
+
+#
+# Global PHP configuration changes
+#
+RUN sed -i \
+ -e 's~^;date.timezone =$~date.timezone = Europe/Rome~g' \
+ -e 's~^;user_ini.filename =$~user_ini.filename =~g' \
+ /etc/php.ini
+
+RUN echo '' > /var/www/html/index.php
+
+ENV VERSION=$version
+ENV COMANAGE_URL=https://github.com/Internet2/comanage-registry/archive/$VERSION.tar.gz
+ENV COMANAGE_PREFIX=comanage-registry
+
+RUN mkdir -p /tmp/comanage && cd /tmp/comanage && \
+ wget -q $COMANAGE_URL && \
+# Perform verifications [TODO]
+# Prepare filesystem
+ mkdir -p /opt/comanage && \
+ tar xf $VERSION.tar.gz && \
+ mv $COMANAGE_PREFIX-$VERSION /opt/comanage/. && \
+ ln -s /opt/comanage/$VERSION /opt/comanage/current && \
+# # Cleanup
+ rm -rf /tmp/comanage
+
+ENV COMANAGE_HOME /opt/comanage/current
+
+WORKDIR $COMANAGE_HOME
+
+# Add starters and installers
+ADD ./container_files /opt
+
+# Add Volumes and Set permissions
+RUN mkdir /opt/shared \
+ && chmod 777 /opt/shared \
+ && chmod 777 /opt/bin/*.sh
+
+# Environment variables
+ENV ADMIN_NAME "Scott"
+ENV ADMIN_FAMILY "Koranda"
+ENV ADMIN_USERNAME "scott.koranda@sphericalcowgroup.com"
+ENV COMANAGE_SERVER_FQDN "comanage.testbed.tier.internet2.edu"
+ENV COMANAGE_MAIL_FROM "comanage_registry@picard.cgac.uwm.edu"
+ENV COMANAGE_MAIL_HOST "localhost"
+ENV COMANAGE_MAIL_PORT "25"
+ENV COMANAGE_MAIL_USER "user"
+ENV COMANAGE_MAIL_PASS "secret"
+ENV MYSQL_HOST "i2mariadb"
+ENV MYSQL_DATABASE "registry"
+ENV MYSQL_USER "registry_user"
+ENV MYSQL_PASSWORD "WJzesbe3poNZ91qIbmR7"
+ENV TERM "testterm"
+# How long will we wait for MariaDB to start up?
+ENV WAIT_TIME 60
+
+# Required volumes for mounting Shibboleth SSL files into container
+VOLUME /opt/shibboleth/ssl/
+
+# Required volumes for mounting Apache SSL files into container
+VOLUME /opt/httpd/ssl/
+
+# Port
+EXPOSE 80 443
+
+CMD ["/opt/bin/start.sh"]
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
index fbb9f16..9f6a1c0 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,45 +1,71 @@
-node {
+node('docker') {
stage 'Checkout'
checkout scm
-
+
stage 'Acquire util'
- sh 'mkdir -p bin'
- dir('bin'){
+ sh 'mkdir -p tmp && mkdir -p bin'
+ dir('tmp'){
git([ url: "https://github.internet2.edu/docker/util.git",
credentialsId: "jenkins-github-access-token" ])
- sh 'ls'
- sh 'mv bin/* .'
+ sh 'mv ./bin/* ../bin/.'
}
-
- stage 'Build'
-
+ sh 'rm -rf tmp'
+
+ stage 'Setting build context'
+
def maintainer = maintainer()
def imagename = imagename()
- def tag = env.BRANCH_NAME
+ def tag
+
+ // Tag images created on master branch with 'latest'
+ if(env.BRANCH_NAME == "master"){
+ tag = "latest"
+ }else{
+ tag = env.BRANCH_NAME
+ }
+
if(!imagename){
echo "You must define an imagename in common.bash"
currentBuild.result = 'FAILURE'
+ }
+ if(maintainer){
+ echo "Building ${imagename}:${tag} for ${maintainer}"
+ }
+
+ stage 'Build'
+ try{
+ sh 'bin/rebuild.sh &> debug'
+ } catch(error) {
+ def error_details = readFile('./debug');
+ def message = "BUILD ERROR: There was a problem building ${imagename}:${tag}. \n\n ${error_details}"
+ sh "rm -f ./debug"
+ handleError(message)
}
- if(maintainer){
- echo "Building ${maintainer}:${tag} for ${maintainer}"
- }
-
- sh 'bin/build.sh'
stage 'Tests'
- sh 'bin/test.sh'
+ try{
+ sh 'bin/test.sh &> debug'
+ } catch(error) {
+ def error_details = readFile('./debug');
+ def message = "BUILD ERROR: There was a problem building ${imagename}:${tag}. \n\n ${error_details}"
+ sh "rm -f ./debug"
+ handleError(message)
+ }
stage 'Push'
-
+
docker.withRegistry('https://registry.hub.docker.com/', "dockerhub-$maintainer") {
def baseImg = docker.build("$maintainer/$imagename")
baseImg.push("$tag")
}
+ stage 'Notify'
+
+ slackSend color: 'good', message: "$maintainer/$imagename:$tag pushed to DockerHub"
}
@@ -51,4 +77,12 @@ def maintainer() {
def imagename() {
def matcher = readFile('common.bash') =~ 'imagename="(.+)"'
matcher ? matcher[0][1] : null
+}
+
+def handleError(String message){
+ echo "${message}"
+ currentBuild.setResult("FAILED")
+ slackSend color: 'danger', message: "${message}"
+ //step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'chris.bynum@levvel.io', sendToIndividuals: true])
+ sh 'exit 1'
}
\ No newline at end of file
diff --git a/common.bash b/common.bash
index 55b3596..79fd23f 100644
--- a/common.bash
+++ b/common.bash
@@ -1,2 +1,3 @@
maintainer="bigfleet"
-imagename="comanage"
\ No newline at end of file
+imagename="comanage"
+version="1.0.5"
\ No newline at end of file
diff --git a/container_files/bin/cleanup.sh b/container_files/bin/cleanup.sh
new file mode 100755
index 0000000..a9bf588
--- /dev/null
+++ b/container_files/bin/cleanup.sh
@@ -0,0 +1 @@
+#!/bin/bash
diff --git a/container_files/bin/configure.sh b/container_files/bin/configure.sh
new file mode 100755
index 0000000..afc0de0
--- /dev/null
+++ b/container_files/bin/configure.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+/opt/bin/configure_httpd.sh
+
+/opt/bin/configure_php.sh
+
+/opt/bin/configure_shibd.sh
+
+
diff --git a/container_files/bin/configure_http.sh b/container_files/bin/configure_http.sh
new file mode 100755
index 0000000..d94aafe
--- /dev/null
+++ b/container_files/bin/configure_http.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+log="/tmp/httpd.log"
+
+echo "Configuring httpd: " > $log
\ No newline at end of file
diff --git a/container_files/bin/configure_php.sh b/container_files/bin/configure_php.sh
new file mode 100755
index 0000000..0a8ecd1
--- /dev/null
+++ b/container_files/bin/configure_php.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+log="/tmp/php.log"
+
+echo "Configuring php: " > $log
+
+
diff --git a/container_files/bin/configure_shibd.sh b/container_files/bin/configure_shibd.sh
new file mode 100755
index 0000000..fa698f4
--- /dev/null
+++ b/container_files/bin/configure_shibd.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+log="/tmp/shibd.log"
+
+echo "Configuring shibd: " > $log
+
+
diff --git a/container_files/bin/main.sh b/container_files/bin/main.sh
new file mode 100755
index 0000000..1f49896
--- /dev/null
+++ b/container_files/bin/main.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -x
+
+log="/tmp/start-main.log"
+
+echo "Starting Container: " > $log
+date >> $log
+echo "" >> $log
+
+if [ -e "/tmp/firsttimerunning" ]; then
+
+ set -e
+
+ /opt/bin/configure.sh >> $log
+
+ /opt/bin/cleanup.sh >> $log
+
+else
+ echo "COmanage container has run." >> $log
+ echo "If there are problems, docker rm this container and try again." >> $log
+fi
\ No newline at end of file
diff --git a/container_files/bin/start.sh b/container_files/bin/start.sh
new file mode 100755
index 0000000..be61c62
--- /dev/null
+++ b/container_files/bin/start.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+log="/tmp/start-starting.log"
+date >> $log
+if [ -z ${COMPOSE+x} ]
+then
+ echo "Not composed so not waiting for MariaDB: " > $log
+ /opt/bin/main.sh
+ laststatus="$?"
+ echo "Not composed status: $laststatus"
+ if [ "$laststatus" != "0" ]; then
+ echo "Not composed non-zero exit status: $laststatus" >> $log
+ echo "Not composed non-zero exit status: $laststatus"
+ exit 1
+ else
+ echo "COmanage was configured" >>$log
+ echo "COmanage was configured"
+ echo "Starting apache" >>$log
+ echo "Starting apache"
+ /usr/local/bin/httpd-shib-foreground &
+ fi
+else
+ echo "Composed so waiting for MariaDB: " > $log
+ date >> $log
+ echo "Testing connectivity to database before continue with install" >> $log
+ echo "Testing connectivity to database before continue with install"
+ /opt/wait-for-it/wait-for-it.sh $MYSQL_HOST:3306 -t $WAIT_TIME --strict -- /opt/bin/main.sh
+
+ date >> $log
+ echo "Starting apache" >>$log
+ echo "Starting apache"
+ /usr/local/bin/httpd-shib-foreground &
+fi
\ No newline at end of file
diff --git a/container_files/etc/httpd/conf.d/comanage.conf b/container_files/etc/httpd/conf.d/comanage.conf
new file mode 100644
index 0000000..0b8e83a
--- /dev/null
+++ b/container_files/etc/httpd/conf.d/comanage.conf
@@ -0,0 +1,107 @@
+Listen 80 http
+Listen 443 https
+
+AddType text/html .php
+php_value session.save_handler "files"
+php_value session.save_path "/var/lib/php/session"
+
+LoadModule mod_shib /usr/lib64/shibboleth/mod_shib_24.so
+
+
+ServerName http://COMANAGE_SERVER_FQDN:80
+UseCanonicalName On
+RedirectMatch (.*) https://COMANAGE_SERVER_FQDN$1
+
+
+SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
+SSLSessionCache shmcb:/run/httpd/sslcache(512000)
+SSLSessionCacheTimeout 300
+SSLRandomSeed startup file:/dev/urandom 256
+SSLRandomSeed connect builtin
+SSLCryptoDevice builtin
+
+
+ServerName https://COMANAGE_SERVER_FQDN:443
+UseCanonicalName On
+Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
+
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+CustomLog logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
+
+ErrorLog logs/ssl_error_log
+TransferLog logs/ssl_access_log
+LogLevel warn
+
+SSLEngine on
+SSLProtocol all -SSLv2 -SSLv3
+SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
+SSLHonorCipherOrder on
+SSLCompression off
+SSLCertificateFile /opt/httpd/ssl/CHANGE_TO_SSL_HTTPD_CERT
+SSLCertificateKeyFile /opt/httpd/ssl/CHANGE_TO_SSL_HTTPD_KEY
+
+# Optional parameter that will only be uncommented on initialization
+# if the file exists:
+#SSLCertificateChainFile CHANGE_TO_SSL_HTTPD_CHAIN
+
+BrowserMatch "MSIE [2-5]" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+
+
+
+ AllowOverride none
+ Require all denied
+
+
+DocumentRoot "/var/www/html"
+
+
+ AllowOverride None
+ Require all granted
+
+
+
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+
+
+
+ Options Indexes FollowSymLinks MultiViews
+ DirectoryIndex index.php
+ AllowOverride All
+ Require all granted
+
+
+ShibCompatValidUser Off
+
+ AuthType None
+ Require all granted
+
+
+
+ AuthType None
+ Require all granted
+
+Alias /shibboleth-sp/main.css /usr/share/shibboleth/main.css
+
+
+ AuthType shibboleth
+ ShibRequestSetting requireSession 1
+ Require shib-session
+
+
+Redirect "/registry/users/logout" "https://COMANAGE_SERVER_FQDN/Shibboleth.sso/Logout?return=https%3A//COMANAGE_SERVER_FQDN/registry/"
+
+
+ SetHandler application/x-httpd-php
+
+
+
+ Require all denied
+
+
+
+
diff --git a/container_files/etc/php/EmailShell.php b/container_files/etc/php/EmailShell.php
new file mode 100644
index 0000000..0bb978d
--- /dev/null
+++ b/container_files/etc/php/EmailShell.php
@@ -0,0 +1,41 @@
+emailFormat('text')
+ ->to('skoranda@uwm.edu')
+ ->subject('test')
+ ->send('Hello');
+
+ $email->send();
+
+ }
+}
diff --git a/container_files/etc/php/database.php b/container_files/etc/php/database.php
new file mode 100644
index 0000000..114d41e
--- /dev/null
+++ b/container_files/etc/php/database.php
@@ -0,0 +1,83 @@
+ The name of a supported datasource; valid options are as follows:
+ * Database/Mysql - MySQL 4 & 5,
+ * Database/Sqlite - SQLite (PHP5 only),
+ * Database/Postgres - PostgreSQL 7 and higher,
+ * Database/Sqlserver - Microsoft SQL Server 2005 and higher
+ *
+ * You can add custom database datasources (or override existing datasources) by adding the
+ * appropriate file to app/Model/Datasource/Database. Datasources should be named 'MyDatasource.php',
+ *
+ *
+ * persistent => true / false
+ * Determines whether or not the database should use a persistent connection
+ *
+ * host =>
+ * the host you connect to the database. To add a socket or port number, use 'port' => #
+ *
+ * prefix =>
+ * Uses the given prefix for all the tables in this database. This setting can be overridden
+ * on a per-table basis with the Model::$tablePrefix property.
+ *
+ * schema =>
+ * For Postgres specifies which schema you would like to use the tables in. Postgres defaults to 'public'.
+ *
+ * encoding =>
+ * For MySQL, Postgres specifies the character encoding to use when connecting to the
+ * database. Uses database default not specified.
+ *
+ * unix_socket =>
+ * For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port`
+ */
+class DATABASE_CONFIG {
+
+ public $default = array(
+ 'datasource' => 'Database/Mysql',
+ 'persistent' => false,
+ 'host' => 'CHANGE_TO_ENV_MYSQL_HOST',
+ 'login' => 'CHANGE_TO_ENV_MYSQL_USERNAME',
+ 'password' => 'CHANGE_TO_ENV_MYSQL_PASSWORD',
+ 'database' => 'CHANGE_TO_ENV_MYSQL_TABLE',
+ 'prefix' => 'cm_',
+ //'encoding' => 'utf8',
+ );
+
+ public $test = array(
+ 'datasource' => 'Database/Mysql',
+ 'persistent' => false,
+ 'host' => 'CHANGE_TO_ENV_MYSQL_HOST',
+ 'login' => 'CHANGE_TO_ENV_MYSQL_USERNAME',
+ 'password' => 'CHANGE_TO_ENV_MYSQL_PASSWORD',
+ 'database' => 'CHANGE_TO_ENV_MYSQL_TABLE',
+ 'prefix' => 'cm_',
+ //'encoding' => 'utf8',
+ );
+}
diff --git a/container_files/etc/php/email.php b/container_files/etc/php/email.php
new file mode 100644
index 0000000..9260909
--- /dev/null
+++ b/container_files/etc/php/email.php
@@ -0,0 +1,101 @@
+ The name of a supported transport; valid options are as follows:
+ * Mail - Send using PHP mail function
+ * Smtp - Send using SMTP
+ * Debug - Do not send the email, just return the result
+ *
+ * You can add custom transports (or override existing transports) by adding the
+ * appropriate file to app/Network/Email. Transports should be named 'YourTransport.php',
+ * where 'Your' is the name of the transport.
+ *
+ * from =>
+ * The origin email. See CakeEmail::from() about the valid values
+ *
+ */
+class EmailConfig {
+
+ public $default = array(
+ 'transport' => 'Smtp',
+ 'from' => 'CHANGE_TO_COMANAGE_MAIL_FROM',
+ 'host' => 'CHANGE_TO_COMANAGE_MAIL_HOST',
+ 'port' => CHANGE_TO_COMANAGE_MAIL_PORT,
+ 'username' => 'CHANGE_TO_COMANAGE_MAIL_USER',
+ 'password' => 'CHANGE_TO_COMANAGE_MAIL_PASS'
+ //'charset' => 'utf-8',
+ //'headerCharset' => 'utf-8',
+ );
+
+ public $smtp = array(
+ 'transport' => 'Smtp',
+ 'from' => array('site@localhost' => 'My Site'),
+ 'host' => 'localhost',
+ 'port' => 25,
+ 'timeout' => 30,
+ 'username' => 'user',
+ 'password' => 'secret',
+ 'client' => null,
+ 'log' => false
+ //'charset' => 'utf-8',
+ //'headerCharset' => 'utf-8',
+ );
+
+ public $fast = array(
+ 'from' => 'you@localhost',
+ 'sender' => null,
+ 'to' => null,
+ 'cc' => null,
+ 'bcc' => null,
+ 'replyTo' => null,
+ 'readReceipt' => null,
+ 'returnPath' => null,
+ 'messageId' => true,
+ 'subject' => null,
+ 'message' => null,
+ 'headers' => null,
+ 'viewRender' => null,
+ 'template' => false,
+ 'layout' => false,
+ 'viewVars' => null,
+ 'attachments' => null,
+ 'emailFormat' => null,
+ 'transport' => 'Smtp',
+ 'host' => 'localhost',
+ 'port' => 25,
+ 'timeout' => 30,
+ 'username' => 'user',
+ 'password' => 'secret',
+ 'client' => null,
+ 'log' => true,
+ //'charset' => 'utf-8',
+ //'headerCharset' => 'utf-8',
+ );
+
+}
diff --git a/container_files/etc/shibboleth/attribute-map.xml b/container_files/etc/shibboleth/attribute-map.xml
new file mode 100644
index 0000000..12c4019
--- /dev/null
+++ b/container_files/etc/shibboleth/attribute-map.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/container_files/etc/shibboleth/inc-md-cert.pem b/container_files/etc/shibboleth/inc-md-cert.pem
new file mode 100644
index 0000000..5ec4ec6
--- /dev/null
+++ b/container_files/etc/shibboleth/inc-md-cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIJAJRJzvdpkmNaMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV
+BAYTAlVTMRUwEwYDVQQKDAxJbkNvbW1vbiBMTEMxMTAvBgNVBAMMKEluQ29tbW9u
+IEZlZGVyYXRpb24gTWV0YWRhdGEgU2lnbmluZyBLZXkwHhcNMTMxMjE2MTkzNDU1
+WhcNMzcxMjE4MTkzNDU1WjBXMQswCQYDVQQGEwJVUzEVMBMGA1UECgwMSW5Db21t
+b24gTExDMTEwLwYDVQQDDChJbkNvbW1vbiBGZWRlcmF0aW9uIE1ldGFkYXRhIFNp
+Z25pbmcgS2V5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Chdkrn+
+dG5Zj5L3UIw+xeWgNzm8ajw7/FyqRQ1SjD4Lfg2WCdlfjOrYGNnVZMCTfItoXTSp
+g4rXxHQsykeNiYRu2+02uMS+1pnBqWjzdPJE0od+q8EbdvE6ShimjyNn0yQfGyQK
+CNdYuc+75MIHsaIOAEtDZUST9Sd4oeU1zRjV2sGvUd+JFHveUAhRc0b+JEZfIEuq
+/LIU9qxm/+gFaawlmojZPyOWZ1JlswbrrJYYyn10qgnJvjh9gZWXKjmPxqvHKJcA
+TPhAh2gWGabWTXBJCckMe1hrHCl/vbDLCmz0/oYuoaSDzP6zE9YSA/xCplaHA0mo
+C1Vs2H5MOQGlewIDAQABo1AwTjAdBgNVHQ4EFgQU5ij9YLU5zQ6K75kPgVpyQ2N/
+lPswHwYDVR0jBBgwFoAU5ij9YLU5zQ6K75kPgVpyQ2N/lPswDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAaQkEx9xvaLUt0PNLvHMtxXQPedCPw5xQBd2V
+WOsWPYspRAOSNbU1VloY+xUkUKorYTogKUY1q+uh2gDIEazW0uZZaQvWPp8xdxWq
+Dh96n5US06lszEc+Lj3dqdxWkXRRqEbjhBFh/utXaeyeSOtaX65GwD5svDHnJBcl
+AGkzeRIXqxmYG+I2zMm/JYGzEnbwToyC7yF6Q8cQxOr37hEpqz+WN/x3qM2qyBLE
+CQFjmlJrvRLkSL15PCZiu+xFNFd/zx6btDun5DBlfDS9DG+SHCNH6Nq+NfP+ZQ8C
+GzP/3TaZPzMlKPDCjp0XOQfyQqFIXdwjPFTWjEusDBlm4qJAlQ==
+-----END CERTIFICATE-----
diff --git a/container_files/etc/shibboleth/shibboleth2.xml b/container_files/etc/shibboleth/shibboleth2.xml
new file mode 100644
index 0000000..ab4445c
--- /dev/null
+++ b/container_files/etc/shibboleth/shibboleth2.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+ SAML2
+
+
+ SAML2 Local
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ http://refeds.org/category/hide-from-discovery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/container_files/etc/shibboleth/shibboleth_keygen.sh b/container_files/etc/shibboleth/shibboleth_keygen.sh
new file mode 100755
index 0000000..205792e
--- /dev/null
+++ b/container_files/etc/shibboleth/shibboleth_keygen.sh
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+while getopts h:u:g:o:e:y:bf c
+ do
+ case $c in
+ o) OUT=$OPTARG;;
+ b) BATCH=1;;
+ f) FORCE=1;;
+ h) FQDN=$OPTARG;;
+ e) ENTITYID=$OPTARG;;
+ y) YEARS=$OPTARG;;
+ \?) echo "shibboleth_keygen [-o output directory (default .)] [-h hostname for cert] [-y years to issue cert] [-e entityID to embed in cert]"
+ exit 1;;
+ esac
+ done
+if [ -z "$OUT" ] ; then
+ OUT=.
+fi
+
+if [ -n "$FORCE" ] ; then
+ rm $OUT/sp-key.pem $OUT/sp-cert.pem
+fi
+
+if [ -s $OUT/sp-key.pem -o -s $OUT/sp-cert.pem ] ; then
+ if [ -z "$BATCH" ] ; then
+ echo The files $OUT/sp-key.pem and/or $OUT/sp-cert.pem already exist!
+ echo Use -f option to force recreation of keypair.
+ exit 2
+ fi
+ exit 0
+fi
+
+if [ -z "$FQDN" ] ; then
+ FQDN=`hostname --fqdn`
+fi
+
+if [ -z "$YEARS" ] ; then
+ YEARS=10
+fi
+
+DAYS=`expr $YEARS \* 365`
+
+if [ -z "$ENTITYID" ] ; then
+ ALTNAME=DNS:$FQDN
+else
+ ALTNAME=DNS:$FQDN,URI:$ENTITYID
+fi
+
+SSLCNF=$OUT/sp-cert.cnf
+cat >$SSLCNF < /dev/null
+fi
+rm $SSLCNF
\ No newline at end of file
diff --git a/container_files/wait-for-it/LICENSE b/container_files/wait-for-it/LICENSE
new file mode 100644
index 0000000..bd18d0c
--- /dev/null
+++ b/container_files/wait-for-it/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+Copyright (c) 2016 Giles Hall
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/container_files/wait-for-it/README.md b/container_files/wait-for-it/README.md
new file mode 100644
index 0000000..3a65c3d
--- /dev/null
+++ b/container_files/wait-for-it/README.md
@@ -0,0 +1,59 @@
+`wait-for-it.sh` is a pure bash script that will wait on the availability of a host and TCP port. It is useful for synchronizing the spin-up of interdependent services, such as linked docker containers. Since it is a pure bash script, it does not have any external dependencies.
+
+## Usage
+
+```
+wait-for-it.sh host:port [-s] [-t timeout] [-- command args]
+-h HOST | --host=HOST Host or IP under test
+-p PORT | --port=PORT TCP port under test
+ Alternatively, you specify the host and port as host:port
+-s | --strict Only execute subcommand if the test succeeds
+-q | --quiet Don't output any status messages
+-t TIMEOUT | --timeout=TIMEOUT
+ Timeout in seconds, zero for no timeout
+-- COMMAND ARGS Execute command with args after the test finishes
+```
+
+## Examples
+
+For example, let's test to see if we can access port 80 on www.google.com, and if it is available, echo the message `google is up`.
+
+```
+$ ./wait-for-it.sh www.google.com:80 -- echo "google is up"
+wait-for-it.sh: waiting 15 seconds for www.google.com:80
+wait-for-it.sh: www.google.com:80 is available after 0 seconds
+google is up
+```
+
+You can set your own timeout with the `-t` or `--timeout=` option. Setting the timeout value to 0 will disable the timeout:
+
+```
+$ ./wait-for-it.sh -t 0 www.google.com:80 -- echo "google is up"
+wait-for-it.sh: waiting for www.google.com:80 without a timeout
+wait-for-it.sh: www.google.com:80 is available after 0 seconds
+google is up
+```
+
+The subcommand will be executed regardless if the service is up or not. If you wish to execute the subcommand only if the service is up, add the `--strict` argument. In this example, we will test port 81 on www.google.com which will fail:
+
+```
+$ ./wait-for-it.sh www.google.com:81 --timeout=1 --strict -- echo "google is up"
+wait-for-it.sh: waiting 1 seconds for www.google.com:81
+wait-for-it.sh: timeout occurred after waiting 1 seconds for www.google.com:81
+wait-for-it.sh: strict mode, refusing to execute subprocess
+```
+
+If you don't want to execute a subcommand, leave off the `--` argument. This way, you can test the exit condition of `wait-for-it.sh` in your own scripts, and determine how to proceed:
+
+```
+$ ./wait-for-it.sh www.google.com:80
+wait-for-it.sh: waiting 15 seconds for www.google.com:80
+wait-for-it.sh: www.google.com:80 is available after 0 seconds
+$ echo $?
+0
+$ ./wait-for-it.sh www.google.com:81
+wait-for-it.sh: waiting 15 seconds for www.google.com:81
+wait-for-it.sh: timeout occurred after waiting 15 seconds for www.google.com:81
+$ echo $?
+124
+```
diff --git a/container_files/wait-for-it/wait-for-it.sh b/container_files/wait-for-it/wait-for-it.sh
new file mode 100755
index 0000000..eca6c3b
--- /dev/null
+++ b/container_files/wait-for-it/wait-for-it.sh
@@ -0,0 +1,161 @@
+#!/usr/bin/env bash
+# Use this script to test if a given TCP host/port are available
+
+cmdname=$(basename $0)
+
+echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
+
+usage()
+{
+ cat << USAGE >&2
+Usage:
+ $cmdname host:port [-s] [-t timeout] [-- command args]
+ -h HOST | --host=HOST Host or IP under test
+ -p PORT | --port=PORT TCP port under test
+ Alternatively, you specify the host and port as host:port
+ -s | --strict Only execute subcommand if the test succeeds
+ -q | --quiet Don't output any status messages
+ -t TIMEOUT | --timeout=TIMEOUT
+ Timeout in seconds, zero for no timeout
+ -- COMMAND ARGS Execute command with args after the test finishes
+USAGE
+ exit 1
+}
+
+wait_for()
+{
+ if [[ $TIMEOUT -gt 0 ]]; then
+ echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"
+ else
+ echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"
+ fi
+ start_ts=$(date +%s)
+ while :
+ do
+ (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1
+ result=$?
+ if [[ $result -eq 0 ]]; then
+ end_ts=$(date +%s)
+ echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"
+ break
+ fi
+ sleep 1
+ done
+ return $result
+}
+
+wait_for_wrapper()
+{
+ # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
+ if [[ $QUIET -eq 1 ]]; then
+ timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
+ else
+ timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
+ fi
+ PID=$!
+ trap "kill -INT -$PID" INT
+ wait $PID
+ RESULT=$?
+ if [[ $RESULT -ne 0 ]]; then
+ echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"
+ fi
+ return $RESULT
+}
+
+# process arguments
+while [[ $# -gt 0 ]]
+do
+ case "$1" in
+ *:* )
+ hostport=(${1//:/ })
+ HOST=${hostport[0]}
+ PORT=${hostport[1]}
+ shift 1
+ ;;
+ --child)
+ CHILD=1
+ shift 1
+ ;;
+ -q | --quiet)
+ QUIET=1
+ shift 1
+ ;;
+ -s | --strict)
+ STRICT=1
+ shift 1
+ ;;
+ -h)
+ HOST="$2"
+ if [[ $HOST == "" ]]; then break; fi
+ shift 2
+ ;;
+ --host=*)
+ HOST="${1#*=}"
+ shift 1
+ ;;
+ -p)
+ PORT="$2"
+ if [[ $PORT == "" ]]; then break; fi
+ shift 2
+ ;;
+ --port=*)
+ PORT="${1#*=}"
+ shift 1
+ ;;
+ -t)
+ TIMEOUT="$2"
+ if [[ $TIMEOUT == "" ]]; then break; fi
+ shift 2
+ ;;
+ --timeout=*)
+ TIMEOUT="${1#*=}"
+ shift 1
+ ;;
+ --)
+ shift
+ CLI="$@"
+ break
+ ;;
+ --help)
+ usage
+ ;;
+ *)
+ echoerr "Unknown argument: $1"
+ usage
+ ;;
+ esac
+done
+
+if [[ "$HOST" == "" || "$PORT" == "" ]]; then
+ echoerr "Error: you need to provide a host and port to test."
+ usage
+fi
+
+TIMEOUT=${TIMEOUT:-15}
+STRICT=${STRICT:-0}
+CHILD=${CHILD:-0}
+QUIET=${QUIET:-0}
+
+if [[ $CHILD -gt 0 ]]; then
+ wait_for
+ RESULT=$?
+ exit $RESULT
+else
+ if [[ $TIMEOUT -gt 0 ]]; then
+ wait_for_wrapper
+ RESULT=$?
+ else
+ wait_for
+ RESULT=$?
+ fi
+fi
+
+if [[ $CLI != "" ]]; then
+ if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then
+ echoerr "$cmdname: strict mode, refusing to execute subprocess"
+ exit $RESULT
+ fi
+ exec $CLI
+else
+ exit $RESULT
+fi
diff --git a/tests/image.bats b/tests/image.bats
new file mode 100644
index 0000000..e14978f
--- /dev/null
+++ b/tests/image.bats
@@ -0,0 +1,7 @@
+#!/usr/bin/env bats
+
+load ../common
+
+@test "COmanage directory created" {
+ docker run -i $maintainer/$imagename find /opt/comanage/comanage-registry-$version
+}
\ No newline at end of file