Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files Browse the repository at this point in the history
-Merge branch 'multi-stage-build' of github.internet2.edu:docker/grou…
…per_noVM into tier-secrets

-Password via env or env specified files examples
John Gasper committed Mar 29, 2018
2 parents 2ef4ce9 + 6a8f626 commit d775cac
Showing 21 changed files with 272 additions and 135 deletions.
1 change: 1 addition & 0 deletions .dockerignore
@@ -2,4 +2,5 @@
test-compose/
*.md
manualBuild.sh
Jenkinsfile
LICENSE
22 changes: 17 additions & 5 deletions 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/

33 changes: 29 additions & 4 deletions 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. `<GROUPER_HOME>/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. `<GROUPER_HOME>/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: <no label configured>
```

# Misc Notes

8 changes: 4 additions & 4 deletions 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,15 +47,15 @@ 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
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

12 changes: 5 additions & 7 deletions 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
14 changes: 7 additions & 7 deletions 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

10 changes: 5 additions & 5 deletions 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

3 changes: 3 additions & 0 deletions 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
26 changes: 26 additions & 0 deletions container_files/tomcat/conf/log4j2.xml
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Configuration status="info">
<Properties>
<Property name="layout">%d [%t] %-5p %c- %m%n</Property>
</Properties>
<Appenders>
<File name="CATALINA"
fileName="/tmp/logpipe">
<PatternLayout pattern="tomcat catalina.out ${env:ENV} ${env:USERTOKEN} ${layout}"/>
</File>
<File name="LOCALHOST"
fileName="/tmp/logpipe">
<PatternLayout pattern="tomcat localhost.log ${env:ENV} ${env:USERTOKEN} ${layout}"/>
</File>

</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="CATALINA"/>
</Root>
<Logger name="org.apache.catalina.core.ContainerBase.[Catalina].[localhost]"
level="info" additivity="false">
<AppenderRef ref="LOCALHOST"/>
</Logger>
</Loggers>
</Configuration>
3 changes: 3 additions & 0 deletions 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
26 changes: 26 additions & 0 deletions container_files/tomee/conf/log4j2.xml
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Configuration status="info">
<Properties>
<Property name="layout">%d [%t] %-5p %c- %m%n</Property>
</Properties>
<Appenders>
<File name="CATALINA"
fileName="/tmp/logpipe">
<PatternLayout pattern="tomee catalina.out ${env:ENV} ${env:USERTOKEN} ${layout}"/>
</File>
<File name="LOCALHOST"
fileName="/tmp/logpipe">
<PatternLayout pattern="tomee localhost.log ${env:ENV} ${env:USERTOKEN} ${layout}"/>
</File>

</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="CATALINA"/>
</Root>
<Logger name="org.apache.catalina.core.ContainerBase.[Catalina].[localhost]"
level="info" additivity="false">
<AppenderRef ref="LOCALHOST"/>
</Logger>
</Loggers>
</Configuration>

0 comments on commit d775cac

Please sign in to comment.