diff --git a/Dockerfile b/Dockerfile index 84b0e06..b462124 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,40 +1,83 @@ FROM centos:centos8 -RUN dnf install -y @freeradius freeradius-utils freeradius-mysql net-tools +#run-time settings and defaults +ENV DB_LOCATION=local \ + DB_DRIVER=rlm_sql_mysql \ + DB_DIALECT=mysql \ + DB_HOST=localhost \ + DB_PORT=3306 \ + DB_ROOT_PWD=SuperStrongPassword \ + DB_USER=radius \ + DB_USER_PWD=SuperStrongPassword \ + DB_NAME=radius \ + ENV=dev \ + USERTOKEN=nothing \ +################## \ +### OTHER VARS ### \ +################## \ + VERSION=3.0.x \ + TIERVERSION=20200222 \ + IMAGENAME=radius \ + MAINTAINER=tier +# 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 scalaing 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 -RUN ln -s /etc/raddb/mods-available/sql /etc/raddb/mods-enabled/ && chgrp -h radiusd /etc/raddb/mods-enabled/sql +#install/enable required packages +RUN dnf install -y epel-release +RUN dnf install -y \ + @freeradius freeradius-utils freeradius-mysql \ + net-tools unzip cronie curl openssl supervisor \ + @httpd @php php-{cli,curl,mysqlnd,devel,gd,pear,mbstring,xml,pear} +RUN pear install MDB2 DB && ln -s /etc/raddb/mods-available/sql /etc/raddb/mods-enabled/ && chgrp -h radiusd /etc/raddb/mods-enabled/sql +RUN dnf module install -y mariadb -#commands to apply local config to radius' sql config -#RUN sed -i 's/\"rlm_sql_null\"/\"rlm_sql_mysql\"/' /etc/raddb/mods-available/sql \ -#&& sed -i 's/\"sqlite\"/\"mysql\"/' /etc/raddb/mods-available/sql \ -#&& sed -i '/server = \"localhost\"/s/^#*//g' /etc/raddb/mods-available/sql \ -#&& sed -i 's/\"localhost\"/\"${DB_HOST}\"/' /etc/raddb/mods-available/sql \ -#&& sed -i '/port = \"3306\"/s/^#*//g' /etc/raddb/mods-available/sql \ -#&& sed -i 's/\"3306\"/\"${DB_PORT}\"/' /etc/raddb/mods-available/sql \ -#&& sed -i '/login = \"radius\"/s/^#*//g' /etc/raddb/mods-available/sql \ -#&& sed -i 's/login = \"radius\"/login = \"${DB_USER}\"/' /etc/raddb/mods-available/sql \ -#&& sed -i '/password = \"SuperStrongPassword\"/s/^#*//g' /etc/raddb/mods-available/sql \ -#&& sed -i 's/\"SuperStrongPassword\"/\"${DB_PWD}\"/' /etc/raddb/mods-available/sql \ -#&& sed -i 's/radius_db = \"radius\"/radius_db = \"${DB_NAME}\"/' /etc/raddb/mods-available/sql +#install/configure Daloradius UI +RUN curl -L -O 'https://github.com/lirantal/daloradius/archive/master.zip' \ + && unzip master.zip \ + && rm master.zip \ + && mv daloradius-master/ /opt/daloradius \ + && rm -rf /var/www/html \ + && cp -r /opt/daloradius /var/www/html \ + && chown -R apache:apache /var/www/html/ \ + && mkdir -p /run/php-fpm/ +#configure supervisord and crond +RUN mkdir -p /opt/tier/ +ADD container_files/setenv.sh /opt/tier/setenv.sh +ADD container_files/setupcron.sh /usr/local/bin/setupcron.sh +ADD container_files/sendtierbeacon.sh /usr/local/bin/sendtierbeacon.sh +ADD container_files/supervisord_with_db.conf /etc/supervisor/ +ADD container_files/supervisord_no_db.conf /etc/supervisor/ +ADD container_files/startup.sh /usr/local/bin/ +RUN mkdir -p /etc/supervisor/conf.d && chmod +x /opt/tier/setenv.sh \ + && chmod +x /usr/local/bin/setupcron.sh \ + && chmod +x /usr/local/bin/sendtierbeacon.sh \ + && chmod +x /usr/local/bin/startup.sh \ +# setup cron + && /usr/local/bin/setupcron.sh \ +# set cron to not require a login session + && sed -i '/session required pam_loginuid.so/c\#session required pam_loginuid.so' /etc/pam.d/crond +#setup logging +RUN sed -i 's/LogFormat "/LogFormat "httpd;access_log;%{ENV}e;%{USERTOKEN}e;/g' /etc/httpd/conf/httpd.conf \ + && echo -e "\nErrorLogFormat \"httpd;error_log;%{ENV}e;%{USERTOKEN}e;[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i\"" >> /etc/httpd/conf/httpd.conf \ + && sed -i 's/CustomLog "logs\/access_log"/CustomLog "\/tmp\/logpipe"/g' /etc/httpd/conf/httpd.conf \ + && sed -i 's/ErrorLog "logs\/error_log"/ErrorLog "\/tmp\/logpipe"/g' /etc/httpd/conf/httpd.conf \ + && echo -e "\nPassEnv ENV" >> /etc/httpd/conf/httpd.conf \ + && echo -e "\nPassEnv USERTOKEN" >> /etc/httpd/conf/httpd.conf \ + && touch /tmp/daloradius.log && chmod 755 /var/log/radius/ && touch /var/log/radius/radius.log && chmod 644 /var/log/radius/radius.log -#install httpd and php +VOLUME /var/lib/mysql - - -#install Daloradius - - - -#script for use in starting radius only when dependent services are available -# example for downstream Dockerfile: CMD ["/wait-for-it.sh","-q","db:3306","--","/usr/sbin/radiusd","-fl","stdout"] -COPY container_files/wait-for-it.sh / -RUN chmod 755 /wait-for-it.sh - -EXPOSE 1812/udp 1813/udp +EXPOSE 1812/udp 1813/udp 443 #healthcheck command so that the container's state is known HEALTHCHECK CMD netstat -an | grep udp | grep 1812 > /dev/null; if [ 0 != $? ]; then exit 1; fi; -CMD ["/usr/sbin/radiusd","-fl","stdout"] +CMD /usr/local/bin/startup.sh + diff --git a/container_files/docker-entrypoint.sh b/container_files/docker-entrypoint.sh deleted file mode 100644 index 900ad6b..0000000 --- a/container_files/docker-entrypoint.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -set -e - -# this if will check if the first argument is a flag -# but only works if all arguments require a hyphenated flag -# -v; -SL; -f arg; etc will work, but not arg1 arg2 -if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then - set -- radiusd "$@" -fi - -# check for the expected command -if [ "$1" = 'radiusd' ]; then - shift - exec radiusd -f "$@" -fi - -# debian people are likely to call "freeradius" as well, so allow that -if [ "$1" = 'freeradius' ]; then - shift - exec radiusd -f "$@" -fi - -# else default to run whatever the user wanted like "bash" or "sh" -exec "$@" diff --git a/container_files/sendtierbeacon.sh b/container_files/sendtierbeacon.sh new file mode 100644 index 0000000..a4cda01 --- /dev/null +++ b/container_files/sendtierbeacon.sh @@ -0,0 +1,31 @@ +#!/bin/bash +LOGHOST="collector.testbed.tier.internet2.edu" +LOGPORT="5001" +if [ -s /opt/tier/env.bash ]; then + . /opt/tier/env.bash +fi + +#below for syslog, F-TICKS style +#LOGTEXT="TIERBEACON/TIER/1.0#IM=$IMAGENAME#PV=$VERSION#TR=$TIERVERSION#MT=$MAINTAINER#" + +#below for 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/setenv.sh b/container_files/setenv.sh new file mode 100644 index 0000000..ccc5485 --- /dev/null +++ b/container_files/setenv.sh @@ -0,0 +1,7 @@ +#!/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 "^IMAGENAME" >> /opt/tier/env.bash +printenv | sed 's/^\(.*\)$/\1/g' | grep -E "^MAINTAINER" >> /opt/tier/env.bash +printenv | sed 's/^\(.*\)$/\1/g' | grep -E "^TIER_BEACON_OPT_OUT" >> /opt/tier/env.bash + diff --git a/container_files/setupcron.sh b/container_files/setupcron.sh new file mode 100644 index 0000000..3cabd35 --- /dev/null +++ b/container_files/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/startup.sh b/container_files/startup.sh new file mode 100644 index 0000000..3004556 --- /dev/null +++ b/container_files/startup.sh @@ -0,0 +1,90 @@ + + +#configure radius for DB +sed -i 's/\"rlm_sql_null\"/\"'${DB_DRIVER}'\"/' /etc/raddb/mods-available/sql +sed -i 's/\"sqlite\"/\"'${DB_DIALECT}'\"/' /etc/raddb/mods-available/sql +sed -i '/server = \"localhost\"/s/^#*//g' /etc/raddb/mods-available/sql +sed -i 's/\"localhost\"/\"'${DB_HOST}'\"/' /etc/raddb/mods-available/sql +sed -i '/port = 3306/s/^#*//g' /etc/raddb/mods-available/sql +sed -i 's/3306/'${DB_PORT}'/' /etc/raddb/mods-available/sql +sed -i '/login = \"radius\"/s/^#*//g' /etc/raddb/mods-available/sql +sed -i 's/login = \"radius\"/login = \"'${DB_USER}'\"/' /etc/raddb/mods-available/sql +sed -i '/password = \"radpass\"/s/^#*//g' /etc/raddb/mods-available/sql +sed -i 's/\"radpass\"/\"'${DB_USER_PWD}'\"/' /etc/raddb/mods-available/sql +sed -i 's/radius_db = \"radius\"/radius_db = \"'${DB_NAME}'\"/' /etc/raddb/mods-available/sql +sed -i 's/${dialect}/'${DB_DIALECT}'/' /etc/raddb/mods-available/sql + +#setup MariaDB, if desired +if [ ${DB_LOCATION} = "local" ]; then + mysql_install_db + chown -R mysql:mysql /var/lib/mysql/ + sed -i 's/^\(bind-address\s.*\)/# \1/' /etc/my.cnf + sed -i 's/^\(log_error\s.*\)/# \1/' /etc/my.cnf + sed -i 's/\[mysqld\]/\[mysqld\]\ncharacter_set_server = utf8/' /etc/my.cnf + sed -i 's/\[mysqld\]/\[mysqld\]\ncollation_server = utf8_general_ci/' /etc/my.cnf + sed -i 's/\[mysqld\]/\[mysqld\]\nport = 3306/' /etc/my.cnf + echo "/usr/bin/mysqld_safe &" > /tmp/config + echo "mysqladmin --silent --wait=30 ping || exit 1" >> /tmp/config + echo "mysql -e 'UPDATE mysql.user SET Password=PASSWORD(\"'${DB_ROOT_PWD}'\") WHERE User=\"root\";'" >> /tmp/config + echo "mysql -e 'DELETE FROM mysql.user WHERE User=\"\";'" >> /tmp/config + echo "mysql -e 'DELETE FROM mysql.user WHERE User=\"root\" AND Host NOT IN (\"localhost\", \"127.0.0.1\", \"::1\");'" >> /tmp/config + echo "mysql -e 'DROP DATABASE IF EXISTS test;'" >> /tmp/config + echo "mysql -e 'DELETE FROM mysql.db WHERE Db=\"test\" OR Db=\"test\\_%\";'" >> /tmp/config + echo "mysql -e 'CREATE DATABASE '${DB_NAME}';'" >> /tmp/config + echo "mysql -e 'CREATE USER \"'${DB_USER}'\"@\"localhost\" IDENTIFIED BY \"'${DB_USER_PWD}'\";'" >> /tmp/config + echo "mysql -e 'GRANT ALL ON '${DB_NAME}'.* TO \"root\"@\"localhost\";'" >> /tmp/config + echo "mysql -e 'GRANT ALL ON '${DB_NAME}'.* TO \"'${DB_USER}'\"@\"localhost\";'" >> /tmp/config + echo "mysql -u root ${DB_NAME} < /etc/raddb/mods-config/sql/main/mysql/schema.sql" >> /tmp/config + echo "mysql -u root ${DB_NAME} < /opt/daloradius/contrib/db/fr2-mysql-daloradius-and-freeradius.sql" >> /tmp/config + echo "mysql -u root ${DB_NAME} < /opt/daloradius/contrib/db/mysql-daloradius.sql" >> /tmp/config + echo "mysql -e 'FLUSH PRIVILEGES;'" >> /tmp/config + bash /tmp/config + rm -f /tmp/config +fi + +#configure Daloradius +sed -i "s/\['CONFIG_DB_USER'] = 'root'/\['CONFIG_DB_USER'] = '"${DB_USER}"'/" /var/www/html/library/daloradius.conf.php +sed -i "s/\['CONFIG_DB_PASS'] = ''/\['CONFIG_DB_PASS'] = '"${DB_USER_PWD}"'/" /var/www/html/library/daloradius.conf.php +sed -i "s/\['CONFIG_DB_NAME'] = 'radius'/\['CONFIG_DB_NAME'] = '"${DB_NAME}"'/" /var/www/html/library/daloradius.conf.php +sed -i "s/\['CONFIG_DB_HOST'] = 'localhost'/\['CONFIG_DB_HOST'] = '"${DB_HOST}"'/" /var/www/html/library/daloradius.conf.php +sed -i "s/\['CONFIG_DB_PORT'] = '3306'/\['CONFIG_DB_PORT'] = '"${DB_PORT}"'/" /var/www/html/library/daloradius.conf.php + +#generate self-signed SSL cert +openssl req -new -nodes -newkey rsa:2048 -subj "/commonName=localhost" -batch -keyout /etc/pki/tls/private/localhost.key -out localhost.csr +echo '[SAN]' > extensions +echo "subjectAltName=DNS:localhost,URI:https://localhost/" >>extensions +echo "subjectKeyIdentifier=hash" >> extensions +openssl x509 -req -days 1095 -in localhost.csr -signkey /etc/pki/tls/private/localhost.key -extensions SAN -extfile extensions -out /etc/pki/tls/certs/localhost.crt +rm -f extensions localhost.csr + +#setup pipes for logging +export USERTOKEN="${USERTOKEN//;/:}" +export USERTOKEN="${USERTOKEN// /}" +export ENV="${ENV//;/:}" +export ENV="${ENV// /}" +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/logradius +(cat <> /tmp/logradius | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "radius;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/logmysql +(cat <> /tmp/logmysql | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "mysql;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) & +mkfifo -m 666 /tmp/logmysqldb +(cat <> /tmp/logmysqldb | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "mysql;mysql.log;%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/logphpfpm +(cat <> /tmp/logphpfpm | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "phpfpm;console;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) & +mkfifo -m 666 /tmp/logidp-consent-audit +(cat <> /tmp/logidp-consent-audit | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "shib-idp;idp-consent-audit.log;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) & + +#launch supervisord +if [ ${DB_LOCATION} = "local" ]; then + /usr/bin/supervisord -c /etc/supervisor/supervisord_with_db.conf +else + /usr/bin/supervisord -c /etc/supervisor/supervisord_no_db.conf +fi + diff --git a/container_files/supervisord_no_db.conf b/container_files/supervisord_no_db.conf new file mode 100644 index 0000000..c4dd7c8 --- /dev/null +++ b/container_files/supervisord_no_db.conf @@ -0,0 +1,43 @@ +[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/local/bin + +[program:radius] +command=/usr/sbin/radiusd -f +autostart=true +autorestart=true +stdout_logfile=/tmp/logradius +stdout_logfile_maxbytes=0 +stderr_logfile=/tmp/logradius +stderr_logfile_maxbytes=0 + +[program:httpd] +command=httpd -D FOREGROUND +autostart=true +autorestart=true +stdout_logfile=/tmp/loghttpd +stdout_logfile_maxbytes=0 +redirect_stderr=true + +[program:php-fpm] +command=/usr/sbin/php-fpm -c /etc/php.ini +stdout_logfile=/tmp/logphpfpm +stdout_logfile_maxbytes=0 +stderr_logfile=/tmp/logphpfpm +stderr_logfile_maxbytes=0 + +[include] +files=/etc/supervisor/conf.d/* diff --git a/container_files/supervisord_with_db.conf b/container_files/supervisord_with_db.conf new file mode 100644 index 0000000..c81a922 --- /dev/null +++ b/container_files/supervisord_with_db.conf @@ -0,0 +1,52 @@ +[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/local/bin + +[program:radius] +command=/usr/sbin/radiusd -f +autostart=true +autorestart=true +stdout_logfile=/tmp/logradius +stdout_logfile_maxbytes=0 +stderr_logfile=/tmp/logradius +stderr_logfile_maxbytes=0 + +[program:mariadb] +command=mysqld_safe +autostart=true +autorestart=true +stdout_logfile=/tmp/logmysql +stdout_logfile_maxbytes=0 +stderr_logfile=/tmp/logmysql +stderr_logfile_maxbytes=0 + +[program:httpd] +command=httpd -D FOREGROUND +autostart=true +autorestart=true +stdout_logfile=/tmp/loghttpd +stdout_logfile_maxbytes=0 +redirect_stderr=true + +[program:php-fpm] +command=/usr/sbin/php-fpm -c /etc/php.ini +stdout_logfile=/tmp/logphpfpm +stdout_logfile_maxbytes=0 +stderr_logfile=/tmp/logphpfpm +stderr_logfile_maxbytes=0 + +[include] +files=/etc/supervisor/conf.d/* diff --git a/container_files/wait-for-it.sh b/container_files/wait-for-it.sh deleted file mode 100755 index b931da1..0000000 --- a/container_files/wait-for-it.sh +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env bash -# Use this script to test if a given TCP host/port are available - -WAITFORIT_cmdname=${0##*/} - -echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } - -usage() -{ - cat << USAGE >&2 -Usage: - $WAITFORIT_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 [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then - echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" - else - echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" - fi - WAITFORIT_start_ts=$(date +%s) - while : - do - if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then - nc -z $WAITFORIT_HOST $WAITFORIT_PORT - WAITFORIT_result=$? - else - (echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 - WAITFORIT_result=$? - fi - if [[ $WAITFORIT_result -eq 0 ]]; then - WAITFORIT_end_ts=$(date +%s) - echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" - break - fi - sleep 1 - done - return $WAITFORIT_result -} - -wait_for_wrapper() -{ - # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 - if [[ $WAITFORIT_QUIET -eq 1 ]]; then - timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & - else - timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & - fi - WAITFORIT_PID=$! - trap "kill -INT -$WAITFORIT_PID" INT - wait $WAITFORIT_PID - WAITFORIT_RESULT=$? - if [[ $WAITFORIT_RESULT -ne 0 ]]; then - echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" - fi - return $WAITFORIT_RESULT -} - -# process arguments -while [[ $# -gt 0 ]] -do - case "$1" in - *:* ) - WAITFORIT_hostport=(${1//:/ }) - WAITFORIT_HOST=${WAITFORIT_hostport[0]} - WAITFORIT_PORT=${WAITFORIT_hostport[1]} - shift 1 - ;; - --child) - WAITFORIT_CHILD=1 - shift 1 - ;; - -q | --quiet) - WAITFORIT_QUIET=1 - shift 1 - ;; - -s | --strict) - WAITFORIT_STRICT=1 - shift 1 - ;; - -h) - WAITFORIT_HOST="$2" - if [[ $WAITFORIT_HOST == "" ]]; then break; fi - shift 2 - ;; - --host=*) - WAITFORIT_HOST="${1#*=}" - shift 1 - ;; - -p) - WAITFORIT_PORT="$2" - if [[ $WAITFORIT_PORT == "" ]]; then break; fi - shift 2 - ;; - --port=*) - WAITFORIT_PORT="${1#*=}" - shift 1 - ;; - -t) - WAITFORIT_TIMEOUT="$2" - if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi - shift 2 - ;; - --timeout=*) - WAITFORIT_TIMEOUT="${1#*=}" - shift 1 - ;; - --) - shift - WAITFORIT_CLI=("$@") - break - ;; - --help) - usage - ;; - *) - echoerr "Unknown argument: $1" - usage - ;; - esac -done - -if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then - echoerr "Error: you need to provide a host and port to test." - usage -fi - -WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} -WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} -WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} -WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} - -# Check to see if timeout is from busybox? -WAITFORIT_TIMEOUT_PATH=$(type -p timeout) -WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) - -WAITFORIT_BUSYTIMEFLAG="" -if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then - WAITFORIT_ISBUSY=1 - # Check if busybox timeout uses -t flag - # (recent Alpine versions don't support -t anymore) - if timeout &>/dev/stdout | grep -q -e '-t '; then - WAITFORIT_BUSYTIMEFLAG="-t" - fi -else - WAITFORIT_ISBUSY=0 -fi - -if [[ $WAITFORIT_CHILD -gt 0 ]]; then - wait_for - WAITFORIT_RESULT=$? - exit $WAITFORIT_RESULT -else - if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then - wait_for_wrapper - WAITFORIT_RESULT=$? - else - wait_for - WAITFORIT_RESULT=$? - fi -fi - -if [[ $WAITFORIT_CLI != "" ]]; then - if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then - echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" - exit $WAITFORIT_RESULT - fi - exec "${WAITFORIT_CLI[@]}" -else - exit $WAITFORIT_RESULT -fi - diff --git a/test-compose/db/Dockerfile b/test-compose/db/Dockerfile deleted file mode 100644 index af99003..0000000 --- a/test-compose/db/Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -FROM centos:centos8 - -ARG DB_ROOT_PWD=SecretPassword -ENV DB_ROOT_PWD=$DB_ROOT_PWD - -ARG DB_USER=radius -ENV DB_USER=$DB_USER - -ARG DB_USER_PWD=password -ENV DB_USER_PWD=$DB_USER_PWD - -ARG DB_NAME=radius -ENV DB_NAME=$DB_NAME - -RUN dnf module install -y mariadb - -COPY container_files/rad-schema.sql / - -RUN mysql_install_db \ - && chown -R mysql:mysql /var/lib/mysql/ \ - && sed -i 's/^\(bind-address\s.*\)/# \1/' /etc/my.cnf \ - && sed -i 's/^\(log_error\s.*\)/# \1/' /etc/my.cnf \ - && sed -i 's/\[mysqld\]/\[mysqld\]\ncharacter_set_server = utf8/' /etc/my.cnf \ - && sed -i 's/\[mysqld\]/\[mysqld\]\ncollation_server = utf8_general_ci/' /etc/my.cnf \ - && sed -i 's/\[mysqld\]/\[mysqld\]\nport = 3306/' /etc/my.cnf \ - && cat /etc/my.cnf \ - && echo "/usr/bin/mysqld_safe &" > /tmp/config \ - && echo "mysqladmin --silent --wait=30 ping || exit 1" >> /tmp/config \ - #steps performed by mysql_secure_installation - && echo "mysql -e 'UPDATE mysql.user SET Password=PASSWORD(\"${DB_ROOT_PWD}\") WHERE User=\"root\";'" >> /tmp/config \ - && echo "mysql -e 'DELETE FROM mysql.user WHERE User=\"\";'" >> /tmp/config \ - && echo "mysql -e 'DELETE FROM mysql.user WHERE User=\"root\" AND Host NOT IN (\"localhost\", \"127.0.0.1\", \"::1\");'" >> /tmp/config \ - && echo "mysql -e 'DROP DATABASE IF EXISTS test;'" >> /tmp/config \ - && echo "mysql -e 'DELETE FROM mysql.db WHERE Db=\"test\" OR Db=\"test\\_%\";'" >> /tmp/config \ - && echo "mysql -e 'CREATE DATABASE ${DB_NAME};'" >> /tmp/config \ - && echo "mysql -u root --password=${DB_PWD} ${DB_NAME} < /rad-schema.sql" >> /tmp/config \ - && echo "mysql -e 'CREATE USER \"${DB_USER}\"@\"%\" IDENTIFIED BY \"${DB_USER_PWD}\";'" >> /tmp/config \ - && echo "mysql -e 'GRANT ALL ON ${DB_NAME}.* TO \"${DB_USER}\"@\"%\";'" >> /tmp/config \ - && echo "mysql -e 'FLUSH PRIVILEGES;'" >> /tmp/config \ - && bash /tmp/config \ - && rm -f /tmp/config - -EXPOSE 3306 - -HEALTHCHECK CMD mysqladmin --silent --wait=30 ping || exit 1 - -CMD mysqld_safe diff --git a/test-compose/db/container_files/rad-schema.sql b/test-compose/db/container_files/rad-schema.sql deleted file mode 100644 index 2de3666..0000000 --- a/test-compose/db/container_files/rad-schema.sql +++ /dev/null @@ -1,150 +0,0 @@ -########################################################################### -# $Id: 1059b115282ea738353fe4fbc8d92b03a338f8c1 $ # -# # -# schema.sql rlm_sql - FreeRADIUS SQL Module # -# # -# Database schema for MySQL rlm_sql module # -# # -# To load: # -# mysql -uroot -prootpass radius < schema.sql # -# # -# Mike Machado # -########################################################################### -# -# Table structure for table 'radacct' -# - -CREATE TABLE radacct ( - radacctid bigint(21) NOT NULL auto_increment, - acctsessionid varchar(64) NOT NULL default '', - acctuniqueid varchar(32) NOT NULL default '', - username varchar(64) NOT NULL default '', - realm varchar(64) default '', - nasipaddress varchar(15) NOT NULL default '', - nasportid varchar(15) default NULL, - nasporttype varchar(32) default NULL, - acctstarttime datetime NULL default NULL, - acctupdatetime datetime NULL default NULL, - acctstoptime datetime NULL default NULL, - acctinterval int(12) default NULL, - acctsessiontime int(12) unsigned default NULL, - acctauthentic varchar(32) default NULL, - connectinfo_start varchar(50) default NULL, - connectinfo_stop varchar(50) default NULL, - acctinputoctets bigint(20) default NULL, - acctoutputoctets bigint(20) default NULL, - calledstationid varchar(50) NOT NULL default '', - callingstationid varchar(50) NOT NULL default '', - acctterminatecause varchar(32) NOT NULL default '', - servicetype varchar(32) default NULL, - framedprotocol varchar(32) default NULL, - framedipaddress varchar(15) NOT NULL default '', - PRIMARY KEY (radacctid), - UNIQUE KEY acctuniqueid (acctuniqueid), - KEY username (username), - KEY framedipaddress (framedipaddress), - KEY acctsessionid (acctsessionid), - KEY acctsessiontime (acctsessiontime), - KEY acctstarttime (acctstarttime), - KEY acctinterval (acctinterval), - KEY acctstoptime (acctstoptime), - KEY nasipaddress (nasipaddress) -) ENGINE = INNODB; - -# -# Table structure for table 'radcheck' -# - -CREATE TABLE radcheck ( - id int(11) unsigned NOT NULL auto_increment, - username varchar(64) NOT NULL default '', - attribute varchar(64) NOT NULL default '', - op char(2) NOT NULL DEFAULT '==', - value varchar(253) NOT NULL default '', - PRIMARY KEY (id), - KEY username (username(32)) -); - -# -# Table structure for table 'radgroupcheck' -# - -CREATE TABLE radgroupcheck ( - id int(11) unsigned NOT NULL auto_increment, - groupname varchar(64) NOT NULL default '', - attribute varchar(64) NOT NULL default '', - op char(2) NOT NULL DEFAULT '==', - value varchar(253) NOT NULL default '', - PRIMARY KEY (id), - KEY groupname (groupname(32)) -); - -# -# Table structure for table 'radgroupreply' -# - -CREATE TABLE radgroupreply ( - id int(11) unsigned NOT NULL auto_increment, - groupname varchar(64) NOT NULL default '', - attribute varchar(64) NOT NULL default '', - op char(2) NOT NULL DEFAULT '=', - value varchar(253) NOT NULL default '', - PRIMARY KEY (id), - KEY groupname (groupname(32)) -); - -# -# Table structure for table 'radreply' -# - -CREATE TABLE radreply ( - id int(11) unsigned NOT NULL auto_increment, - username varchar(64) NOT NULL default '', - attribute varchar(64) NOT NULL default '', - op char(2) NOT NULL DEFAULT '=', - value varchar(253) NOT NULL default '', - PRIMARY KEY (id), - KEY username (username(32)) -); - - -# -# Table structure for table 'radusergroup' -# - -CREATE TABLE radusergroup ( - username varchar(64) NOT NULL default '', - groupname varchar(64) NOT NULL default '', - priority int(11) NOT NULL default '1', - KEY username (username(32)) -); - -# -# Table structure for table 'radpostauth' -# -CREATE TABLE radpostauth ( - id int(11) NOT NULL auto_increment, - username varchar(64) NOT NULL default '', - pass varchar(64) NOT NULL default '', - reply varchar(32) NOT NULL default '', - authdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id) -) ENGINE = INNODB; - -# -# Table structure for table 'nas' -# -CREATE TABLE nas ( - id int(10) NOT NULL auto_increment, - nasname varchar(128) NOT NULL, - shortname varchar(32), - type varchar(30) DEFAULT 'other', - ports int(5), - secret varchar(60) DEFAULT 'secret' NOT NULL, - server varchar(64), - community varchar(50), - description varchar(200) DEFAULT 'RADIUS Client', - PRIMARY KEY (id), - KEY nasname (nasname) -); - diff --git a/test-compose/docker-compose.yml b/test-compose/docker-compose.yml index 459964b..28e58f3 100644 --- a/test-compose/docker-compose.yml +++ b/test-compose/docker-compose.yml @@ -3,47 +3,15 @@ version: "3.3" services: radius: - build: - context: ./radius/ -# command: bash -c "while ! curl -s db:3306 > /dev/null; do echo waiting for mysql to start; sleep 3; done; /usr/sbin/radiusd -fxxl stdout" - depends_on: - - db - expose: - - "1812/udp" - - "1813/udp" - - "443" - networks: - - front - - back + image: + - "tier/eduroam-radius:3.0-20200222 ports: - "1812:1812/udp" - "1813:1813/udp" - "443:443" - - db: - build: - context: ./db/ - args: - DB_USER: radius - DB_USER_PWD: MySecretPassword - DB_ROOT_PWD: MySecretPassword - DB_NAME: radius - expose: - - "3306" - networks: - - back - ports: - - "3306:3306" volumes: - radius_db:/var/lib/mysql -networks: - front: - driver: bridge - back: - driver: bridge - - volumes: radius_db: driver: local diff --git a/test-compose/radius/Dockerfile b/test-compose/radius/Dockerfile deleted file mode 100644 index 45ad26d..0000000 --- a/test-compose/radius/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM tier/eduroam-freeradius:3.0-20200221 - -COPY container_files/rad-sql.cfg /etc/raddb/mods-available/sql - -CMD ["/wait-for-it.sh","-q","db:3306","--","/usr/sbin/radiusd","-fxxl","stdout"] diff --git a/test-compose/radius/container_files/rad-sql.cfg b/test-compose/radius/container_files/rad-sql.cfg deleted file mode 100644 index d7077ff..0000000 --- a/test-compose/radius/container_files/rad-sql.cfg +++ /dev/null @@ -1,267 +0,0 @@ -# -*- text -*- -## -## sql.conf -- SQL modules -## -## $Id: 4a59483c35c77f573fb177919e19ba4434cc3da1 $ - -###################################################################### -# -# Configuration for the SQL module -# -# The database schemas and queries are located in subdirectories: -# -# sql//main/schema.sql Schema -# sql//main/queries.conf Authorisation and Accounting queries -# -# Where "DB" is mysql, mssql, oracle, or postgresql. -# -# - -sql { - # The sub-module to use to execute queries. This should match - # the database you're attempting to connect to. - # - # * rlm_sql_mysql - # * rlm_sql_mssql - # * rlm_sql_oracle - # * rlm_sql_postgresql - # * rlm_sql_sqlite - # * rlm_sql_null (log queries to disk) - # - driver = "rlm_sql_mysql" - -# -# Several drivers accept specific options, to set them, a -# config section with the the name as the driver should be added -# to the sql instance. -# -# Driver specific options are: -# -# sqlite { -# # Path to the sqlite database -# filename = "/tmp/freeradius.db" -# -# # How long to wait for write locks on the database to be -# # released (in ms) before giving up. -# busy_timeout = 200 -# -# # If the file above does not exist and bootstrap is set -# # a new database file will be created, and the SQL statements -# # contained within the bootstrap file will be executed. -# bootstrap = "${modconfdir}/${..:name}/main/sqlite/schema.sql" -# } -# -# mysql { -# # If any of the files below are set, TLS encryption is enabled -# tls { -# ca_file = "/etc/ssl/certs/my_ca.crt" -# ca_path = "/etc/ssl/certs/" -# certificate_file = "/etc/ssl/certs/private/client.crt" -# private_key_file = "/etc/ssl/certs/private/client.key" -# cipher = "DHE-RSA-AES256-SHA:AES128-SHA" -# } -# -# # If yes, (or auto and libmysqlclient reports warnings are -# # available), will retrieve and log additional warnings from -# # the server if an error has occured. Defaults to 'auto' -# warnings = auto -# } -# -# postgresql { -# -# # unlike MySQL, which has a tls{} connection configuration, postgresql -# # uses its connection parameters - see the radius_db option below in -# # this file -# -# # Send application_name to the postgres server -# # Only supported in PG 9.0 and greater. Defaults to no. -# send_application_name = yes -# } -# - - # The dialect of SQL you want to use, this should usually match - # the driver you selected above. - # - # If you're using rlm_sql_null, then it should be the type of - # database the logged queries are going to be executed against. - dialect = "mysql" - - # Connection info: - # - server = "db" - port = 3306 - login = "radius" - password = "MySecretPassword" - - # Database table configuration for everything except Oracle - radius_db = "radius" - - # If you are using Oracle then use this instead -# radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))" - - # If you're using postgresql this can also be used instead of the connection info parameters -# radius_db = "dbname=radius host=localhost user=radius password=raddpass" - - # Postgreql doesn't take tls{} options in its module config like mysql does - if you want to - # use SSL connections then use this form of connection info parameter -# radius_db = "host=localhost port=5432 dbname=radius user=radius password=raddpass sslmode=verify-full sslcert=/etc/ssl/client.crt sslkey=/etc/ssl/client.key sslrootcert=/etc/ssl/ca.crt" - - # If you want both stop and start records logged to the - # same SQL table, leave this as is. If you want them in - # different tables, put the start table in acct_table1 - # and stop table in acct_table2 - acct_table1 = "radacct" - acct_table2 = "radacct" - - # Allow for storing data after authentication - postauth_table = "radpostauth" - - # Tables containing 'check' items - authcheck_table = "radcheck" - groupcheck_table = "radgroupcheck" - - # Tables containing 'reply' items - authreply_table = "radreply" - groupreply_table = "radgroupreply" - - # Table to keep group info - usergroup_table = "radusergroup" - - # If set to 'yes' (default) we read the group tables unless Fall-Through = no in the reply table. - # If set to 'no' we do not read the group tables unless Fall-Through = yes in the reply table. -# read_groups = yes - - # If set to 'yes' (default) we read profiles unless Fall-Through = no in the groupreply table. - # If set to 'no' we do not read profiles unless Fall-Through = yes in the groupreply table. -# read_profiles = yes - - # Remove stale session if checkrad does not see a double login - delete_stale_sessions = yes - - # Write SQL queries to a logfile. This is potentially useful for tracing - # issues with authorization queries. See also "logfile" directives in - # mods-config/sql/main/*/queries.conf. You can enable per-section logging - # by enabling "logfile" there, or global logging by enabling "logfile" here. - # - # Per-section logging can be disabled by setting "logfile = ''" -# logfile = ${logdir}/sqllog.sql - - # Set the maximum query duration and connection timeout - # for rlm_sql_mysql. -# query_timeout = 5 - - # As of version 3.0, the "pool" section has replaced the - # following configuration items: - # - # num_sql_socks - # connect_failure_retry_delay - # lifetime - # max_queries - - # - # The connection pool is new for 3.0, and will be used in many - # modules, for all kinds of connection-related activity. - # - # When the server is not threaded, the connection pool - # limits are ignored, and only one connection is used. - # - # If you want to have multiple SQL modules re-use the same - # connection pool, use "pool = name" instead of a "pool" - # section. e.g. - # - # sql1 { - # ... - # pool { - # ... - # } - # } - # - # # sql2 will use the connection pool from sql1 - # sql2 { - # ... - # pool = sql1 - # } - # - pool { - # Connections to create during module instantiation. - # If the server cannot create specified number of - # connections during instantiation it will exit. - # Set to 0 to allow the server to start without the - # database being available. - start = ${thread[pool].start_servers} - - # Minimum number of connections to keep open - min = ${thread[pool].min_spare_servers} - - # Maximum number of connections - # - # If these connections are all in use and a new one - # is requested, the request will NOT get a connection. - # - # Setting 'max' to LESS than the number of threads means - # that some threads may starve, and you will see errors - # like 'No connections available and at max connection limit' - # - # Setting 'max' to MORE than the number of threads means - # that there are more connections than necessary. - max = ${thread[pool].max_servers} - - # Spare connections to be left idle - # - # NOTE: Idle connections WILL be closed if "idle_timeout" - # is set. This should be less than or equal to "max" above. - spare = ${thread[pool].max_spare_servers} - - # Number of uses before the connection is closed - # - # 0 means "infinite" - uses = 0 - - # The number of seconds to wait after the server tries - # to open a connection, and fails. During this time, - # no new connections will be opened. - retry_delay = 30 - - # The lifetime (in seconds) of the connection - lifetime = 0 - - # idle timeout (in seconds). A connection which is - # unused for this length of time will be closed. - idle_timeout = 60 - - # NOTE: All configuration settings are enforced. If a - # connection is closed because of "idle_timeout", - # "uses", or "lifetime", then the total number of - # connections MAY fall below "min". When that - # happens, it will open a new connection. It will - # also log a WARNING message. - # - # The solution is to either lower the "min" connections, - # or increase lifetime/idle_timeout. - } - - # Set to 'yes' to read radius clients from the database ('nas' table) - # Clients will ONLY be read on server startup. -# read_clients = yes - - # Table to keep radius client info - client_table = "nas" - - # - # The group attribute specific to this instance of rlm_sql - # - - # This entry should be used for additional instances (sql foo {}) - # of the SQL module. -# group_attribute = "${.:instance}-SQL-Group" - - # This entry should be used for the default instance (sql {}) - # of the SQL module. - group_attribute = "SQL-Group" - - # Read database-specific queries -# $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf - $INCLUDE /etc/raddb/mods-config/sql/main/mysql/queries.conf -} - -