diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..b43bf86
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+README.md
diff --git a/000-comanage.conf b/000-comanage.conf
new file mode 100644
index 0000000..b198062
--- /dev/null
+++ b/000-comanage.conf
@@ -0,0 +1,86 @@
+# COmanage Registry Apache HTTP Server configuration
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+Listen 443
+ServerName %%SERVER_NAME%%
+PassEnv ENV
+PassEnv USERTOKEN
+
+
+ServerName http://%%SERVER_NAME%%:80
+RewriteEngine On
+RewriteCond %{HTTPS} off
+RewriteRule ^ https://%{HTTP_HOST}:443%{REQUEST_URI} [R=302,L,QSA]
+
+
+
+
+ServerName https://%%SERVER_NAME%%:443
+
+PassEnv ENV
+PassEnv USERTOKEN
+
+DocumentRoot /var/www/html
+
+RedirectMatch ^/$ /registry/
+
+ErrorLogFormat "httpd;ssl_error_log;%{ENV}e;%{USERTOKEN}e;[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"
+ErrorLog /tmp/logpipe
+LogLevel warn
+
+LogFormat "httpd;ssl_access_log;%{ENV}e;%{USERTOKEN}e;%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" ssl_combined
+CustomLog /tmp/logpipe ssl_combined
+
+Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
+
+SSLEngine on
+SSLProtocol all -SSLv2 -SSLv3
+SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
+SSLHonorCipherOrder on
+
+SSLCertificateFile /etc/httpd/cert.pem
+SSLCertificateKeyFile /etc/httpd/privkey.pem
+
+
+Options Indexes FollowSymLinks
+DirectoryIndex index.php
+AllowOverride All
+Require all granted
+
+
+
+SetHandler shib
+
+
+
+AuthType shibboleth
+ShibRequestSetting requireSession 1
+Require valid-user
+
+
+
+AuthType shibboleth
+Require shibboleth
+
+
+RewriteEngine On
+RewriteCond %{QUERY_STRING} !after_redirect
+RewriteRule ^/registry/auth/logout.* https://%%SERVER_NAME%%/Shibboleth.sso/Logout?return=https://%%SERVER_NAME%%/registry/auth/logout/?after_redirect [L,R]
+
+
diff --git a/10-php7.conf b/10-php7.conf
new file mode 100644
index 0000000..64ef2d7
--- /dev/null
+++ b/10-php7.conf
@@ -0,0 +1,3 @@
+
+ LoadModule php7_module modules/libphp7.so
+
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..6abb497
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,197 @@
+# COmanage Registry Dockerfile
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+FROM centos:centos7 AS php-build
+
+RUN yum -y install epel-release
+
+RUN yum -y update && yum -y install \
+ autoconf \
+ bison \
+ gcc \
+ httpd-devel \
+ libargon2-devel \
+ libcurl-devel \
+ libedit-devel \
+ libsodium-devel \
+ libxml2-devel \
+ libxslt-devel \
+ make \
+ mariadb-devel \
+ openldap-devel \
+ openssl-devel \
+ postgresql-devel \
+ re2c \
+ wget
+
+WORKDIR /usr/local/src
+
+ARG PHP_VERSION=7.2.5
+ARG PHP_SRC_URL=https://github.com/php/php-src/archive/php-${PHP_VERSION}.tar.gz
+
+RUN mkdir php-src \
+ && wget -O php-src.tar.gz ${PHP_SRC_URL} \
+ && tar zxf php-src.tar.gz -C php-src --strip-components=1 \
+ && rm php-src.tar.gz
+
+ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
+ENV PHP_CPPFLAGS="$PHP_CFLAGS"
+ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
+
+RUN cd php-src \
+ && ./buildconf --force \
+ && ./configure \
+ --disable-cgi \
+ --enable-mbstring \
+ --enable-mysqlnd \
+ --with-apxs2=/usr/bin/apxs \
+ --with-config-file-path=/usr/local/etc/php \
+ --with-config-file-scan-dir=/usr/local/etc/php/conf.d \
+ --with-curl \
+ --with-ldap \
+ --with-libdir=lib64 \
+ --with-libedit \
+ --with-mysqli \
+ --with-openssl \
+ --with-password-argon2 \
+ --with-pdo-mysql \
+ --with-pdo-pgsql \
+ --with-pgsql \
+ --with-sodium \
+ --with-xsl \
+ --with-zlib \
+ && export CFLAGS="$PHP_CFLAGS" \
+ && export CPPFLAGS="$PHP_CPPFLAGS" \
+ && export LDFLAGS="$PHP_LDFLAGS" \
+ && make -j "$(nproc)" \
+ && make install
+
+FROM centos:centos7
+
+RUN yum -y install epel-release
+
+COPY shibboleth.repo /etc/yum.repos.d/
+
+RUN yum -y update && yum -y install \
+ cronie \
+ httpd \
+ libargon2 \
+ libcurl \
+ libedit \
+ libsodium \
+ libxml2 \
+ libxslt \
+ mod_ssl \
+ mariadb-libs \
+ postgresql \
+ python-pip \
+ shibboleth \
+ wget \
+ zlib \
+ && pip install --upgrade pip \
+ && pip install supervisor \
+ && yum clean -y all
+
+COPY --from=php-build /usr/lib64/httpd/modules/libphp7.so /usr/lib64/httpd/modules/
+COPY --from=php-build /usr/local/lib/php /usr/local/lib/php/
+COPY --from=php-build /usr/local/include/php /usr/local/include/php/
+COPY --from=php-build /usr/local/bin /usr/local/bin/
+
+ARG COMANAGE_REGISTRY_VERSION
+ARG COMANAGE_REGISTRY_SRC_URL=https://github.com/Internet2/comanage-registry/archive/${COMANAGE_REGISTRY_VERSION}.tar.gz
+ENV COMANAGE_REGISTRY_VERSION ${COMANAGE_REGISTRY_VERSION}
+
+LABEL comanage_registry_version=${COMANAGE_REGISTRY_VERSION}
+LABEL comanage_registry_src_url=${COMANAGE_REGISTRY_SRC_URL}
+
+ENV COMANAGE_REGISTRY_DIR /srv/comanage-registry
+
+WORKDIR "$COMANAGE_REGISTRY_DIR"
+
+RUN mkdir -p "${COMANAGE_REGISTRY_DIR}" \
+ && wget -O comanage.tar.gz ${COMANAGE_REGISTRY_SRC_URL} \
+ && tar -zxf comanage.tar.gz -C ${COMANAGE_REGISTRY_DIR} --strip-components=1 \
+ && rm -f comanage.tar.gz \
+ && rm -f ${COMANAGE_REGISTRY_DIR}/app/tmp \
+ && cp -r ${COMANAGE_REGISTRY_DIR}/app/tmp.dist ${COMANAGE_REGISTRY_DIR}/app/tmp \
+ && chown -R apache:apache ${COMANAGE_REGISTRY_DIR}/app/tmp \
+ && cd /var/www/html \
+ && ln -s ${COMANAGE_REGISTRY_DIR}/app/webroot registry \
+ && rm -rf ${COMANAGE_REGISTRY_DIR}/local/* \
+ && ln -s ${COMANAGE_REGISTRY_DIR}/local /local
+
+COPY 000-comanage.conf /etc/httpd/conf.d/
+COPY 10-php7.conf /etc/httpd/conf.modules.d/
+COPY php.conf /etc/httpd/conf.d/
+COPY supervisord.conf /usr/local/etc/supervisord.conf
+COPY shibd.logger /etc/shibboleth/
+COPY native.logger /etc/shibboleth/
+COPY httpd.conf /etc/httpd/conf/
+COPY sendtierbeacon.sh /usr/local/bin/sendtierbeacon.sh
+COPY setupcron.sh /usr/local/bin/setupcron.sh
+
+RUN cd /etc/httpd/conf.d \
+ && rm -f autoindex.conf ssl.conf userdir.conf welcome.conf \
+ && cd /etc/httpd \
+ && ln -s /etc/pki/tls/certs/localhost.crt cert.pem \
+ && ln -s /etc/pki/tls/private/localhost.key privkey.pem \
+ && chmod 755 /usr/local/bin/sendtierbeacon.sh \
+ && chmod 755 /usr/local/bin/setupcron.sh \
+ && /usr/local/bin/setupcron.sh
+
+# Allow values for first administrator bootstrapped into the
+# platform to be specified at image build time, in addition to
+# being injected at run time through the entrypoint script.
+ARG COMANAGE_REGISTRY_ADMIN_GIVEN_NAME
+ARG COMANAGE_REGISTRY_ADMIN_FAMILY_NAME
+ARG COMANAGE_REGISTRY_ADMIN_USERNAME
+ARG COMANAGE_REGISTRY_ENABLE_POOLING
+
+# Set simple defaults for first administrator bootstrapped into the
+# platform to make simple evaluation of the platform easier.
+ENV COMANAGE_REGISTRY_ADMIN_GIVEN_NAME ${COMANAGE_REGISTRY_ADMIN_GIVEN_NAME:-Registry}
+ENV COMANAGE_REGISTRY_ADMIN_FAMILY_NAME ${COMANAGE_REGISTRY_ADMIN_FAMILY_NAME:-Admin}
+ENV COMANAGE_REGISTRY_ADMIN_USERNAME ${COMANAGE_REGISTRY_ADMIN_USERNAME:-registry.admin}
+ENV COMANAGE_REGISTRY_ENABLE_POOLING ${COMANAGE_REGISTRY_ENABLE_POOLING:-No}
+
+EXPOSE 80 443
+
+VOLUME ["/srv/comanage-registry/local"]
+
+VOLUME ["/etc/shibboleth"]
+
+COPY docker-comanage-entrypoint /usr/local/bin/
+COPY docker-comanage-shibboleth-sp-entrypoint /usr/local/bin/
+COPY docker-supervisord-entrypoint /usr/local/bin/
+
+# TIER Beacon Opt-out
+#
+# Completely uncomment the following ENV line to prevent the containers from
+# sending analytics information to Internet2. With the default/release
+# configuration, it will only send product (Shibb/Grouper/COmanage) and version
+# (3.3.1-17040, etc) once daily between midnight and 4am. There is no
+# configuration or private information collected or sent. This data helps with
+# the scaling and funding of TIER. Please do not disable it if you find the
+# TIER tools useful. To keep it commented, keep multiple comments on the
+# following line (to prevent other scripts from processing it).
+##### ENV TIER_BEACON_OPT_OUT True
+
+ENV TIER_RELEASE=180501
+ENV TIER_MAINTAINER=tier
+
+ENTRYPOINT ["docker-supervisord-entrypoint"]
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..50d0a06
--- /dev/null
+++ b/README.md
@@ -0,0 +1,556 @@
+# COmanage Registry Internet2 TIER Docker
+
+## What it is
+Docker version of [COmanage
+Registry](https://spaces.internet2.edu/display/COmanage/Home) packaged to meet
+the specifications of the
+[Internet2 TIER](https://www.internet2.edu/vision-initiatives/initiatives/trust-identity-education-research/)
+program.
+
+COmanage Registry is a web application that requires a relational database
+and an authentication mechanism such as
+[Shibboleth](http://shibboleth.net/products/service-provider.html).
+
+## How To
+
+* Install Docker. These instructions require version 17.03.1 or higher.
+
+* Clone this repository:
+
+```
+git clone https://github.com/Internet2/comanage-registry-docker.git
+cd comanage-registry-docker
+```
+
+* Define `COMANAGE_REGISTRY_VERSION`. Currently we recommend
+
+```
+export COMANAGE_REGISTRY_VERSION=3.1.0
+```
+
+* Build a local image for COmanage Registry:
+
+```
+pushd comanage-registry-internet2-tier
+docker build \
+ --build-arg COMANAGE_REGISTRY_VERSION=${COMANAGE_REGISTRY_VERSION} \
+ -t comanage-registry:${COMANAGE_REGISTRY_VERSION}-internet2-tier .
+popd
+```
+
+* Create directories to store local state files:
+
+```
+sudo mkdir -p /srv/docker/internet2-tier/srv/comanage-registry/local
+sudo mkdir -p /srv/docker/internet2-tier/var/lib/mysql
+sudo mkdir -p /srv/docker/internet2-tier/var/lib/ldap
+sudo mkdir -p /srv/docker/internet2-tier/etc/ldap/slapd.d
+```
+
+* Initialize Docker Swarm:
+
+```
+docker swarm init
+```
+
+* Hash a password to use as the LDAP admin password:
+
+```
+/usr/sbin/slappasswd -c '$6$rounds=5000$%.86s'
+```
+
+* Create Docker Swarm secrets (please be sure to substitute your own secrets):
+
+
+```
+echo "88cdfwOgQ1OblrHPNTyY" | docker secret create mysql_root_password -
+
+echo "5zY87knHxbP3sVQstRW2" | docker secret create mysql_password -
+
+echo "5zY87knHxbP3sVQstRW2" | docker secret create comanage_registry_database_user_password -
+
+echo "qselvrfaomxktlra" | docker secret create comanage_registry_email_account_password -
+
+docker secret create https_cert_file fullchain.pem
+
+docker secret create https_privkey_file privkey.pem
+
+docker secret create shibboleth_sp_cert sp-cert.pem
+
+docker secret create shibboleth_sp_privkey sp-key.pem
+
+echo '{CRYPT}$6$rounds=5000$HHDyV7yz4yn4FH/d$eAg9uXbSnxvCCTZ8GstprFryip3Br111tArqsIaBDCF2Rm7tciEivDLCjpcMVT7OL.Lg5QKjEUM.C5UA2DNuf1' \
+ | docker secret create olc_root_pw -
+
+docker secret create slapd_cert_file cert.pem
+
+docker secret create slapd_privkey_file privkey.pem
+
+docker secret create slapd_chain_file chain.pem
+```
+
+* Create a Docker compose file:
+
+```
+version: '3.1'
+
+services:
+ comanage-registry:
+ image: comanage-registry:3.1.0-internet2-tier
+ volumes:
+ - /srv/docker/internet2-tier/srv/comanage-registry/local:/srv/comanage-registry/local
+ environment:
+ - COMANAGE_REGISTRY_DATASOURCE=Database/Mysql
+ - COMANAGE_REGISTRY_DATABASE=registry
+ - COMANAGE_REGISTRY_DATABASE_HOST=comanage-registry-database
+ - COMANAGE_REGISTRY_DATABASE_USER=registry_user
+ - COMANAGE_REGISTRY_DATABASE_USER_PASSWORD_FILE=/run/secrets/comanage_registry_database_user_password
+ - COMANAGE_REGISTRY_EMAIL_FROM=registry@some.org
+ - COMANAGE_REGISTRY_EMAIL_TRANSPORT=Smtp
+ - COMANAGE_REGISTRY_EMAIL_HOST=tls://smtp.some.org
+ - COMANAGE_REGISTRY_EMAIL_PORT=465
+ - COMANAGE_REGISTRY_EMAIL_ACCOUNT=registry@some.org
+ - COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD_FILE=/run/secrets/comanage_registry_email_account_password
+ - COMANAGE_REGISTRY_ADMIN_GIVEN_NAME=Emma
+ - COMANAGE_REGISTRY_ADMIN_FAMILY_NAME=Sanchez
+ - COMANAGE_REGISTRY_ADMIN_USERNAME=emma.sanchez@some.org
+ - HTTPS_CERT_FILE=/run/secrets/https_cert_file
+ - HTTPS_PRIVKEY_FILE=/run/secrets/https_privkey_file
+ - SERVER_NAME=registry.some.org
+ - SHIBBOLETH_SP_CERT=/run/secrets/shibboleth_sp_cert
+ - SHIBBOLETH_SP_PRIVKEY=/run/secrets/shibboleth_sp_privkey
+ secrets:
+ - comanage_registry_database_user_password
+ - comanage_registry_email_account_password
+ - https_cert_file
+ - https_privkey_file
+ - shibboleth_sp_cert
+ - shibboleth_sp_privkey
+ networks:
+ - default
+ ports:
+ - "80:80"
+ - "443:443"
+ logging:
+ driver: syslog
+ options:
+ tag: "comanage_registry"
+ deploy:
+ replicas: 1
+
+ comanage-registry-database:
+ image: mariadb:10.2
+ volumes:
+ - /srv/docker/internet2-tier/var/lib/mysql:/var/lib/mysql
+ environment:
+ - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_password
+ - MYSQL_DATABASE=registry
+ - MYSQL_USER=registry_user
+ - MYSQL_PASSWORD_FILE=/run/secrets/mysql_password
+ secrets:
+ - mysql_root_password
+ - mysql_password
+ networks:
+ - default
+ logging:
+ driver: syslog
+ options:
+ tag: "mariadb"
+ deploy:
+ replicas: 1
+
+ comanage-registry-ldap:
+ image: sphericalcowgroup/comanage-registry-slapd
+ command: ["slapd", "-d", "256", "-h", "ldapi:/// ldap:/// ldaps:///", "-u", "openldap", "-g", "openldap"]
+ volumes:
+ - /srv/docker/development/var/lib/ldap:/var/lib/ldap
+ - /srv/docker/development/etc/ldap/slapd.d:/etc/ldap/slapd.d
+ environment:
+ - SLAPD_CERT_FILE=/run/secrets/slapd_cert_file
+ - SLAPD_PRIVKEY_FILE=/run/secrets/slapd_privkey_file
+ - SLAPD_CHAIN_FILE=/run/secrets/slapd_chain_file
+ - OLC_ROOT_PW_FILE=/run/secrets/olc_root_pw
+ - OLC_SUFFIX=dc=sphericalcowgroup,dc=com
+ - OLC_ROOT_DN=cn=admin,dc=sphericalcowgroup,dc=com
+ secrets:
+ - slapd_cert_file
+ - slapd_privkey_file
+ - slapd_chain_file
+ - olc_root_pw
+ networks:
+ - default
+ logging:
+ driver: syslog
+ options:
+ tag: "openldap"
+ ports:
+ - "636:636"
+ - "389:389"
+ deploy:
+ replicas: 1
+
+secrets:
+ mysql_root_password:
+ external: true
+ mysql_password:
+ external: true
+ comanage_registry_database_user_password:
+ external: true
+ comanage_registry_email_account_password:
+ external: true
+ https_cert_file:
+ external: true
+ https_privkey_file:
+ external: true
+ shibboleth_sp_cert:
+ external: true
+ shibboleth_sp_privkey:
+ external: true
+ slapd_cert_file:
+ external: true
+ slapd_privkey_file:
+ external: true
+ slapd_chain_file:
+ external: true
+ olc_root_pw:
+ external: true
+
+```
+
+* Start the services:
+
+```
+docker stack deploy comanage-registry
+```
+
+* Visit the [COmanage wiki](https://spaces.internet2.edu/display/COmanage/Setting+Up+Your+First+CO)
+to learn how to create your first collaborative organization (CO) and begin using
+the platform.
+
+* To stop the services:
+```
+docker stack rm comanage-registry
+```
+
+## Advanced Configuration Options
+
+* [Environment Variables](#environ)
+* [Apache HTTP ServerName](#servername)
+* [X.509 Certificates and Private Keys](#certskeys)
+* [Full Control](#full)
+
+## Environment Variables
+
+All deployment details for COmanage Registry may be configured using environment variables set for the container.
+The set of possible environment variables is listed below.
+
+The entrypoint scripts will attempt to use values from environment variables and if not
+present reasonable defaults will be used. *Note that some defaults like passwords are
+easily guessable and not suitable for production deployments*.
+
+For secrets such as passwords you may wish to use the environment variable with
+`_FILE` appended and set the value to a path. The entrypoint scripts will read the
+file to find the value to use. For example to set the database user password to the
+value `dEodxlXQE2dKl8own7T2` you can for the container either set the environment variable
+
+```
+COMANAGE_REGISTRY_DATABASE_USER_PASSWORD=dEodxlXQE2dKl8own7T2
+```
+
+or instead ensure that inside the container the file
+`/db_password` contains
+on a single line the value `dEodxlXQE2dKl8own7T2` and then set the
+environment variable
+
+*When present an environment variable pointing to a file inside the container overrides
+an otherwise configured environment variable*.
+
+```
+COMANAGE_REGISTRY_DATABASE_USER_PASSWORD_FILE=/db_password
+```
+
+Some deployment details for the Shibboleth SP may be set using environment variables, but most
+deployments will prefer to mount or COPY in `/etc/shibboleth/shibboleth2.xml` to be able
+to configure SAML federation details.
+
+### COmanage Registry
+
+* COMANAGE_REGISTRY_ADMIN_GIVEN_NAME:
+ * Description: platform admin given name
+ * Default: Registry
+ * Example 1: Scott
+ * Example 2: Himari
+
+* COMANAGE_REGISTRY_ADMIN_FAMILY_NAME:
+ * Description: platform admin family name
+ * Default: Admin
+ * Example 1: Koranda
+ * Example 2: Tanaka
+
+* COMANAGE_REGISTRY_ADMIN_USERNAME:
+ * Description: platform admin username identifier (often eduPersonPrincipalName)
+ * Default: registry.admin
+ * Example 1: scott.koranda@sphericalcowgroup.com
+ * Example 2: himaritanaka@some.org
+
+* COMANAGE_REGISTRY_DATASOURCE
+ * Description: database type
+ * Default: Database/Postgres
+ * Example 1: Database/Mysql
+ * Example 2: Database/Postgres
+
+* COMANAGE_REGISTRY_DATABASE
+ * Description: name of the database
+ * Default: registry
+ * Example 1: comanage_registry
+ * Example 2: COmanageRegistryDB
+
+* COMANAGE_REGISTRY_DATABASE_HOST
+ * Description: hostname of the database server
+ * Default: comanage-registry-database
+ * Example 1: comanage-registry-database
+ * Example 2: my-db-container
+
+* COMANAGE_REGISTRY_DATABASE_USER
+ * Description: database username
+ * Default: registry_user
+ * Example 1: comanage
+ * Example 2: comanage_user
+
+* COMANAGE_REGISTRY_DATABASE_USER_PASSWORD
+ * Description: database user password
+ * Default: password
+ * Example 1: AFH9OiyuowiY3Wq6qX0j
+ * Example 2: qVcsJPo7$@
+
+* COMANAGE_REGISTRY_EMAIL_FROM
+ * Description: default From used by Registry for sending email
+ * Default: none
+ * Example 1: registry@some.org
+ * Example 2: skoranda@gmail.com
+
+* COMANAGE_REGISTRY_EMAIL_TRANSPORT
+ * Description: email transport mechanism
+ * Default: Smtp
+ * Example 1: Smtp
+ * Example 2: MyCustom
+
+* COMANAGE_REGISTRY_EMAIL_PORT
+ * Description: email transport port
+ * Default: 465
+ * Example 1: 465
+ * Example 2: 25
+
+* COMANAGE_REGISTRY_EMAIL_HOST
+ * Description: email server host
+ * Default: tls://smtp.gmail.com
+ * Example 1: smtp.my.org
+ * Example 2: mail.some.org
+
+* COMANAGE_REGISTRY_EMAIL_ACCOUNT
+ * Description: email server account
+ * Default: none
+ * Example 1: skoranda@gmail.com
+ * Example 2: registry_email_sender
+
+* COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD
+ * Description: email server account password
+ * Default: none
+ * Example 1: 82P3mt1T0PByZRHNQ6he
+ * Example 2: ak&&u1$@
+
+* COMANAGE_REGISTRY_SECURITY_SALT
+ * Description: security salt value
+ * Default: auto-generated at initial deployment if not specified
+ * Example 1: wciEjD1KbX9Q8nB3YdWItFuzEoRdf6l5BpoCuTHm
+ * Example 2: JpmKTdO88NX6RsCIVnru6hV79zKOfvjGk0tTG0Cb
+
+* COMANAGE_REGISTRY_SECURITY_SEED
+ * Description: security seed value
+ * Default: auto-generated at initial deployment if not specified
+ * Example 1: 32616298446590535751260992683
+ * Example 2: 21812581423282761029813528278
+
+* HTTPS_CERT_FILE
+ * Description: X.509 certificate and CA chain in PEM format for use with Apache HTTP Server to serve HTTPS
+ * Default: self-signed auto-generated certificate
+
+* HTTPS_KEY_FILE
+ * Description: Associated private key for HTTPS in PEM format
+ * Default: private key for self-signed auto-generated certificate
+
+* SERVER_NAME
+ * Description: ServerName for Apache HTTP Server virtual host configuration
+ * Default: none, parsed from X.509 certificate if not defined
+ * Example 1: registry.some.org
+ * Example 2: comanage.my.edu
+
+### MariaDB
+
+* MYSQL_ROOT_PASSWORD
+ * Description: password for root user
+ * Default: none
+ * Example 1: ukZd7IZDRfOqgF82938A
+ * Example 2: 28hvua3%,2
+
+* MYSQL_DATABASE
+ * Description: name of the database, must be same as set for COmanage Registry container
+ * Default: none
+ * Example 1: comanage_registry
+ * Example 2: COmanageRegistryDB
+
+* MYSQL_USER:
+ * Description: database username, must be same as set for COmanage Registry container
+ * Default: none
+ * Example 1: comanage
+ * Example 2: comanage_user
+
+* MYSQL_PASSWORD_FILE:
+ * Description: database user password, must be same as set for COmanage Registry container
+ * Default: none
+ * Example 1: AFH9OiyuowiY3Wq6qX0j
+ * Example 2: qVcsJPo7$@
+
+### Shibboleth SP
+
+* SHIBBOLETH_SP_CERT
+ * Description: SAML certificate
+ * Default: self-signed per-image, must be copied out to persist
+
+* SHIBBOLETH_SP_ENTITY_ID
+ * Description: entityID for SP
+ * Default: none
+ * Example 1: https://comanage.registry/shibboleth
+ * Example 2: https://my.org/comanage
+
+* SHIBBOLETH_SP_METADATA_PROVIDER_XML
+ * Description: Shibboleth SP metadata provider element
+ * Default: none
+
+* SHIBBOLETH_SP_PRIVKEY
+ * Description: SAML private key
+ * Default: self-signed per-image, must be copied out to persist
+
+* SHIBBOLETH_SP_SAMLDS_URL
+ * Description: URL for SAML IdP discovery service
+ * Default: none
+ * Example 1: https://my.org/registry/pages/eds/index
+ * Exammple 2: https://discovery.my.org
+
+### OpenLDAP slapd
+
+* OLC_ROOT_DN
+ * Description: DN for the administrator
+ * Default: cn=admin,dc=my,dc=org
+ * Exammle 1: cn=admin,dc=some,dc=edu
+ * Example 2: cn=admin,ou=service,dc=my,dc=org
+
+* OLC_ROOT_PW
+ * Description: hashed password for root DN
+ * Default: none
+ * Example 1: See compose file above
+
+* OLC_SUFFIX
+ * Description: Suffix for the directory
+ * Default: dc=my,dc=org
+ * Example 1: dc=some,dc=edu
+ * Example 2: o=unit,dc=my,dc=org
+
+* SLAPD_CERT_FILE
+ * Description: X.509 certificate in PEM format for use with OpenLDAP Server to serve ldaps://
+ * Default: none
+
+* SLAPD_CHAIN_FILE
+ * Description: CA certificate chain in PEM format
+ * Default: none
+
+* SLAPD_KEY_FILE
+ * Description: Associated private key for ldaps:// in PEM format
+ * Default: none
+
+## X.509 Certificates and Private Keys
+
+### COmanage Registry
+
+The certificate and private key files used for HTTPS may
+be injected into the COmanage Registry container using environment variables
+to point to files mounted into the container. The certificate file should
+include the server certificate and any intermediate CA signing certificates
+sorted from leaf to root.
+
+Alternatively you can directly mount files in the container to
+
+```
+/etc/apache2/cert.pem
+/etc/apache2/privkey.pem
+```
+
+If no files are configured the containers use self-signed certificates
+for HTTPS by default.
+
+### Shibboleth SP
+
+The SAML certificate and private key used for decryption (and sometimes signing)
+by the Shibboleth SP may be injected into the COmanage Registry container using
+environment variables to point to files mounted into the container.
+
+Alternatively you can directly mount files in the container to
+
+```
+/etc/shibboleth/sp-cert.pem
+/etc/shibboleth/sp-key.pem
+```
+
+If no files are configured the container uses a default self-signed certificate
+*this is the same for all images and not suitable for production*.
+
+### OpenLDAP slapd
+
+The certificate, private key, and CA signing file or chain file used for TLS
+(port 636 by default) may
+be injected into the OpenLDAP slapd container using environment variables
+to point to files mounted into the container.
+
+## ServerName
+
+The entrypoint scripts will attempt to parse the appropriate value for the
+Apache HTTP Server configuration option `ServerName` from the X.509 certificate
+provided for HTTPS.
+
+To override the parsing a deployer may explicitly set the environment variable
+`SERVER_NAME`.
+
+## Full control
+
+Deployers needing full control may inject configuration and deployment details directly.
+The entrypoint scripts will *not* overwrite any details found so directly injected
+details always override environment variables.
+
+### COmanage Registry
+
+COmanage Registry expects to find all local configuration details
+in the container at `/srv/comanage-registry/local`. A deployer may therefore mount
+a directory at that location to provide any and all configuration details. Note, however,
+that Registry expects to find a particular directory structure under
+`/srv/comanage-registry/local` and will not function properly if the structure is not
+found. The entrypoint script will create the necessary structure if it does not find it
+so it is recommended to mount an empty directory for the first deployment, let the
+entrypoint script create the structure, then later adjust the details as necessary
+for your deployment.
+
+### Shibboleth SP
+
+All Shibboleth SP configuration is available inside the container in
+`/etc/shibboleth`. A deployer may therefore mount into that directory any
+necessary adjustment to the Shibboleth configuration, such as static metadata
+files, metadata signing certificates, or advanced attribute filtering
+configurations.
+
+A default set of all configuration files is available in the image.
+
+### OpenLDAP slapd
+
+Since slapd is configured dynamically using standard LDAP operations on the
+configuration directory (`cn=config`) the most straightforward way to inject
+advanced configuration details at the time the container is *created* is
+to customize the entrypoint script.
diff --git a/docker-comanage-entrypoint b/docker-comanage-entrypoint
new file mode 100755
index 0000000..6191e13
--- /dev/null
+++ b/docker-comanage-entrypoint
@@ -0,0 +1,350 @@
+#!/bin/bash
+
+# COmanage Registry Dockerfile entrypoint
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [ -n "$COMANAGE_DEBUG" ]
+then
+ OUTPUT=/dev/stdout
+else
+ OUTPUT=/dev/null
+fi
+
+# Configuration details that may be injected through environment
+# variables or the contents of files.
+
+injectable_config_vars=(
+ COMANAGE_REGISTRY_DATASOURCE
+ COMANAGE_REGISTRY_DATABASE
+ COMANAGE_REGISTRY_DATABASE_HOST
+ COMANAGE_REGISTRY_DATABASE_USER
+ COMANAGE_REGISTRY_DATABASE_USER_PASSWORD
+ COMANAGE_REGISTRY_EMAIL_FROM
+ COMANAGE_REGISTRY_EMAIL_TRANSPORT
+ COMANAGE_REGISTRY_EMAIL_HOST
+ COMANAGE_REGISTRY_EMAIL_PORT
+ COMANAGE_REGISTRY_EMAIL_ACCOUNT
+ COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD
+ COMANAGE_REGISTRY_SECURITY_SALT
+ COMANAGE_REGISTRY_SECURITY_SEED
+ ENV
+ HTTPS_CERT_FILE
+ HTTPS_PRIVKEY_FILE
+ SERVER_NAME
+ USERTOKEN
+)
+
+# If the file associated with a configuration variable is present then
+# read the value from it into the appropriate variable. So for example
+# if the variable COMANAGE_REGISTRY_DATASOURCE_FILE exists and its
+# value points to a file on the file system then read the contents
+# of that file into the variable COMANAGE_REGISTRY_DATASOURCE.
+
+for config_var in "${injectable_config_vars[@]}"
+do
+ eval file_name=\$"${config_var}_FILE";
+
+ if [ -e "$file_name" ]; then
+ declare "${config_var}"=`cat $file_name`
+ fi
+done
+
+# Make sure the directory structure we need is available
+# in the data volume for $COMANAGE_REGISTRY_DIR/local
+mkdir -p "$COMANAGE_REGISTRY_DIR/local/Config"
+mkdir -p "$COMANAGE_REGISTRY_DIR/local/Plugin"
+mkdir -p "$COMANAGE_REGISTRY_DIR/local/View/Pages/public"
+mkdir -p "$COMANAGE_REGISTRY_DIR/local/webroot/img"
+
+# If the COmanage Registry database configuration file does not exist
+# then try to create it from injected information with reasonable defaults
+# that aid simple evaluation deployments.
+if [ ! -e "$COMANAGE_REGISTRY_DIR/local/Config/database.php" ]; then
+ cat > "$COMANAGE_REGISTRY_DIR/local/Config/database.php" < '${COMANAGE_REGISTRY_DATASOURCE:-Database/Mysql}',
+ 'persistent' => false,
+ 'host' => '${COMANAGE_REGISTRY_DATABASE_HOST:-comanage-registry-database}',
+ 'login' => '${COMANAGE_REGISTRY_DATABASE_USER:-registry_user}',
+ 'password' => '${COMANAGE_REGISTRY_DATABASE_USER_PASSWORD:-password}',
+ 'database' => '${COMANAGE_REGISTRY_DATABASE:-registry}',
+ 'prefix' => 'cm_',
+ );
+
+}
+EOF
+fi
+
+# If the COmanage Registry email configuration file does not exist
+# then try to create it from injected information with reasonable defaults
+# that aid simple evaluation deployments.
+email_config="$COMANAGE_REGISTRY_DIR/local/Config/email.php"
+
+if [ ! -e "$email_config" ]; then
+ # If the deployer has injected an email for from then use it,
+ # otherwise set a default purely as a template that can edited
+ # easier later.
+ if [ -n "$COMANAGE_REGISTRY_EMAIL_FROM" ]; then
+ email_from="$COMANAGE_REGISTRY_EMAIL_FROM"
+ else
+ email_from="array('account@gmail.com' => 'Registry')"
+ fi
+
+ # If the injected email from does not include a single quote (')
+ # then add them to make it a PHP string.
+ if [[ ! $email_from =~ .*"'".* ]]; then
+ email_from="'$email_from'"
+ fi
+
+ cat > "$email_config" < $email_from,
+ 'transport' => '${COMANAGE_REGISTRY_EMAIL_TRANSPORT:-Smtp}',
+ 'host' => '${COMANAGE_REGISTRY_EMAIL_HOST:-tls://smtp.gmail.com}',
+ 'port' => ${COMANAGE_REGISTRY_EMAIL_PORT:-465},
+EOF
+
+ # If the deployer has injected a username then add it to the configuration.
+ if [ -n "$COMANAGE_REGISTRY_EMAIL_ACCOUNT" ]; then
+ cat >> "$email_config" < '$COMANAGE_REGISTRY_EMAIL_ACCOUNT',
+EOF
+ fi
+
+ # If the deployer has injected a password then add it to the configuration.
+ if [ -n "$COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD" ]; then
+ cat >> "$email_config" < '$COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD',
+EOF
+ fi
+
+ # Complete the PHP array.
+ cat >> "$email_config" < $DATABASE_TEST_SCRIPT <<"EOF"
+error("Unable to connect to datasource");
+ }
+ $this->out("Connected to datasource");
+ }
+}
+EOF
+
+pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+
+until ./Console/cake databaseTest > "$OUTPUT" 2>&1; do
+ >&2 echo "Database is unavailable - sleeping"
+ sleep 1
+done
+
+rm -f "$DATABASE_TEST_SCRIPT"
+
+popd > "$OUTPUT" 2>&1
+
+# We only want to run the setup script once since it creates
+# state in the database. Until COmanage Registry has a better
+# mechanism for telling us if setup has already been run
+# we create an ephemeral CakePHP script to tell us.
+SETUP_ALREADY_SCRIPT="$COMANAGE_REGISTRY_DIR/app/Console/Command/SetupAlreadyShell.php"
+
+cat > $SETUP_ALREADY_SCRIPT <<"EOF"
+Co->find('first', $args);
+ } catch (CakeException $e) {
+ $this->out('Not setup already');
+ }
+
+ if(empty($co)) {
+ $this->out('Not setup already');
+ } else {
+ $this->error('Setup already');
+ }
+ }
+}
+EOF
+
+pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+./Console/cake setupAlready > "$OUTPUT" 2>&1
+setup_already=$?
+
+rm -f "$SETUP_ALREADY_SCRIPT"
+
+if [ $setup_already -eq 0 ]; then
+ rm -f "$COMANAGE_REGISTRY_DIR/local/Config/security.salt" > "$OUTPUT" 2>&1
+ rm -f "$COMANAGE_REGISTRY_DIR/local/Config/security.seed" > "$OUTPUT" 2>&1
+ # Run database twice until issue on develop branch is resolved. Since
+ # the command is idempotent normally it is not a problem to have it run
+ # more than once.
+ ./Console/cake database > "$OUTPUT" 2>&1 && \
+ ./Console/cake database > "$OUTPUT" 2>&1 && \
+ ./Console/cake setup --admin-given-name "${COMANAGE_REGISTRY_ADMIN_GIVEN_NAME}" \
+ --admin-family-name "${COMANAGE_REGISTRY_ADMIN_FAMILY_NAME}" \
+ --admin-username "${COMANAGE_REGISTRY_ADMIN_USERNAME}" \
+ --enable-pooling "${COMANAGE_REGISTRY_ENABLE_POOLING}" > "$OUTPUT" 2>&1
+ AUTO_GENERATED_SECURITY=1
+fi
+
+popd > "$OUTPUT" 2>&1
+
+# If COmanage Registry CakePHP security salt and seed have been
+# injected and the files do not otherwise exist create them.
+if [[ -n "$COMANAGE_REGISTRY_SECURITY_SALT" && ( -n "$AUTO_GENERATED_SECURITY" || ! -e "$COMANAGE_REGISTRY_DIR/local/Config/security.salt" ) ]]; then
+ echo "$COMANAGE_REGISTRY_SECURITY_SALT" > "$COMANAGE_REGISTRY_DIR/local/Config/security.salt"
+fi
+
+if [[ -n "$COMANAGE_REGISTRY_SECURITY_SEED" && ( -n "$AUTO_GENERATED_SECURITY" || ! -e "$COMANAGE_REGISTRY_DIR/local/Config/security.seed" ) ]]; then
+ echo "$COMANAGE_REGISTRY_SECURITY_SEED" > "$COMANAGE_REGISTRY_DIR/local/Config/security.seed"
+fi
+
+# We always run upgradeVersion since it will not make any changes
+# if the current and target versions are the same or if
+# an upgrade from the current to the target version is not allowed.
+pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+
+./Console/cake upgradeVersion "${COMANAGE_REGISTRY_UPGRADE_VERSION_OPTS}" > "$OUTPUT" 2>&1
+
+popd > "$OUTPUT" 2>&1
+
+# Force a datbase update if requested. This is helpful when deploying
+# a new version of the code that does not result in a change in the
+# version number and so upgradeVersion does not fire. An example
+# of this scenario is when new code is introduced in the develop
+# branch but before a release happens.
+if [ -n "$COMANAGE_REGISTRY_DATABASE_SCHEMA_FORCE" ]; then
+ echo "Forcing a database schema update..." > "$OUTPUT" 2>&1
+ pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+ ./Console/cake database > "$OUTPUT" 2>&1
+ popd > "$OUTPUT" 2>&1
+fi
+
+# Enable any supported non-core plugins if requested.
+if [ -n "$COMANAGE_REGISTRY_ENABLE_PLUGIN" ]; then
+ plugins=(`echo "$COMANAGE_REGISTRY_ENABLE_PLUGIN" | sed -e 's@,@ @'`) > "$OUTPUT" 2>&1
+ for plugin in "${plugins[@]}";
+ do
+ echo "Enabling available plugin $plugin..." > "$OUTPUT" 2>&1
+ pushd "$COMANAGE_REGISTRY_DIR/local/Plugin" > "$OUTPUT" 2>&1
+ ln -s "../../app/AvailablePlugin/$plugin" "$plugin" > "$OUTPUT" 2>&1
+ popd > "$OUTPUT" 2>&1
+ pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+ ./Console/cake database > "$OUTPUT" 2>&1
+ popd > "$OUTPUT" 2>&1
+ done
+fi
+
+# Remove any cache files generated thus far.
+find "$COMANAGE_REGISTRY_DIR/app/tmp/cache" -type f -exec rm -f {} \;
+
+# If defined use configured location of Apache HTTP Server
+# HTTPS certificate and key files. The certificate file may also
+# include intermediate CA certificates, sorted from leaf to root.
+if [ -n "$HTTPS_CERT_FILE" ]; then
+ rm -f /etc/httpd/cert.pem
+ cp "$HTTPS_CERT_FILE" /etc/httpd/cert.pem
+ chown apache /etc/httpd/cert.pem
+ chmod 0644 /etc/httpd/cert.pem
+fi
+
+if [ -n "$HTTPS_PRIVKEY_FILE" ]; then
+ rm -f /etc/httpd/privkey.pem
+ cp "$HTTPS_PRIVKEY_FILE" /etc/httpd/privkey.pem
+ chown apache /etc/httpd/privkey.pem
+ chmod 0600 /etc/httpd/privkey.pem
+fi
+
+# If SERVER_NAME has not been injected try to determine
+# it from the HTTPS_CERT_FILE.
+if [ -z "$SERVER_NAME" ]; then
+ SERVER_NAME=`openssl x509 -in /etc/httpd/cert.pem -text -noout | sed -n '/X509v3 Subject Alternative Name:/ {n;p}' | sed -E 's/.*DNS:(.*)\s*$/\1/'`
+ if [ -z "$SERVER_NAME" ]; then
+ SERVER_NAME=`openssl x509 -in /etc/httpd/cert.pem -subject -noout | sed -E 's/subject=.*CN=(.*)\s*/\1/'`
+ fi
+fi
+
+# Configure Apache HTTP Server with the server name.
+sed -i -e s@%%SERVER_NAME%%@"${SERVER_NAME:-unknown}"@g /etc/httpd/conf.d/000-comanage.conf
+
+# If ENV or USERTOKEN as injected by the deployer contain a semi-colon remove it.
+if [[ $ENV =~ .*";".* ]]; then
+ ENV=`echo $ENV | tr -d ';'`
+ export ENV
+fi
+
+if [[ $USERTOKEN =~ .*";".* ]]; then
+ USERTOKEN=`echo $USERTOKEN | tr -d ';'`
+ export USERTOKEN
+fi
+
+# If ENV or USERTOKEN as injected by the deployer contain a space remove it.
+if [[ $ENV =~ [[:space:]] ]]; then
+ ENV=`echo $ENV | tr -d [:space:]`
+ export ENV
+fi
+
+if [[ $USERTOKEN =~ [[:space:]] ]]; then
+ USERTOKEN=`echo $USERTOKEN | tr -d [:space:]`
+ export USERTOKEN
+fi
+
+# Create pipes to use for COmanage Registry instead of standard log files.
+rm -f "$COMANAGE_REGISTRY_DIR/app/tmp/logs/error.log" > "$OUTPUT" 2>&1
+rm -f "$COMANAGE_REGISTRY_DIR/app/tmp/logs/debug.log" > "$OUTPUT" 2>&1
+mkfifo -m 666 "$COMANAGE_REGISTRY_DIR/app/tmp/logs/error.log" > "$OUTPUT" 2>&1
+mkfifo -m 666 "$COMANAGE_REGISTRY_DIR/app/tmp/logs/debug.log" > "$OUTPUT" 2>&1
+
+# Format any output from COmanange Registry into standard TIER form.
+(cat <> "$COMANAGE_REGISTRY_DIR/app/tmp/logs/error.log" | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "comanage_registry;error.log;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe)&
+(cat <> "$COMANAGE_REGISTRY_DIR/app/tmp/logs/debug.log" | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "comanage_registry;debug.log;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe)&
+
+# Start Apache HTTP Server
+exec /usr/sbin/httpd -DFOREGROUND
diff --git a/docker-comanage-shibboleth-sp-entrypoint b/docker-comanage-shibboleth-sp-entrypoint
new file mode 100755
index 0000000..11527b8
--- /dev/null
+++ b/docker-comanage-shibboleth-sp-entrypoint
@@ -0,0 +1,127 @@
+#!/bin/bash
+
+# COmanage Registry Shibboleth SP Dockerfile entrypoint
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [ -n "$COMANAGE_DEBUG" ]
+then
+ OUTPUT=/dev/stdout
+else
+ OUTPUT=/dev/null
+fi
+
+# Configuration details that may be injected through environment
+# variables or the contents of files.
+#
+# SHIBBOLETH_SP_METADATA_PROVIDER_XML may also be injected in the
+# same way but because of the presence of special characters in the
+# XML it is handled differently.
+
+injectable_config_vars=(
+ SHIBBOLETH_SP_ENTITY_ID
+ SHIBBOLETH_SP_CERT
+ SHIBBOLETH_SP_PRIVKEY
+ SHIBBOLETH_SP_SAMLDS_URL
+)
+
+# If the file associated with a configuration variable is present then
+# read the value from it into the appropriate variable. So for example
+# if the variable COMANAGE_REGISTRY_DATASOURCE_FILE exists and its
+# value points to a file on the file system then read the contents
+# of that file into the variable COMANAGE_REGISTRY_DATASOURCE.
+
+for config_var in "${injectable_config_vars[@]}"
+do
+ eval file_name=\$"${config_var}_FILE";
+
+ if [ -e "$file_name" ]; then
+ payload=`cat $file_name`
+ declare "${config_var}"="${payload}"
+ fi
+done
+
+# If no shibboleth2.xml file is present then create one using
+# injected information or defaults that are not particularly
+# useful in a federated context but will allow shibd to start.
+if [ ! -e /etc/shibboleth/shibboleth2.xml ]; then
+ cp /etc/shibboleth/shibboleth2.xml.template /etc/shibboleth/shibboleth2.xml
+ sed -i -e s@%%SHIBBOLETH_SP_ENTITY_ID%%@"${SHIBBOLETH_SP_ENTITY_ID:-https://comanage.registry/shibboleth}"@ /etc/shibboleth/shibboleth2.xml
+ sed -i -e s@%%SHIBBOLETH_SP_SAMLDS_URL%%@"${SHIBBOLETH_SP_SAMLDS_URL:-https://localhost/registry/pages/eds/index}"@ /etc/shibboleth/shibboleth2.xml
+
+ # The metadata provider injected input most likely contains special characters
+ # so use a sed script instead of simple substitution on the command line.
+
+ if [ -n "$SHIBBOLETH_SP_METADATA_PROVIDER_XML_FILE" ]; then
+ xml_content_file="$SHIBBOLETH_SP_METADATA_PROVIDER_XML_FILE"
+ else
+ xml_content_file=`/bin/mktemp`
+ echo ${SHIBBOLETH_SP_METADATA_PROVIDER_XML:-} > ${xml_content_file}
+ fi
+
+ sed_script_file=`/bin/mktemp`
+ cat > ${sed_script_file}< "$OUTPUT" 2>&1
+mkfifo -m 666 /tmp/logpipe > "$OUTPUT" 2>&1
+cat <> /tmp/logpipe &
+
+# Format any console output from httpd into standard TIER form.
+rm -f /tmp/loghttpd > "$OUTPUT" 2>&1
+mkfifo -m 666 /tmp/loghttpd > "$OUTPUT" 2>&1
+(cat <> /tmp/loghttpd | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "httpd;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe 2>&1)&
+
+# Format any console output from shibd into standard TIER form.
+rm -f /tmp/logshibd > "$OUTPUT" 2>&1
+mkfifo -m 666 /tmp/logshibd > "$OUTPUT" 2>&1
+(cat <> /tmp/logshibd | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "httpd;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe 2>&1)&
+
+# Format any console output from supervisord into standard TIER form.
+rm -f /tmp/logsuperd > "$OUTPUT" 2>&1
+mkfifo -m 666 /tmp/logsuperd > "$OUTPUT" 2>&1
+(cat <> /tmp/logsuperd | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "supervisord;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe 2>&1)&
+
+# Format any output from cron into standard TIER form.
+rm -f /var/log/cron > "$OUTPUT" 2>&1
+rm -f /tmp/logcrond > "$OUTPUT" 2>&1
+mkfifo -m 666 /tmp/logcrond > "$OUTPUT" 2>&1
+ln -s /tmp/logcrond /var/log/cron > "$OUTPUT" 2>&1
+(cat <> /tmp/logcrond | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "crond;cron;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe 2>&1)&
+
+# Close stdout and stderr for this process since supervisord will write
+# to its logfile and its children are configured to write to different
+# pipes.
+exec 1<&-
+exec 2<&-
+
+# Start supervisord
+exec /usr/bin/supervisord -c /usr/local/etc/supervisord.conf
diff --git a/httpd.conf b/httpd.conf
new file mode 100644
index 0000000..3cbc05a
--- /dev/null
+++ b/httpd.conf
@@ -0,0 +1,74 @@
+# COmanage Registry Apache HTTP Server configuration
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ServerRoot "/etc/httpd"
+Listen 80
+Include conf.modules.d/*.conf
+User apache
+Group apache
+ServerAdmin root@localhost
+
+
+ AllowOverride none
+ Require all denied
+
+
+DocumentRoot "/var/www/html"
+
+
+ AllowOverride None
+ # Allow open access:
+ Require all granted
+
+
+
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+
+
+DirectoryIndex index.html
+
+
+ Require all denied
+
+
+PassEnv ENV
+PassEnv USERTOKEN
+
+ErrorLogFormat "httpd;error_log;%{ENV}e;%{USERTOKEN}e;[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"
+ErrorLog "/tmp/logpipe"
+LogLevel warn
+
+LogFormat "httpd;access_log;%{ENV}e;%{USERTOKEN}e;%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+CustomLog "/tmp/logpipe" combined
+
+TypesConfig /etc/mime.types
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+
+AddDefaultCharset UTF-8
+
+MIMEMagicFile conf/magic
+
+EnableSendfile on
+
+IncludeOptional conf.d/*.conf
diff --git a/native.logger b/native.logger
new file mode 100644
index 0000000..0b01f32
--- /dev/null
+++ b/native.logger
@@ -0,0 +1,39 @@
+# set overall behavior
+log4j.rootCategory=INFO, native_log, warn_log
+
+# fairly verbose for DEBUG, so generally leave at INFO
+log4j.category.XMLTooling.XMLObject=INFO
+log4j.category.XMLTooling.KeyInfoResolver=INFO
+log4j.category.Shibboleth.IPRange=INFO
+log4j.category.Shibboleth.PropertySet=INFO
+
+# raise for low-level tracing of SOAP client HTTP/SSL behavior
+log4j.category.XMLTooling.libcurl=INFO
+
+# useful categories to tune independently:
+#
+# tracing of SAML messages and security policies
+#log4j.category.OpenSAML.MessageDecoder=DEBUG
+#log4j.category.OpenSAML.MessageEncoder=DEBUG
+#log4j.category.OpenSAML.SecurityPolicyRule=DEBUG
+# interprocess message remoting
+#log4j.category.Shibboleth.Listener=DEBUG
+# mapping of requests to applicationId
+#log4j.category.Shibboleth.RequestMapper=DEBUG
+# high level session cache operations
+#log4j.category.Shibboleth.SessionCache=DEBUG
+# persistent storage and caching
+#log4j.category.XMLTooling.StorageService=DEBUG
+
+# define the appender
+
+log4j.appender.native_log=org.apache.log4j.FileAppender
+log4j.appender.native_log.fileName=/tmp/logpipe
+log4j.appender.native_log.layout=org.apache.log4j.PatternLayout
+log4j.appender.native_log.layout.ConversionPattern=shibd;native.log;${ENV};${USERTOKEN};%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+
+log4j.appender.warn_log=org.apache.log4j.FileAppender
+log4j.appender.warn_log.fileName=/tmp/logpipe
+log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout
+log4j.appender.warn_log.layout.ConversionPattern=shibd;native_warn.log;${ENV};${USERTOKEN};%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+log4j.appender.warn_log.threshold=WARN
diff --git a/php.conf b/php.conf
new file mode 100644
index 0000000..ffda6de
--- /dev/null
+++ b/php.conf
@@ -0,0 +1,10 @@
+
+ SetHandler application/x-httpd-php
+
+
+AddType text/html .php
+
+DirectoryIndex index.php
+
+#php_value session.save_handler "files"
+#php_value session.save_path "/var/lib/php/session"
diff --git a/sendtierbeacon.sh b/sendtierbeacon.sh
new file mode 100755
index 0000000..63e27f9
--- /dev/null
+++ b/sendtierbeacon.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# COmanage Regsitry script to send TIER beacon
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOGHOST="collector.testbed.tier.internet2.edu"
+LOGPORT="5001"
+
+messagefile="/tmp/beaconmsg"
+
+if [ -z "$TIER_BEACON_OPT_OUT" ]; then
+ cat > $messagefile </dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ echo "tier_beacon;none;$ENV;$USERTOKEN;"`date`"; TIER beacon sent"
+ else
+ echo "tier_beacon;none;$ENV;$USERTOKEN;"`date`"; Failed to send TIER beacon"
+ fi
+
+ rm -f $messagefile 1>/dev/null 2>&1
+
+fi
diff --git a/setupcron.sh b/setupcron.sh
new file mode 100755
index 0000000..3f45f05
--- /dev/null
+++ b/setupcron.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# COmanage Registry shell script to install TIER beacon crontab
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CRONFILE=/tmp/cronfile
+
+# Build and install crontab file with random start time
+# between midnight and 3:59am.
+echo "#send daily beacon to TIER Central" > ${CRONFILE}
+echo $(expr $RANDOM % 59) $(expr $RANDOM % 3) "* * * /usr/local/bin/sendtierbeacon.sh >> /tmp/logpipe 2>&1" >> ${CRONFILE}
+chmod 644 ${CRONFILE}
+crontab ${CRONFILE}
diff --git a/shibboleth.repo b/shibboleth.repo
new file mode 100644
index 0000000..393aa48
--- /dev/null
+++ b/shibboleth.repo
@@ -0,0 +1,7 @@
+[security_shibboleth]
+name=Shibboleth (CentOS_7)
+type=rpm-md
+baseurl=http://downloadcontent.opensuse.org/repositories/security:/shibboleth/CentOS_7/
+gpgcheck=1
+gpgkey=http://downloadcontent.opensuse.org/repositories/security:/shibboleth/CentOS_7/repodata/repomd.xml.key
+enabled=1
diff --git a/shibd.logger b/shibd.logger
new file mode 100644
index 0000000..41300f2
--- /dev/null
+++ b/shibd.logger
@@ -0,0 +1,63 @@
+# set overall behavior
+log4j.rootCategory=INFO, shibd_log, warn_log
+
+# fairly verbose for DEBUG, so generally leave at INFO
+log4j.category.XMLTooling.XMLObject=INFO
+log4j.category.XMLTooling.KeyInfoResolver=INFO
+log4j.category.Shibboleth.IPRange=INFO
+log4j.category.Shibboleth.PropertySet=INFO
+
+# raise for low-level tracing of SOAP client HTTP/SSL behavior
+log4j.category.XMLTooling.libcurl=INFO
+
+# useful categories to tune independently:
+#
+# tracing of SAML messages and security policies
+#log4j.category.OpenSAML.MessageDecoder=DEBUG
+#log4j.category.OpenSAML.MessageEncoder=DEBUG
+#log4j.category.OpenSAML.SecurityPolicyRule=DEBUG
+#log4j.category.XMLTooling.SOAPClient=DEBUG
+# interprocess message remoting
+#log4j.category.Shibboleth.Listener=DEBUG
+# mapping of requests to applicationId
+#log4j.category.Shibboleth.RequestMapper=DEBUG
+# high level session cache operations
+#log4j.category.Shibboleth.SessionCache=DEBUG
+# persistent storage and caching
+#log4j.category.XMLTooling.StorageService=DEBUG
+
+# logs XML being signed or verified if set to DEBUG
+log4j.category.XMLTooling.Signature.Debugger=INFO, sig_log
+log4j.additivity.XMLTooling.Signature.Debugger=false
+
+# the tran log blocks the "default" appender(s) at runtime
+# Level should be left at INFO for this category
+log4j.category.Shibboleth-TRANSACTION=INFO, tran_log
+log4j.additivity.Shibboleth-TRANSACTION=false
+# uncomment to suppress particular event types
+#log4j.category.Shibboleth-TRANSACTION.AuthnRequest=WARN
+#log4j.category.Shibboleth-TRANSACTION.Login=WARN
+#log4j.category.Shibboleth-TRANSACTION.Logout=WARN
+
+# define the appenders
+
+log4j.appender.shibd_log=org.apache.log4j.FileAppender
+log4j.appender.shibd_log.fileName=/tmp/logpipe
+log4j.appender.shibd_log.layout=org.apache.log4j.PatternLayout
+log4j.appender.shibd_log.layout.ConversionPattern=shibd;shibd.log;${ENV};${USERTOKEN};%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+
+log4j.appender.warn_log=org.apache.log4j.FileAppender
+log4j.appender.warn_log.fileName=/tmp/logpipe
+log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout
+log4j.appender.warn_log.layout.ConversionPattern=shibd;shibd_warn.log;${ENV};${USERTOKEN};%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+log4j.appender.warn_log.threshold=WARN
+
+log4j.appender.tran_log=org.apache.log4j.FileAppender
+log4j.appender.tran_log.fileName=/tmp/logpipe
+log4j.appender.tran_log.layout=org.apache.log4j.PatternLayout
+log4j.appender.tran_log.layout.ConversionPattern=shibd;transaction.log;${ENV};${USERTOKEN};%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
+
+log4j.appender.sig_log=org.apache.log4j.FileAppender
+log4j.appender.sig_log.fileName=/tmp/logpipe
+log4j.appender.sig_log.layout=org.apache.log4j.PatternLayout
+log4j.appender.sig_log.layout.ConversionPattern=shibd;signature.log${ENV};${USERTOKEN};%m
diff --git a/supervisord.conf b/supervisord.conf
new file mode 100644
index 0000000..6130af4
--- /dev/null
+++ b/supervisord.conf
@@ -0,0 +1,45 @@
+; COmanage Registry Docker supervisord configuration
+;
+; Portions licensed to the University Corporation for Advanced Internet
+; Development, Inc. ("UCAID") under one or more contributor license agreements.
+; See the NOTICE file distributed with this work for additional information
+; regarding copyright ownership.
+;
+; UCAID licenses this file to you under the Apache License, Version 2.0
+; (the "License"); you may not use this file except in compliance with the
+; License. You may obtain a copy of the License at:
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+[supervisord]
+logfile=/tmp/logsuperd
+logfile_maxbytes=0
+nodaemon=true
+user=root
+
+[program:httpd]
+command=/usr/local/bin/docker-comanage-entrypoint
+stdout_logfile=/tmp/loghttpd
+stdout_logfile_maxbytes=0
+stderr_logfile=/tmp/loghttpd
+stderr_logfile_maxbytes=0
+
+[program:shibd]
+command=/usr/local/bin/docker-comanage-shibboleth-sp-entrypoint
+stdout_logfile=/tmp/logshibd
+stdout_logfile_maxbytes=0
+stderr_logfile=/tmp/logshibd
+stderr_logfile_maxbytes=0
+
+[program:crond]
+command=/usr/sbin/crond -i -m off -n
+stdout_logfile=/tmp/logcrond
+stdout_logfile_maxbytes=0
+stderr_logfile=/tmp/logcrond
+stderr_logfile_maxbytes=0