diff --git a/.dockerignore b/.dockerignore index ac0479b..d82e95b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,4 +2,5 @@ test-compose/ *.md manualBuild.sh +Jenkinsfile LICENSE diff --git a/Dockerfile b/Dockerfile index 8f12322..2d1b5bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,14 +54,24 @@ COPY --from=installing /opt/grouper/$GROUPER_VERSION/grouper.ws-$GROUPER_VERSION COPY --from=installing /opt/grouper/$GROUPER_VERSION/apache-tomcat-$TOMCAT_VERSION/ /opt/tomcat/ COPY --from=installing /opt/grouper/$GROUPER_VERSION/apache-tomee-webprofile-$TOMEE_VERSION/ /opt/tomee/ +ADD http://central.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.11.0/log4j-core-2.11.0.jar /opt/tomcat/bin +ADD http://central.maven.org/maven2/org/apache/logging/log4j/log4j-api/2.11.0/log4j-api-2.11.0.jar /opt/tomcat/bin +ADD http://central.maven.org/maven2/org/apache/logging/log4j/log4j-jul/2.11.0/log4j-jul-2.11.0.jar /opt/tomcat/bin + +ADD http://central.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.11.0/log4j-core-2.11.0.jar /opt/tomee/bin +ADD http://central.maven.org/maven2/org/apache/logging/log4j/log4j-api/2.11.0/log4j-api-2.11.0.jar /opt/tomee/bin +ADD http://central.maven.org/maven2/org/apache/logging/log4j/log4j-jul/2.11.0/log4j-jul-2.11.0.jar /opt/tomee/bin + RUN cd /opt/grouper/grouper.apiBinary/; \ rm -fr ddlScripts/ grouper.lck grouper.log grouper.script grouper.tmp/ gshAddGrouperSystemWsGroup.gsh logs/ RUN cd /opt/tomcat/; \ - rm -fr webapps/docs/ webapps/examples/ webapps/host-manager/ webapps/manager/ logs/* temp/* work/* + chmod +r bin/log4j-*.jar; \ + rm -fr webapps/docs/ webapps/examples/ webapps/host-manager/ webapps/manager/ logs/* temp/* work/* conf/logging.properties RUN cd /opt/tomee/; \ - rm -fr webapps/docs/ webapps/host-manager/ webapps/manager/ logs/* temp/* work/* + chmod +r bin/log4j-*.jar; \ + rm -fr webapps/docs/ webapps/host-manager/ webapps/manager/ logs/* temp/* work/* conf/logging.properties COPY container_files/api/* /opt/grouper/grouper.apiBinary/conf/ COPY container_files/ui/ /opt/grouper/grouper.ui/WEB-INF/ @@ -107,10 +117,12 @@ COPY container_files/httpd/* /etc/httpd/conf.d/ COPY container_files/shibboleth/* /etc/shibboleth/ RUN cp /dev/null /etc/httpd/conf.d/ssl.conf \ - && sed -i 's/LogFormat "/LogFormat "httpd-access /g' /etc/httpd/conf/httpd.conf \ - && echo -e "\nErrorLogFormat \"httpd-error [%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i\"" >> /etc/httpd/conf/httpd.conf \ + && 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 + && 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 WORKDIR /opt/grouper/grouper.apiBinary/ diff --git a/README.md b/README.md index 646ead5..d91d8d1 100644 --- a/README.md +++ b/README.md @@ -141,15 +141,23 @@ There are three primary ways to provide Grouper and additional configuration fil Docker Config and Docker Secrets are Docker's way of providing configurations files to a container at runtime. The primary difference between the Config and Secrets functionality is that Secrets is designed to protect resources/files that are sensitive. -This container will make any secrets with secret names prepended with `grouper_` available to the appropriate Grouper component's conf directory (i.e. `/conf` or `WEB-INF/classes`). Any secrets with secret names starting with `shib_` will be available in the Shibboleth SP `/etc/shibboleth/` directory. Any secrets with secret names starting with `httpd_` will be available to `/etc/httpd/conf.d` directory. Finally, if a secret with the name of `host-key.pem` will be mapped to the httpd TLS cert used by Grouper UI, Grouper WS, and Grouper SCIM Server containers. These files will supercede any found in the underlying image. +For passing full files into the container, this container will make any secrets with secret names prepended with `grouper_` available to the appropriate Grouper component's conf directory (i.e. `/conf` or `WEB-INF/classes`). Any secrets with secret names starting with `shib_` will be available in the Shibboleth SP `/etc/shibboleth/` directory. Any secrets with secret names starting with `httpd_` will be available to `/etc/httpd/conf.d` directory. Finally, if a secret with the name of `host-key.pem` will be mapped to the httpd TLS cert used by Grouper UI, Grouper WS, and Grouper SCIM Server containers. These files will supercede any found in the underlying image. + +Docker Secrets can also be used to pass in strings, such as a database connection string password, into the component config. To pass in the Grouper database connection string, one might set the property and value as such: + +```text +hibernate.connection.password.elConfig = ${java.lang.System.getenv().get('GROUPER_DATABASE_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('GROUPER_DATABASE_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('GROUPER_DATABASE_PASSWORD') } +``` + +Note that the default property name has been changed by appending `.elConfig`. (This causes Grouper to evaluate the string before saving the value.) The expression allows deployers to use a file containing only the database password as a Docker Secret and reference the file name via the `GROUPER_DATABASE_PASSWORD_FILE` environment property. This allows the config files to be baked into the image, if desired. Also, but not recommended, the database password could just be set in the Docker Service definition as an environment variable, `GROUPER_DATABASE_PASSWORD`. (Technically the expression can be broken up and just the desired functionality used.) Of course, using Grouper's MorphString functionality is supported and likely is the best option, but does require more effort in setting it up. Secrets can be managed using the `docker secret` command: `docker secret create grouper_grouper.hibernate.properties ./grouper.hibernate.properties`. This will securely store the file in the swarm. Secrets can then be assigned to the service `docker service create -d --name daemon --secret grouper_grouper.hibernate.properties --secret grouper_sources.xml tier/grouper daemon`. -> `docker run` does not support secrets; Bind mounts need to be used instead. +> `docker run` does not support secrets; Bind mounts need to be used instead, which is technically what Docker Compose does when not running against a Swarm. ### Bind Mounts -Bind mounts can be used to connect files/folders on the Docker host into the container's file system. Unless running in swarm mode, the secrets are not supported, so we can use a bind mount to provide the container with the configuration files. +Bind mounts can be used to connect files/folders on the Docker host into the container's file system. Unless running in swarm mode, Docker Secrets are not supported, so we can use a bind mount to provide the container with the configuration files. ```console $ docker run --detach --name daemon \ @@ -215,6 +223,7 @@ Here is a list of significant directories and files that deployers should be awa To examine baseline image files, one might run `docker run --name=temp -it tier/grouper bash` and browse through these file system endpoints. While the container is running one may copy files out of the image/container using something like `docker cp containerId:/opt/grouper/grouper.api/conf/grouper.properties .`, which will copy the `grouper.properties` to the Docker client's present working directory. These files can then be edited and applied via the mechanisms outlined above. # Web Application Endpoints + Here is a list of significant web endpoints that deployers should be aware of: - `/grouper/`: location of the Grouper UI application @@ -235,7 +244,23 @@ $ docker run -it --rm \ tier/grouper gsh -registry -check -runscript -noprompt ``` -Note: a less privileged database user maybe used when running the typical Grouper roles. This user need SELECT, INSERT, UPDATE, and DELETE privileges on the schema objects. +Note: a less privileged database user maybe used when running the typical Grouper roles. This user needs SELECT, INSERT, UPDATE, and DELETE privileges on the schema objects. + +# Logging + +This image outputs logs in a manner that is consistent with Docker Logging. Each log entry is prefaced with the submodule name (e.g. shibd, httpd, tomcat, grouper), the logfile name (e.g. access_log, grouper_error.log, catalina.out) and user definable environment name and a user definable token. Content found after the preface will be specific to the application ands its logging configuration. + +> Note: If customizing a particular component's logging, it is recommended that the file be source from the image (`docker container cp`) or from the image's source repository. + +To assign the "environment" string, set the environment variable `ENV` when defining the Docker service. For the "user defined token" string, use the environment variable of `USERTOKEN`. + +An example might look like the following, with the env of "dev" and the usertoken of "build-2" + +```text +shibd shibd.log dev build-2 2018-03-27 20:42:22 INFO Shibboleth.Listener : listener service starting +grouper-api grouper_event.log dev build-2 2018-03-27 21:10:00,046: [DefaultQuartzScheduler_Worker-1] INFO EventLog.info(156) - - [fdbb0099fe9e46e5be4371eb11250d39,'GrouperSystem','application'] session: start (0ms) +tomcat console dev build-2 Grouper starting up: version: 2.3.0, build date: null, env: +``` # Misc Notes diff --git a/container_files/api/log4j.properties b/container_files/api/log4j.properties index f9298f2..06abdb8 100644 --- a/container_files/api/log4j.properties +++ b/container_files/api/log4j.properties @@ -31,14 +31,14 @@ log4j.appender.grouper_event = org.apache.log4j.FileA log4j.appender.grouper_event.file = /tmp/logpipe log4j.appender.grouper_event.append = true log4j.appender.grouper_event.layout = org.apache.log4j.PatternLayout -log4j.appender.grouper_event.layout.ConversionPattern = grouperd %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_event.layout.ConversionPattern = grouper-api grouper_event.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n ## Grouper API error logging log4j.appender.grouper_error = org.apache.log4j.FileAppender log4j.appender.grouper_error.file = /tmp/logpipe log4j.appender.grouper_errot.append = true log4j.appender.grouper_error.layout = org.apache.log4j.PatternLayout -log4j.appender.grouper_error.layout.ConversionPattern = grouperd %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_error.layout.ConversionPattern = grouper-api grouper_error.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n #log4j.appender.grouper_error.layout.ConversionPattern = %d{ISO8601}: %m%n # Debug logging (Or: logging that I haven't cleaned up yet to send elsewhere) @@ -47,7 +47,7 @@ log4j.appender.grouper_debug.file = /tmp/logpipe log4j.appender.grouper_debug.append = true log4j.appender.grouper_debug.layout = org.apache.log4j.PatternLayout #log4j.appender.grouper_debug.layout.ConversionPattern = %d{ISO8601} %5p %c{2}: %m%n -log4j.appender.grouper_debug.layout.ConversionPattern = grouperd %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_debug.layout.ConversionPattern = grouper-api grouper_debug.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n ## Benchmark logging log4j.appender.grouper_gb = org.apache.log4j.FileAppender @@ -55,7 +55,7 @@ log4j.appender.grouper_gb.file = /tmp/logpipe log4j.appender.grouper_gb.append = true log4j.appender.grouper_gb.layout = org.apache.log4j.PatternLayout #log4j.appender.grouper_gb.layout.ConversionPattern = %d{ISO8601} %5p %c{2}: %m%n -log4j.appender.grouper_gb.layout.ConversionPattern = grouperd %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_gb.layout.ConversionPattern = grouper-api grouper_bench.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n # Loggers diff --git a/container_files/shibboleth/shibd.logger b/container_files/shibboleth/shibd.logger index 22208ca..9269aeb 100644 --- a/container_files/shibboleth/shibd.logger +++ b/container_files/shibboleth/shibd.logger @@ -43,19 +43,17 @@ log4j.additivity.Shibboleth-TRANSACTION=false log4j.appender.shibd_log=org.apache.log4j.FileAppender log4j.appender.shibd_log.fileName=/tmp/logpipe -log4j.appender.shibd_log.maxFileSize=1000000 -log4j.appender.shibd_log.maxBackupIndex=10 +log4j.appender.shibd_log.maxFileSize=0 log4j.appender.shibd_log.layout=org.apache.log4j.PatternLayout -log4j.appender.shibd_log.layout.ConversionPattern=shibd-log %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n +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.tran_log=org.apache.log4j.FileAppender log4j.appender.tran_log.fileName=/tmp/logpipe -log4j.appender.tran_log.maxFileSize=1000000 -log4j.appender.tran_log.maxBackupIndex=20 +log4j.appender.tran_log.maxFileSize=0 log4j.appender.tran_log.layout=org.apache.log4j.PatternLayout -log4j.appender.tran_log.layout.ConversionPattern=shibd-tran %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n +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-sig %m +log4j.appender.sig_log.layout.ConversionPattern=shibd signature.log ${ENV} ${USERTOKEN} %m diff --git a/container_files/tier-support/supervisord-tomcat.conf b/container_files/tier-support/supervisord-tomcat.conf index 78f0b2e..30631e4 100644 --- a/container_files/tier-support/supervisord-tomcat.conf +++ b/container_files/tier-support/supervisord-tomcat.conf @@ -1,5 +1,5 @@ [supervisord] -logfile=/tmp/logpipe ; supervisord log file +logfile=/tmp/logsuperd ; supervisord log file logfile_maxbytes=0 ; maximum size of logfile before rotation loglevel=error ; info, debug, warn, trace nodaemon=true ; run supervisord as a daemon @@ -16,24 +16,24 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix so [program:httpd] command=httpd -DFOREGROUND -stderr_logfile = /tmp/logpipe +stderr_logfile = /tmp/loghttpd stderr_logfile_maxbytes=0 -stdout_logfile = /tmp/logpipe +stdout_logfile = /tmp/loghttpd stdout_logfile_maxbytes=0 [program:shibbolethsp] user=shibd command=/usr/sbin/shibd -f -F -stderr_logfile = /tmp/logpipe +stderr_logfile = /tmp/logshidb stderr_logfile_maxbytes=0 -stdout_logfile = /tmp/logpipe +stdout_logfile = /tmp/logshidb stdout_logfile_maxbytes=0 [program:tomcat] user=tomcat command=/opt/tomcat/bin/catalina.sh run -stderr_logfile = /tmp/logpipe +stderr_logfile = /tmp/logtomcat stderr_logfile_maxbytes=0 -stdout_logfile = /tmp/logpipe +stdout_logfile = /tmp/logtomcat stdout_logfile_maxbytes=0 diff --git a/container_files/tier-support/supervisord-tomee.conf b/container_files/tier-support/supervisord-tomee.conf index 4d83843..35e1948 100644 --- a/container_files/tier-support/supervisord-tomee.conf +++ b/container_files/tier-support/supervisord-tomee.conf @@ -1,5 +1,5 @@ [supervisord] -logfile=/tmp/logpipe ; supervisord log file +logfile=/tmp/logsuperd ; supervisord log file logfile_maxbytes=0 ; maximum size of logfile before rotation loglevel=error ; info, debug, warn, trace nodaemon=true ; run supervisord as a daemon @@ -16,16 +16,16 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix so [program:httpd] command=httpd -DFOREGROUND -stderr_logfile = /tmp/logpipe +stderr_logfile = /tmp/loghttpd stderr_logfile_maxbytes=0 -stdout_logfile = /tmp/logpipe +stdout_logfile = /tmp/loghttpd stdout_logfile_maxbytes=0 [program:tomee] user=tomcat command=/opt/tomee/bin/catalina.sh run -stderr_logfile = /tmp/logpipe +stderr_logfile = /tmp/logtomcat stderr_logfile_maxbytes=0 -stdout_logfile = /tmp/logpipe +stdout_logfile = /tmp/logtomcat stdout_logfile_maxbytes=0 diff --git a/container_files/tomcat/bin/setenv.sh b/container_files/tomcat/bin/setenv.sh new file mode 100755 index 0000000..c6130b5 --- /dev/null +++ b/container_files/tomcat/bin/setenv.sh @@ -0,0 +1,3 @@ +CLASSPATH=/opt/tomcat/bin/* +JAVA_OPTS="-Dlog4j.configurationFile=/opt/tomcat/conf/log4j2.xml -DENV=$ENV -DUSERTOKEN=$USERTOKEN" +LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \ No newline at end of file diff --git a/container_files/tomcat/conf/log4j2.xml b/container_files/tomcat/conf/log4j2.xml new file mode 100644 index 0000000..8be4fd1 --- /dev/null +++ b/container_files/tomcat/conf/log4j2.xml @@ -0,0 +1,26 @@ + + + + %d [%t] %-5p %c- %m%n + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/container_files/tomee/bin/setenv.sh b/container_files/tomee/bin/setenv.sh new file mode 100755 index 0000000..2387d61 --- /dev/null +++ b/container_files/tomee/bin/setenv.sh @@ -0,0 +1,3 @@ +CLASSPATH=/opt/tomee/bin/* +JAVA_OPTS="-Dlog4j.configurationFile=/opt/tomee/conf/log4j2.xml -DENV=$ENV -DUSERTOKEN=$USERTOKEN" +LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \ No newline at end of file diff --git a/container_files/tomee/conf/log4j2.xml b/container_files/tomee/conf/log4j2.xml new file mode 100644 index 0000000..427f8b9 --- /dev/null +++ b/container_files/tomee/conf/log4j2.xml @@ -0,0 +1,26 @@ + + + + %d [%t] %-5p %c- %m%n + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/container_files/ui/classes/log4j.properties b/container_files/ui/classes/log4j.properties index bbbfa94..383838b 100644 --- a/container_files/ui/classes/log4j.properties +++ b/container_files/ui/classes/log4j.properties @@ -31,14 +31,14 @@ log4j.appender.grouper_event = org.apache.log4j.FileA log4j.appender.grouper_event.file = /tmp/logpipe log4j.appender.grouper_event.append = true log4j.appender.grouper_event.layout = org.apache.log4j.PatternLayout -log4j.appender.grouper_event.layout.ConversionPattern = grouper-ui %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_event.layout.ConversionPattern = grouper-ui grouper_event.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n ## Grouper API error logging log4j.appender.grouper_error = org.apache.log4j.FileAppender log4j.appender.grouper_error.file = /tmp/logpipe log4j.appender.grouper_errot.append = true log4j.appender.grouper_error.layout = org.apache.log4j.PatternLayout -log4j.appender.grouper_error.layout.ConversionPattern = grouper-ui %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_error.layout.ConversionPattern = grouper-ui grouper_error.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n #log4j.appender.grouper_error.layout.ConversionPattern = %d{ISO8601}: %m%n # Debug logging (Or: logging that I haven't cleaned up yet to send elsewhere) @@ -47,7 +47,7 @@ log4j.appender.grouper_debug.file = /tmp/logpipe log4j.appender.grouper_debug.append = true log4j.appender.grouper_debug.layout = org.apache.log4j.PatternLayout #log4j.appender.grouper_debug.layout.ConversionPattern = %d{ISO8601} %5p %c{2}: %m%n -log4j.appender.grouper_debug.layout.ConversionPattern = grouper-ui %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_debug.layout.ConversionPattern = grouper-ui grouper_debug.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n ## Benchmark logging log4j.appender.grouper_gb = org.apache.log4j.FileAppender @@ -55,7 +55,7 @@ log4j.appender.grouper_gb.file = /tmp/logpipe log4j.appender.grouper_gb.append = true log4j.appender.grouper_gb.layout = org.apache.log4j.PatternLayout #log4j.appender.grouper_gb.layout.ConversionPattern = %d{ISO8601} %5p %c{2}: %m%n -log4j.appender.grouper_gb.layout.ConversionPattern = grouper-ui %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_gb.layout.ConversionPattern = grouper-ui grouper_bench.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n # Loggers diff --git a/container_files/usr-local-bin/daemon b/container_files/usr-local-bin/daemon index e7e5aab..27f3da6 100755 --- a/container_files/usr-local-bin/daemon +++ b/container_files/usr-local-bin/daemon @@ -4,4 +4,6 @@ prepDaemon -exec bin/gsh -loader +export GSH_JVMARGS="-DENV=$ENV -DUSERTOKEN=$USERTOKEN" + +exec bin/gsh -loader > /tmp/loggrouper diff --git a/container_files/usr-local-bin/gsh b/container_files/usr-local-bin/gsh index e530870..563e564 100755 --- a/container_files/usr-local-bin/gsh +++ b/container_files/usr-local-bin/gsh @@ -4,4 +4,4 @@ prepDaemon -exec bin/gsh "$@" +exec bin/gsh "$@" | tee /tmp/loggrouper diff --git a/container_files/usr-local-bin/library.sh b/container_files/usr-local-bin/library.sh index c89ef4c..e21cc1e 100644 --- a/container_files/usr-local-bin/library.sh +++ b/container_files/usr-local-bin/library.sh @@ -4,6 +4,23 @@ mkfifo -m 666 /tmp/logpipe cat <> /tmp/logpipe 1>&2 & +# Make loggers pipes for the supervisord connected apps' console, so that we can prepend the streams. +mkfifo -m 666 /tmp/loggrouper +(cat <> /tmp/loggrouper | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "grouper 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/logshibd +(cat <> /tmp/logshibd | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "shibd console %s %s %s", ENV, UT, $0; fflush()}' 1>/tmp/logpipe) & + +mkfifo -m 666 /tmp/logtomcat +(cat <> /tmp/logtomcat | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "tomcat 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) & + + linkGrouperSecrets() { for filepath in /run/secrets/*; do local label_file=`basename $filepath` @@ -73,4 +90,4 @@ prepWS() { fi cp /opt/tier-support/grouper-ws.xml /opt/tomcat/conf/Catalina/localhost/ -} \ No newline at end of file +} diff --git a/container_files/ws/classes/log4j.properties b/container_files/ws/classes/log4j.properties index 2ce32b6..1bf749a 100644 --- a/container_files/ws/classes/log4j.properties +++ b/container_files/ws/classes/log4j.properties @@ -31,14 +31,14 @@ log4j.appender.grouper_event = org.apache.log4j.FileA log4j.appender.grouper_event.file = /tmp/logpipe log4j.appender.grouper_event.append = true log4j.appender.grouper_event.layout = org.apache.log4j.PatternLayout -log4j.appender.grouper_event.layout.ConversionPattern = grouper-ws %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_event.layout.ConversionPattern = grouper-ws grouper_event.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n ## Grouper API error logging log4j.appender.grouper_error = org.apache.log4j.FileAppender log4j.appender.grouper_error.file = /tmp/logpipe log4j.appender.grouper_errot.append = true log4j.appender.grouper_error.layout = org.apache.log4j.PatternLayout -log4j.appender.grouper_error.layout.ConversionPattern = grouper-ws %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_error.layout.ConversionPattern = grouper-ws grouper_error.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n #log4j.appender.grouper_error.layout.ConversionPattern = %d{ISO8601}: %m%n # Debug logging (Or: logging that I haven't cleaned up yet to send elsewhere) @@ -47,7 +47,7 @@ log4j.appender.grouper_debug.file = /tmp/logpipe log4j.appender.grouper_debug.append = true log4j.appender.grouper_debug.layout = org.apache.log4j.PatternLayout #log4j.appender.grouper_debug.layout.ConversionPattern = %d{ISO8601} %5p %c{2}: %m%n -log4j.appender.grouper_debug.layout.ConversionPattern = grouper-ws %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_debug.layout.ConversionPattern = grouper-ws grouper_debug.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n ## Benchmark logging log4j.appender.grouper_gb = org.apache.log4j.FileAppender @@ -55,7 +55,7 @@ log4j.appender.grouper_gb.file = /tmp/logpipe log4j.appender.grouper_gb.append = true log4j.appender.grouper_gb.layout = org.apache.log4j.PatternLayout #log4j.appender.grouper_gb.layout.ConversionPattern = %d{ISO8601} %5p %c{2}: %m%n -log4j.appender.grouper_gb.layout.ConversionPattern = grouper-ws %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n +log4j.appender.grouper_gb.layout.ConversionPattern = grouper-ws grouper_bench.log ${ENV} ${USERTOKEN} %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n # Loggers diff --git a/test-compose/README.md b/test-compose/README.md index d1d7199..2dc53e0 100644 --- a/test-compose/README.md +++ b/test-compose/README.md @@ -50,10 +50,11 @@ Note that when accessing the Grouper UI, Grouper WS, or Shibboleth IdP, your bro # Additional Notes -- Docker `configs` are not supported by Docker Compose, so those are represented in the `docker-compose.yml` file as bind mount volumes. -- The Grouper config files in the `data` image's `conf` directory are used to build the sample grouper database and ldap store. They are not used when the container is instantiated. +- In this example, we use a variety of ways to pass in passwords (Grouper database, LDAP, Grouper Client, and RabbitMQ). The point is to demonstrate possibilities and not demonstrating what is required. (See the image readme for more details.) +- Docker `configs` are not supported by Docker Compose (when run in a non-Swarm mode), so those are represented in the `docker-compose.yml` file as bind mount volumes. +- The Grouper config files in the `data` image's `conf` directory are used to build the sample grouper database and ldap store. They are not used when the container is instantiated as there is no Grouper runtime in this container. - The containers will use Docker Secrets and bind mounts for non-sensitive files that are read from the `configs-ans-secrets` directory in the `test-compose` directory. -- With regard to RabbitMQ, the deployer must manually add a queue named `sampleQueue` to see Grouper messages in RabbitMQ. Messages will be dropped by RabbitMQ until this occurs. +- With regard to RabbitMQ, the deployer must manually add a queue named `sampleQueue` to see Grouper messages in RabbitMQ. Messages will be dropped by RabbitMQ (and the Grouper Deamon will log errors) until this occurs. - In this example, we don't care about the IdP secrets. They are baked into the overlay instead of using Docker Secrets. (This is not best practice for an IdP configuration, but that isn't the focus of this example.) # Future TODOs diff --git a/test-compose/data/Dockerfile b/test-compose/data/Dockerfile index 7739de3..3531783 100644 --- a/test-compose/data/Dockerfile +++ b/test-compose/data/Dockerfile @@ -11,20 +11,20 @@ RUN yum install -y epel-release \ && yum clean all 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 \ - && echo "mysql -e 'GRANT ALL PRIVILEGES ON *.* TO \"root\"@\"%\" WITH GRANT OPTION;'" >> /tmp/config \ - && echo "mysql -e 'CREATE DATABASE grouper CHARACTER SET utf8 COLLATE utf8_bin;'" >> /tmp/config \ - && bash /tmp/config \ - && rm -f /tmp/config \ - && mysql grouper < /seed-data/sisData.sql + && 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 \ + && echo "mysql -e 'GRANT ALL PRIVILEGES ON *.* TO \"root\"@\"%\" WITH GRANT OPTION;'" >> /tmp/config \ + && echo "mysql -e 'CREATE DATABASE grouper CHARACTER SET utf8 COLLATE utf8_bin;'" >> /tmp/config \ + && bash /tmp/config \ + && rm -f /tmp/config \ + && mysql grouper < /seed-data/sisData.sql RUN useradd ldapadmin \ && rm -fr /var/lock /usr/lib/systemd/system \ @@ -39,8 +39,10 @@ RUN useradd ldapadmin \ && sleep 3 \ && ldapadd -H ldap:/// -f /seed-data/users.ldif -x -D "cn=Directory Manager" -w password -RUN (/usr/sbin/ns-slapd -D /etc/dirsrv/slapd-dir &); \ - (/usr/bin/mysqld_safe &); \ +RUN (/usr/sbin/ns-slapd -D /etc/dirsrv/slapd-dir &) \ + && while ! curl -s ldap://localhost:389 > /dev/null; do echo waiting for ldap to start; sleep 1; done; \ + (mysqld_safe & ) \ + && while ! curl -s localhost:3306 > /dev/null; do echo waiting for mysqld to start; sleep 1; done; \ bin/gsh -registry -check -runscript -noprompt \ && bin/gsh /seed-data/bootstrap.gsh diff --git a/test-compose/data/container_files/conf/grouper.hibernate.properties b/test-compose/data/container_files/conf/grouper.hibernate.properties index 89404b5..154b8eb 100644 --- a/test-compose/data/container_files/conf/grouper.hibernate.properties +++ b/test-compose/data/container_files/conf/grouper.hibernate.properties @@ -26,4 +26,4 @@ hibernate.connection.username = root # If you are using an empty password, depending upon your version of # Java and Ant you may need to specify a password of "". # Note: you can keep passwords external and encrypted: https://bugs.internet2.edu/jira/browse/GRP-122 -hibernate.connection.password.elConfig = ${java.lang.System.getenv().get('GROUPER_DATABASE_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('GROUPER_DATABASE_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('GROUPER_DATABASE_PASSWORD') } +hibernate.connection.password = diff --git a/test-compose/data/container_files/conf/subject.properties b/test-compose/data/container_files/conf/subject.properties index a73bd20..a823191 100644 --- a/test-compose/data/container_files/conf/subject.properties +++ b/test-compose/data/container_files/conf/subject.properties @@ -8,7 +8,7 @@ subjectApi.source.ldap.param.INITIAL_CONTEXT_FACTORY.value = com.sun.jndi.ldap.L subjectApi.source.ldap.param.PROVIDER_URL.value = ldap://localhost:389 subjectApi.source.ldap.param.SECURITY_AUTHENTICATION.value = simple subjectApi.source.ldap.param.SECURITY_PRINCIPAL.value = cn=admin,dc=internet2,dc=edu -subjectApi.source.ldap.param.SECURITY_CREDENTIALS.value.elConfig = password +subjectApi.source.ldap.param.SECURITY_CREDENTIALS.value = password subjectApi.source.ldap.param.SubjectID_AttributeType.value = uid subjectApi.source.ldap.param.SubjectID_formatToLowerCase.value = false subjectApi.source.ldap.param.Name_AttributeType.value = cn diff --git a/test-compose/docker-compose.yml b/test-compose/docker-compose.yml index cebb97b..b454727 100644 --- a/test-compose/docker-compose.yml +++ b/test-compose/docker-compose.yml @@ -4,20 +4,18 @@ services: daemon: build: ./daemon/ command: bash -c "while ! curl -s data:3306 > /dev/null; do echo waiting for mysql to start; sleep 3; done; exec daemon" - volumes: - - type: bind - source: ./configs-and-secrets/grouper/grouper.properties - target: /opt/grouper/conf/grouper.properties - - type: bind - source: ./configs-and-secrets/grouper/grouper.client.properties - target: /opt/grouper/conf/grouper.client.properties - depends_on: + depends_on: - data environment: + - ENV=dev - GROUPER_CLIENT_WEBSERVICE_PASSWORD_FILE=password - GROUPER_DATABASE_PASSWORD_FILE=/run/secrets/database_password.txt - RABBITMQ_PASSWORD_FILE=/run/secrets/rabbitmq_password.txt - SUBJECT_SOURCE_LDAP_PASSWORD=password + - USERTOKEN=build-2 + logging: + options: + tag: "grouper daemon" networks: - back secrets: @@ -29,10 +27,6 @@ services: target: grouper_grouper-loader.properties - source: subject.properties target: grouper_subject.properties - - ui: - build: ./ui/ - command: bash -c "while ! curl -s data:3306 > /dev/null; do echo waiting for mysql to start; sleep 3; done; while ! curl -s ldap://data:389 > /dev/null; do echo waiting for ldap to start; sleep 3; done; exec ui" volumes: - type: bind source: ./configs-and-secrets/grouper/grouper.properties @@ -40,26 +34,21 @@ services: - type: bind source: ./configs-and-secrets/grouper/grouper.client.properties target: /opt/grouper/conf/grouper.client.properties - - type: bind - source: ./configs-and-secrets/shibboleth/sp-cert.pem - target: /etc/shibboleth/sp-cert.pem - - type: bind - source: ./configs-and-secrets/shibboleth/shibboleth2.xml - target: /etc/shibboleth/shibboleth2.xml - - type: bind - source: ./configs-and-secrets/shibboleth/idp-metadata.xml - target: /etc/shibboleth/idp-metadata.xml - - type: bind - source: ./configs-and-secrets/httpd/host-cert.pem - target: /etc/pki/tls/certs/host-cert.pem - - type: bind - source: ./configs-and-secrets/httpd/host-cert.pem - target: /etc/pki/tls/certs/cachain.pem - depends_on: + + + ui: + build: ./ui/ + command: bash -c "while ! curl -s data:3306 > /dev/null; do echo waiting for mysql to start; sleep 3; done; while ! curl -s ldap://data:389 > /dev/null; do echo waiting for ldap to start; sleep 3; done; exec ui" + depends_on: - data environment: + - ENV=dev - GROUPER_DATABASE_PASSWORD_FILE=/run/secrets/database_password.txt - SUBJECT_SOURCE_LDAP_PASSWORD=password + - USERTOKEN=build-2 + logging: + options: + tag: "grouper ui" networks: - front - back @@ -77,11 +66,6 @@ services: - source: sp-key.pem target: shib_sp-key.pem - source: host-key.pem - - - ws: - build: ./ws/ - command: bash -c "while ! curl -s data:3306 > /dev/null; do echo waiting for mysql to start; sleep 3; done; while ! curl -s ldap://data:389 > /dev/null; do echo waiting for ldap to start; sleep 3; done; exec ws" volumes: - type: bind source: ./configs-and-secrets/grouper/grouper.properties @@ -89,17 +73,36 @@ services: - type: bind source: ./configs-and-secrets/grouper/grouper.client.properties target: /opt/grouper/conf/grouper.client.properties + - type: bind + source: ./configs-and-secrets/shibboleth/sp-cert.pem + target: /etc/shibboleth/sp-cert.pem + - type: bind + source: ./configs-and-secrets/shibboleth/shibboleth2.xml + target: /etc/shibboleth/shibboleth2.xml + - type: bind + source: ./configs-and-secrets/shibboleth/idp-metadata.xml + target: /etc/shibboleth/idp-metadata.xml - type: bind source: ./configs-and-secrets/httpd/host-cert.pem target: /etc/pki/tls/certs/host-cert.pem - type: bind source: ./configs-and-secrets/httpd/host-cert.pem target: /etc/pki/tls/certs/cachain.pem - depends_on: + + + ws: + build: ./ws/ + command: bash -c "while ! curl -s data:3306 > /dev/null; do echo waiting for mysql to start; sleep 3; done; while ! curl -s ldap://data:389 > /dev/null; do echo waiting for ldap to start; sleep 3; done; exec ws" + depends_on: - data environment: + - ENV=dev - GROUPER_DATABASE_PASSWORD_FILE=/run/secrets/database_password.txt - SUBJECT_SOURCE_LDAP_PASSWORD=password + - USERTOKEN=build-2 + logging: + options: + tag: "grouoer ws" networks: - front - back @@ -113,25 +116,28 @@ services: target: grouper_grouper-loader.properties - source: subject.properties target: grouper_subject.properties + - source: sp-key.pem + target: shib_sp-key.pem - source: host-key.pem + volumes: + - type: bind + source: ./configs-and-secrets/grouper/grouper.properties + target: /opt/grouper/conf/grouper.properties + - type: bind + source: ./configs-and-secrets/grouper/grouper.client.properties + target: /opt/grouper/conf/grouper.client.properties + - type: bind + source: ./configs-and-secrets/httpd/host-cert.pem + target: /etc/pki/tls/certs/host-cert.pem + - type: bind + source: ./configs-and-secrets/httpd/host-cert.pem + target: /etc/pki/tls/certs/cachain.pem + # scim: # build: ./scim/ # command: bash -c "while ! curl -s data:3306 > /dev/null; do echo waiting for mysql to start; sleep 3; done; while ! curl -s ldap://data:389 > /dev/null; do echo waiting for ldap to start; sleep 3; done; exec scim" -# volumes: -# - type: bind -# source: ./configs-and-secrets/grouper/grouper.properties -# target: /opt/grouper/conf/grouper.properties -# - type: bind -# source: ./configs-and-secrets/grouper/grouper.client.properties -# target: /opt/grouper/conf/grouper.client.properties -# - type: bind -# source: ./configs-and-secrets/httpd/host-cert.pem -# target: /etc/pki/tls/certs/host-cert.pem -# - type: bind -# source: ./configs-and-secrets/httpd/host-cert.pem -# target: /etc/pki/tls/certs/cachain.pem -# depends_on: +# depends_on: # - data # networks: # - front @@ -145,24 +151,36 @@ services: # target: grouper_grouper-loader.properties # - source: ldap.properties # target: grouper_ldap.properties -# - source: sources.xml -# target: grouper_sources.xml +# - source: subject.properties +# target: grouper_subject.properties # - source: host-key.pem +# volumes: +# - type: bind +# source: ./configs-and-secrets/grouper/grouper.properties +# target: /opt/grouper/conf/grouper.properties +# - type: bind +# source: ./configs-and-secrets/grouper/grouper.client.properties +# target: /opt/grouper/conf/grouper.client.properties +# - type: bind +# source: ./configs-and-secrets/httpd/host-cert.pem +# target: /etc/pki/tls/certs/host-cert.pem +# - type: bind +# source: ./configs-and-secrets/httpd/host-cert.pem +# target: /etc/pki/tls/certs/cachain.pem + gsh: build: ./gsh/ - volumes: - - type: bind - source: ./configs-and-secrets/grouper/grouper.properties - target: /opt/grouper/conf/grouper.properties - - type: bind - source: ./configs-and-secrets/grouper/grouper.client.properties - target: /opt/grouper/conf/grouper.client.properties - depends_on: + depends_on: - data environment: + - ENV=dev - GROUPER_DATABASE_PASSWORD_FILE=/run/secrets/database_password.txt - SUBJECT_SOURCE_LDAP_PASSWORD=password + - USERTOKEN=build-2 + logging: + options: + tag: "grouper gsh" networks: - back secrets: @@ -173,13 +191,17 @@ services: target: grouper_grouper-loader.properties - source: subject.properties target: grouper_subject.properties + volumes: + - type: bind + source: ./configs-and-secrets/grouper/grouper.properties + target: /opt/grouper/conf/grouper.properties + - type: bind + source: ./configs-and-secrets/grouper/grouper.client.properties + target: /opt/grouper/conf/grouper.client.properties data: build: ./data/ - environment: - - GROUPER_DATABASE_PASSWORD_FILE=/run/secrets/database_password.txt - - SUBJECT_SOURCE_LDAP_PASSWORD=password expose: - "389" - "3306" @@ -188,8 +210,6 @@ services: ports: - "389:389" - "3306:3306" - secrets: - - database_password.txt idp: @@ -206,6 +226,7 @@ services: ports: - "4443:4443" + rabbitmq: image: rabbitmq:management environment: @@ -217,26 +238,26 @@ services: ports: - "15672:15672" + networks: front: driver: bridge back: driver: bridge + secrets: + database_password.txt: + file: ./configs-and-secrets/grouper/database_password.txt grouper.hibernate.properties: file: ./configs-and-secrets/grouper/grouper.hibernate.properties grouper-loader.properties: file: ./configs-and-secrets/grouper/grouper-loader.properties - subject.properties: - file: ./configs-and-secrets/grouper/subject.properties - sp-key.pem: - file: ./configs-and-secrets/shibboleth/sp-key.pem host-key.pem: file: ./configs-and-secrets/httpd/host-key.pem - database_password.txt: - file: ./configs-and-secrets/grouper/database_password.txt rabbitmq_password.txt: file: ./configs-and-secrets/grouper/rabbitmq_password.txt - - \ No newline at end of file + subject.properties: + file: ./configs-and-secrets/grouper/subject.properties + sp-key.pem: + file: ./configs-and-secrets/shibboleth/sp-key.pem