diff --git a/Dockerfile b/Dockerfile
index 44fce78..06810e5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -18,9 +18,10 @@ RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime \
&& echo "NETWORKING=yes" > /etc/sysconfig/network
RUN rm -fr /var/cache/yum/* && yum clean all && yum -y install --setopt=tsflags=nodocs epel-release && yum -y update && \
- yum -y install net-tools wget curl tar unzip mlocate logrotate strace telnet man vim rsyslog cron httpd mod_ssl dos2unix && \
+ yum -y install net-tools wget curl tar unzip mlocate logrotate strace telnet man vim rsyslog cron httpd mod_ssl dos2unix cronie supervisor && \
yum clean all
+#install shibboleth, cleanup httpd
RUN curl -o /etc/yum.repos.d/security:shibboleth.repo \
http://download.opensuse.org/repositories/security://shibboleth/CentOS_7/security:shibboleth.repo \
&& yum -y install shibboleth.x86_64 \
@@ -33,13 +34,10 @@ RUN curl -o /etc/yum.repos.d/security:shibboleth.repo \
RUN LD_LIBRARY_PATH="/opt/shibboleth/lib64"
RUN export LD_LIBRARY_PATH
-ADD ./container_files/system/httpd-shib-foreground /usr/local/bin/
ADD ./container_files/system/shibboleth_keygen.sh /usr/local/bin/
ADD ./container_files/httpd/ssl.conf /etc/httpd/conf.d/
ADD ./container_files/shibboleth/* /etc/shibboleth/
-
-RUN chmod +x /usr/local/bin/httpd-shib-foreground \
- && chmod +x /usr/local/bin/shibboleth_keygen.sh
+RUN chmod +x /usr/local/bin/shibboleth_keygen.sh
# fix httpd logging to tier format
RUN sed -i 's/LogFormat "/LogFormat "httpd;access_log;%{ENV}e;%{USERTOKEN}e;/g' /etc/httpd/conf/httpd.conf \
@@ -51,11 +49,31 @@ RUN sed -i 's/LogFormat "/LogFormat "httpd;access_log;%{ENV}e;%{USERTOKEN}e;/g'
&& sed -i '/UseCanonicalName/c\UseCanonicalName On' /etc/httpd/conf/httpd.conf
# add a basic page to shibb's default protected directory
-RUN mkdir -p /var/www/html/secure/
+RUN mkdir -p /var/www/html/secure/; mkdir -p /opt/tier/
ADD container_files/httpd/index.html /var/www/html/secure/
+# setup crond and supervisord
+ADD container_files/system/startup.sh /usr/local/bin/
+ADD container_files/system/setupcron.sh /usr/local/bin/
+ADD container_files/system/setenv.sh /opt/tier/
+ADD container_files/system/sendtierbeacon.sh /usr/local/bin/
+ADD container_files/system/supervisord.conf /etc/supervisor/
+RUN mkdir -p /etc/supervisor/conf.d \
+ && chmod +x /usr/local/bin/setupcron.sh \
+ && chmod +x /usr/local/bin/sendtierbeacon.sh \
+# setup cron
+ && /usr/local/bin/setupcron.sh
+
+#set cron to not require a login session
+RUN sed -i '/session required pam_loginuid.so/c\#session required pam_loginuid.so' /etc/pam.d/crond
+
+
EXPOSE 80 443
-CMD ["httpd-shib-foreground"]
+HEALTHCHECK --interval=1m --timeout=30s \
+ CMD curl -k -f https://127.0.0.1:8443/Shibboleth.sso/Status || exit 1
+
+
+CMD ["/usr/local/bin/startup.sh"]
diff --git a/README.md b/README.md
index c66928e..3c2eced 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,34 @@
-# shibboleth-sp
+# TIER shibboleth-sp
[](https://jenkins.testbed.tier.internet2.edu/job/docker/shib-sp/master)
-This is the TIER upstream Shibboleth SP container.
-
-It is based from CentOS 7 and includes httpd, mod_ssl, and the current shibboleth SP.
-
-Files you must supply/override in your downstream builds:
-
-The SP's private key and corresponding certificate (very important!) can be generated in your downstream container like this:
- RUN /usr/local/bin/shibboleth_keygen.sh -o /etc/shibboleth -f
-
- ...that command generates/overwrites the following files:
- /etc/shibboleth/sp-key.pem
-
- /etc/shibboleth/sp-cert.pem
-
-/etc/httpd/conf.d/ssl.conf
- including:
- ServerName fqdn:port
- UseCanonicalName On
-
-/etc/shibboleth/shibboleth2.xml
- including:
- entityID
+This is the TIER upstream Shibboleth SP container.
+
+It is based from CentOS 7 and includes httpd, mod_ssl, and the current shibboleth SP.
+
+Files you must supply/override in your downstream builds:
+
+1. The SP's ***private key and corresponding certificate*** (very important!), which can be generated in your downstream container like this:
+> RUN /usr/local/bin/shibboleth_keygen.sh -o /etc/shibboleth -f
+>
+> ...that command generates/overwrites the following files:
+> /etc/shibboleth/sp-key.pem
+> /etc/shibboleth/sp-cert.pem
+
+2. ***/etc/httpd/conf.d/ssl.conf***
+> including:
+> ServerName fqdn:port
+> UseCanonicalName On
+
+3. ***/etc/shibboleth/shibboleth2.xml***
+> including:
+> entityID
+
+ ***New in the 3.0 release:***
+>The image is based from the public CentOS7 image
+>The TIER logging format has been implemented for shibd and httpd
+>Everything now runs under supervisord
+>The TIER Beacon has been implemented
+>The file */etc/httpd/conf.d/ssl.conf* is now the default CentOS7 file
diff --git a/container_files/system/httpd-shib-foreground b/container_files/system/httpd-shib-foreground
deleted file mode 100755
index 60a415f..0000000
--- a/container_files/system/httpd-shib-foreground
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-set -e
-
-# Apache gets grumpy about PID files pre-existing
-rm -f /etc/httpd/logs/httpd.pid
-
-(/usr/sbin/shibd) & httpd -DFOREGROUND
diff --git a/container_files/system/sendtierbeacon.sh b/container_files/system/sendtierbeacon.sh
new file mode 100755
index 0000000..7496968
--- /dev/null
+++ b/container_files/system/sendtierbeacon.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+LOGHOST="collector.testbed.tier.internet2.edu"
+LOGPORT="5001"
+if [ -s /opt/tier/env.bash ]; then
+ . /opt/tier/env.bash
+fi
+
+#JSON/REST style
+LOGTEXT="{ \"msgType\" : \"TIERBEACON\", \"msgName\" : \"TIER\", \"msgVersion\" : \"1.0\", \"tbProduct\" : \"$IMAGENAME\", \"tbProductVersion\" : \"$VERSION\", \"tbTIERRelease\" : \"$TIERVERSION\", \"tbMaintainer\" : \"$MAINTAINER\" }"
+
+
+if [ -z "$TIER_BEACON_OPT_OUT" ]; then
+ #send JSON
+ echo $LOGTEXT > msgjson.txt
+ curl -s -XPOST "${LOGHOST}:${LOGPORT}/" -H 'Content-Type: application/json' -T msgjson.txt 1>/dev/null
+ 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 msgjson.txt
+
+ #below is for syslog, F-TICKS style
+ #`logger -n $LOGHOST -P $LOGPORT -t TIERBEACON $LOGTEXT`
+
+fi
+
diff --git a/container_files/system/setenv.sh b/container_files/system/setenv.sh
new file mode 100755
index 0000000..55c8c89
--- /dev/null
+++ b/container_files/system/setenv.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+printenv | sed 's/^\(.*\)$/\1/g' | grep -E "^VERSION" > /opt/tier/env.bash
+printenv | sed 's/^\(.*\)$/\1/g' | grep -E "^TIERVERSION" >> /opt/tier/env.bash
+printenv | sed 's/^\(.*\)$/\1/g' | grep -E "^IMAGE" >> /opt/tier/env.bash
+printenv | sed 's/^\(.*\)$/\1/g' | grep -E "^MAINTAINER" >> /opt/tier/env.bash
+
diff --git a/container_files/system/setupcron.sh b/container_files/system/setupcron.sh
new file mode 100755
index 0000000..3cabd35
--- /dev/null
+++ b/container_files/system/setupcron.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+CRONFILE=/opt/tier/tier-cron
+
+#set env vars for cron job
+# this script creates /opt/tier/env.bash which is sourced by the cron job's script, which was not seeing the environment set by the Dockerfile
+/opt/tier/setenv.sh
+
+#build 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 >> /var/log/cron.log 2>&1" >> ${CRONFILE}
+chmod 644 ${CRONFILE}
+
+#install crontab
+crontab ${CRONFILE}
+
+#create cron logfile
+touch /var/log/cron.log
+
diff --git a/container_files/system/startup.sh b/container_files/system/startup.sh
new file mode 100755
index 0000000..b5f0d3a
--- /dev/null
+++ b/container_files/system/startup.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+#for passed-in env vars, remove spaces and replace any ; with : in usertoken env var since we will use ; as a delimiter
+export USERTOKEN="${USERTOKEN//;/:}"
+export USERTOKEN="${USERTOKEN// /}"
+export ENV="${ENV//;/:}"
+export ENV="${ENV// /}"
+
+# generic console logging pipe for anyone
+mkfifo -m 666 /tmp/logpipe
+cat <> /tmp/logpipe 1>&2 &
+
+mkfifo -m 666 /tmp/logcrond
+(cat <> /tmp/logcrond | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "crond;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) &
+
+mkfifo -m 666 /tmp/loghttpd
+(cat <> /tmp/loghttpd | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "httpd;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) &
+
+mkfifo -m 666 /tmp/logsuperd
+(cat <> /tmp/logsuperd | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "supervisord;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) &
+
+mkfifo -m 666 /tmp/logshibd
+(cat <> /tmp/logshibd | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "shibd;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) &
+
+#launch supervisord
+/usr/bin/supervisord -c /etc/supervisor/supervisord.conf
+
diff --git a/container_files/system/supervisord.conf b/container_files/system/supervisord.conf
new file mode 100644
index 0000000..e25dd78
--- /dev/null
+++ b/container_files/system/supervisord.conf
@@ -0,0 +1,37 @@
+[supervisord]
+logfile=/tmp/logsuperd
+logfile_maxbytes=0
+loglevel=error
+nodaemon=true
+user=root
+
+[program:cron]
+command=/usr/sbin/crond -n
+autostart=true
+autorestart=true
+stdout_logfile=/tmp/logcrond
+stdout_logfile_maxbytes=0
+stderr_logfile=/tmp/logcrond
+stderr_logfile_maxbytes=0
+directory=/usr/bin
+
+[program:httpd]
+command=httpd -DFOREGROUND
+autostart=true
+autorestart=true
+stdout_logfile=/tmp/loghttpd
+stdout_logfile_maxbytes=0
+stderr_logfile=/tmp/loghttpd
+stderr_logfile_maxbytes=0
+
+[program:shibd]
+command=/usr/sbin/shibd
+autostart=true
+autorestart=true
+stdout_logfile=/tmp/logshibd
+stdout_logfile_maxbytes=0
+stderr_logfile=/tmp/logshibd
+stderr_logfile_maxbytes=0
+
+[include]
+files=/etc/supervisor/conf.d/*
diff --git a/tests/clairscan.sh b/tests/clairscan.sh
new file mode 100755
index 0000000..a06ea78
--- /dev/null
+++ b/tests/clairscan.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+startsecs=$(date +'%s')
+starttime=$(date +%H:%M:%S)
+
+echo 'starting:' ${starttime}
+
+#ensure clair-scanner
+if [ ! -s ./clair-scanner ]; then
+ echo 'downloading curl-scanner...'
+ curl -s -L -o ./clair-scanner https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
+ chmod 755 clair-scanner
+else
+ echo 'using existing clair-scanner...'
+fi
+
+#ensure DB container
+echo 'ensuring a fresh clair-db container...'
+docker ps | grep clair-db &>/dev/null
+if [ $? == "0" ]; then
+ echo 'removing existing clair-db container...'
+ docker kill db &>/dev/null
+ docker rm db &>/dev/null
+ docker run -p 5432:5432 -d --name db arminc/clair-db:latest &>/dev/null
+else
+ docker run -p 5432:5432 -d --name db arminc/clair-db:latest &>/dev/null
+fi
+sleep 30
+
+#ensure clair-scan container
+echo 'ensuring a fresh clair-scan container...'
+docker ps | grep clair-local-scan &>/dev/null
+if [ $? == "0" ]; then
+ echo 'removing existing clair-scan container...'
+ docker kill clair &>/dev/null
+ docker rm clair &>/dev/null
+ docker run -p 6060:6060 --link db:postgres -d --name clair arminc/clair-local-scan:v2.0.5 &>/dev/null
+else
+ docker run -p 6060:6060 --link db:postgres -d --name clair arminc/clair-local-scan:v2.0.5 &>/dev/null
+fi
+sleep 30
+
+#get ip where clair-scanner will listen
+clairip=$(/sbin/ifconfig docker0 | grep 'inet ' | sed 's/^[[:space:]]*//g' | cut -f 2 -d ' ' | sed 's/^[[:space:]]*//g')
+echo 'sending ip addr' ${clairip} 'to clair-scan server...'
+
+#run scan
+echo 'running scan...'
+./clair-scanner --ip ${clairip} $1
+retcode=$?
+
+#eval results
+if [ $retcode == '0' ]; then
+ echo 'scan found nothing.'
+else
+ echo 'scan found issues.'
+fi
+
+#cleanup
+echo 'removing temporary containers...'
+docker kill clair &>/dev/null
+docker rm clair &>/dev/null
+docker kill db &>/dev/null
+docker rm db &>/dev/null
+
+endsecs=$(date +'%s')
+endtime=$(date +%H:%M:%S)
+echo 'finished:' $endtime ' ('$((endsecs - startsecs)) 'seconds)'
+echo ""
+
+#pass along return code from scan
+exit $retcode
+
diff --git a/tests/image.bats b/tests/image.bats
index 3d9fb5e..2ab8f4b 100644
--- a/tests/image.bats
+++ b/tests/image.bats
@@ -26,3 +26,6 @@ load ../common
docker run -i $maintainer/$imagename find /usr/local/bin/httpd-shib-foreground
}
+@test "070 There are no known security vulnerabilities" {
+ ./tests/clairscan.sh ${maintainer}/${imagename}:latest
+}