- Install docker (note, using a server with systemd is easier)
See if docker is running
Code Block |
---|
bin $ docker info
Client:
Debug Mode: false
Server:
Containers: 5
Running: 0
Paused: 0
|
List containers. Containers are instances of docker images, which is the product delivered from Grouper.
Code Block |
---|
bin $ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ca762df952a6 tier/gte:101.1.1-201906i2incommon/grouper 2.5.02 "/usr/local/bin/entr…" 9 months ago Exited (137) 9 months ago 101.1.1grouper-ui
bin $
|
Remove unneeded containers if necessary
Code Block |
---|
bin $ docker rm -f ca762df952a6
ca762df952a6
|
(Reference command) List images
Code Block |
---|
[root@ip-172-30-3-152 ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
my-grouper-2.5.XX02 latest 918f5dd01bd5 6 hours ago 1.23GB
i2incommon/grouper 2.5.XX f939770b7d91 34 hours ago 1.23GB
[root@ip-172-30-3-152 ~]# |
(Reference command) Remove old images
Code Block |
---|
[root@ip-172-30-3-152 ~]# docker rmi 918f5dd01bd5
[root@ip-172-30-3-152 ~]# docker rmi f939770b7d91 |
- See which version of Grouper to run
Pull the image
Code Block |
---|
bin $ docker pull i2incommon/grouper:2.5.XX |
Make sure the digest is correct (from release notes page)
Code Block |
---|
[root@ip-172-30-3-152 ~]# docker image inspect i2incommon/grouper:2.5.XX | grep i2incommon/grouper@sha256
"i2incommon/grouper@sha256:b675bb410bf873483497b9b231e7a5db208645e58a3a42a8048381a33b79fd19" |
Create a directory to mount files and folder in and out of container. You might have one of these directories that is shared for ws/ui/daemon.
Code Block |
---|
2.5 $ mkdir -p /opt/grouperContainer
2.5 $ mkdir -p /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes
|
- Create a local database. Preferred is Create a directory to mount files and folder in and out of container. You might have one of these directories that is shared for ws/ui/daemon.
Code Block |
---|
2.5 $ mkdir -p /opt/grouperContainer
2.5 $ mkdir -p /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes
|
Create a local database. Preferred is postgres, but could be mysql or oracle too. (e.g. mysql, utf8, bin collation, create a user and password, and grant all to the new database from username and password) Set grouper.hibernate.properties. Note, for DB URL, "localhost" is the container itself, not the enclosing server. You need to use an IP address that the container can communicate with. Look in the grouper.hibernate.properties for documentation on setting up the url.
Code Block |
---|
2.5 $ vi /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/grouper.hibernate.properties
hibernate.connection.url = jdbc:mysql://192.168.86.71:3306/grouper_v2_5?useSSL=false
hibernate.connection.username = grouper_v2_5
hibernate.connection.password = ************
# what version should we auto install DDL up to. You should put the major and minor version here (e.g. 2.5.*). Or you could go to a build number if you like,
# or nothing to not auto DDL. e.g. 2.5.32 or 2.5.*
# {valueType: "string"}
registry.auto.ddl.upToVersion = 2.5.*
# UI basic auth is for quick start. Set to false when you migrate to shib or something else
grouper.is.ui.basicAuthn=true
grouper.is.ws.basicAuthn=true
grouper.is.scim.basicAuthn = true |
If you cant connect to the database, go in the container (instructions later ) and test the communication with telnet
Code Block |
---|
grouperContainer $ docker exec -it grouper-daemon /bin/bash
[root@0d9054515bed WEB-INF]# yum install telnet
[root@0d9054515bed WEB-INF]# telnet database-2.cstlzkqw179p.us-east-1.rds.amazonaws.com 3306
Trying 172.30.3.40...
Connected to database-2.cstlzkqw179p.us-east-1.rds.amazonaws.com.
Escape character is '^]'.
X
5.5.5-10.4.8-MariaDBK;&I~bLþ8pOz8H?EzW(\mysql_native_password^CConnection closed by foreign host.
[root@0d9054515bed WEB-INF]#
|
- The container contains jdbc drivers for hsql, msyql and postgres. If you're using Oracle, you'll need to add the jar.
Might want to use: https://raw.githubusercontent.com/Internet2/grouper/GROUPER_2_4_BRANCH/grouper/lib/jdbcSamples/ojdbc6_g.jar
Might want to use: https://repo1.maven.org/maven2/com/oracle/ojdbc/ojdbc8/19.3.0.0/ojdbc8-19.3.0.0.jar
Code Block |
---|
2.5 $ ls -al /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/lib/ojdbc6_g.jar |
Set morphString.properties unique key for encryption
Code Block |
---|
2.5 $ vi /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/morphString.properties
# random 16 char alphanumeric upper/lower
encrypt.key = ******************* |
Decide how many containers
Strategy | Containers | Notes |
---|
SEPARATE-CONTAINERS | ui ws daemon scim | More like a production env Uses more memory Can control, bring up down, configure each separately Need to manage ports. Generally 443 for UI, 8443 for WS, 8444 for Scim |
ALL-IN-ONE | all | Runs everything in one container. Don't do this in prod Uses less memory When anything is up or down all is up or down Can use 443 for UI, WS, Scim |
UI-WS | ui-ws daemon | This is not documented here. Don't do this in prod You can have a hybrid and put whatever components in whatever containers you want |
Configure logging
There are a few strategies to the maturity level 0 logging. If you have all grouper services in one container for your host, create one log dir on the host:
Code Block |
---|
2.5 $ mkdir -p /opt/grouperContainer/logs
2.5 $ chmod o+rwx /opt/grouperContainer/logs |
If you have If you have multiple containers in a host, then make a log dir for each, and you will change the docker run command to "mount" the inner dir (/opt/grouper/logs) to the outer dir. The chmod is needed if docker runs as a different user. On macs you might not need the chmod.
Code Block |
---|
(SEPARATE-CONTAINERS)
2.5 $ mkdir -p /opt/grouperContainer/logs/grouper-ws-logs
2.5 $ mkdir -pchmod o+rwx /opt/grouperContainer/logs/grouper-daemonws-logs
2.5 $ mkdir -p /opt/grouperContainer/logs/grouper-ui-logs |
This file in generally the same so you log to the same place (/opt/grouper/logs) in your container, just matters where you mount that outside
Code Block |
---|
daemon-logs
2.5 $ vichmod o+rwx /opt/grouperContainer/slashRoot/optlogs/grouper/grouperWebapp/WEB-INF/classes/log4j.properties
## Log messages to stderr
log4j.appender.grouper_stderr = org.apache.log4j.ConsoleAppender
log4j.appender.grouper_stderr.Target = System.err
log4j.appender.grouper_stderr.layout = org.apache.log4j.PatternLayout
log4j.appender.grouper_stderr.layout.ConversionPattern = %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n
## Grouper API error logging-daemon-logs
2.5 $ mkdir -p /opt/grouperContainer/logs/grouper-ui-logs
2.5 $ chmod o+rwx /opt/grouperContainer/logs/grouper-ui-logs |
Below you will see who writes to logs (docker user), and you can change the owner and permissions
Make sure this env variable is provided (v2.5.26+):
Code Block |
---|
-e GROUPER_LOG_TO_HOST=true |
Expand |
---|
title | The previous way to switch to local logs |
---|
|
This file in generally the same so you log to the same place (/opt/grouper/logs) in your container, just matters where you mount that outside Code Block |
---|
2.5 $ vi /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/log4j.properties
## Log messages to stderr
log4j.appender.grouper_ | errorstderr = org.apache.log4j. | DailyRollingFileAppenderConsoleAppender
log4j.appender.grouper_ | errorFile/opt/grouper/logs/grouper.logSystem.err
log4j.appender.grouper_ | error.DatePattern = '.'yyyy-MM-dd
log4j.appender.grouper_error.MaxBackupIndex = 30
log4j.appender.grouper_errorstderr.layout = org.apache.log4j.PatternLayout
log4j.appender.grouper_ | errorstderr.layout.ConversionPattern = %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n
## Grouper API error logging
log4j.appender.grouper_ | daemonerror = org.apache.log4j.DailyRollingFileAppender
log4j.appender.grouper_ | daemonerror.File = /opt/grouper/logs/ | grouperDaemongrouper.log
log4j.appender.grouper_ | daemonerror.DatePattern = '.'yyyy-MM-dd
log4j.appender.grouper_ | daemonerror.MaxBackupIndex = 30
log4j.appender.grouper_ | daemonerror.layout = org.apache.log4j.PatternLayout
log4j.appender.grouper_ | daemonerror.layout.ConversionPattern = %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n
log4j.appender.grouper_ | pspngdaemon = org.apache.log4j.DailyRollingFileAppender
log4j.appender.grouper_ | pspngdaemon.File = /opt/grouper/logs/ | pspnggrouperDaemon.log
log4j.appender.grouper_ | pspngdaemon.DatePattern = '.'yyyy-MM-dd
log4j.appender.grouper_ | pspngdaemon.MaxBackupIndex = 30
log4j.appender.grouper_ | pspngdaemon.layout = org.apache.log4j.PatternLayout
log4j.appender.grouper_ | pspngdaemon.layout.ConversionPattern = %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n |
# Loggers
## Default logger; will log *everything*rootLoggerWARN, grouper_stderr, grouper_error
log4j.logger.edu = ERROR, grouper_stderr
log4j.logger.com = ERROR, grouper_stderr
log4j.logger.org = ERROR, grouper_stderr
log4j.logger.edu.internet2.middleware.grouper.app.loader.GrouperLoaderLog = DEBUG, grouper_daemon
log4j.additivity.edu.internet2.middleware.grouper.app.loader.GrouperLoaderLog = false
log4j.logger.edu.internet2.middleware.grouper.pspng = INFO, grouper_pspng
log4j.additivity.edu.internet2.middleware.grouper.pspng = false |
Allow grouper db config from all. You can decide if you trust your authn and mfa if you want to leave this open, or lock it down to your vpn or whatever.
Code Block |
---|
2.5 $ vi /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/grouper-ui.properties
grouperUi.configurationEditor.sourceIpAddresses = 0.0.0.0/0 |
org.apache.log4j.DailyRollingFileAppender
log4j.appender.grouper_pspng.File = /opt/grouper/logs/pspng.log
log4j.appender.grouper_pspng.DatePattern = '.'yyyy-MM-dd
log4j.appender.grouper_pspng.MaxBackupIndex = 30
log4j.appender.grouper_pspng.layout = org.apache.log4j.PatternLayout
log4j.appender.grouper_pspng.layout.ConversionPattern = %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n
# Loggers
## Default logger; will log *everything*
log4j.rootLogger = WARN, grouper_stderr, grouper_error
log4j.logger.edu = ERROR, grouper_stderr
log4j.logger.com = ERROR, grouper_stderr
log4j.logger.org = ERROR, grouper_stderr
log4j.logger.edu.internet2.middleware.grouper.app.loader.GrouperLoaderLog = DEBUG, grouper_daemon
log4j.additivity.edu.internet2.middleware.grouper.app.loader.GrouperLoaderLog = false
log4j.logger.edu.internet2.middleware.grouper.pspng = INFO, grouper_pspng
log4j.additivity.edu.internet2.middleware.grouper.pspng = false |
|
Allow grouper db config from all. You can decide if you trust your authn and mfa if you want to leave this open, or lock it down to your vpn or whatever.
Code Block |
---|
2.5 $ vi /opt/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/grouper-ui.properties
grouperUi.configurationEditor.sourceIpAddresses = 0.0.0.0/0 |
Self-signed SSL (no need to do this anymore, this is now an env var instead)
Code Block |
---|
-e GROUPER_SELF_SIGNED_CERT=true |
Expand |
---|
This is the old way: Code Block |
---|
slashRoot $ mkdir -p /opt/grouperContainer/slashRoot/etc/httpd/conf.d
slashRoot $ vi /opt/grouperContainer/slashRoot/etc/httpd/conf.d/ssl-enabled.conf
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20- |
|
Self-signed SSL (no need to do this anymore, this is now an env var instead)
Expand |
---|
This is the old way: Code Block |
---|
slashRoot $ mkdir -p /opt/grouperContainer/slashRoot/etc/httpd/conf.d
slashRoot $ vi /opt/grouperContainer/slashRoot/etc/httpd/conf.d/ssl-enabled.conf
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder on
SSLCompression off
# OCSP Stapling, only in httpd 2.3.3 and later
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)
Listen 443 https
<VirtualHost *:443>
RewriteEngine on
RewriteRule "^/$" "/grouper/" [R]
SSLEngine on
#SSLCertificateChainFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
# HSTS (mod_headers is required) (15768000 seconds = 6 months)
Header always set Strict-Transport-Security "max-age=15768000"
</VirtualHost> |
|
Make a Dockerfile and subcontainer (optional, not needed)
this is maturity level 1)
Take out shib, adjust the proxy directives (this is now an env var)
Expand |
---|
This is the old way
Code Block |
---|
slashRoot $ docker cp 058adff0568c:/etc/httpd/conf.d/grouper-www.conf |
|
Code Block |
---|
slashRoot $ vi/Dockerfile
# this matches the version you decided on from release notes
FROM i2incommon/grouper:2.5.XX
|
Make container (optional, not needed). Note you could have one subcontainer (recommended if possible), and deploy that to UI/WS/daemon (either ALL-IN-ONE or SEPARATE-CONTAINERS)
Code Block |
---|
grouperContainer $ docker build -t my-grouper-2.5.XX .
Sending build context to Docker daemon 216.1kB
Step 1/2 : FROM i2incommon/grouper:2.5.XX
---> 04ced0374ad5
---> Running in 7bd1a51c3552
Removing intermediate container 7bd1a51c3552
---> ff79b4b2afb9
Successfully built ff79b4b2afb9
Successfully tagged my-grouper-2.5.XX:latest |
Take out shib, adjust the proxy directives (this is now an env var)
Expand |
---|
This is the old way
Code Block |
---|
slashRoot $ docker cp 058adff0568c:/etc/httpd/conf.d/grouper-www.conf /opt/grouperContainer/slashRoot/etc/httpd/conf.d/grouper-www.conf
slashRoot $ vi /opt/grouperContainer/slashRoot/etc/httpd/conf.d/grouper-www.conf
Timeout 2400
ProxyTimeout 2400
ProxyBadHeader Ignore
ProxyPass /grouper ajp://localhost:8009/grouper timeout=2400
ProxyPass /grouper-ws ajp://localhost:8009/grouper timeout=2400
ProxyPass /grouper-ws-scim ajp://localhost:8009/grouper timeout=2400
RewriteEngine on
RewriteCond %{REQUEST_URI} "^/$"
RewriteRule . %{REQUEST_SCHEME}://%{HTTP_HOST}/grouper/ [R=301,L]
#<Location /grouper>
# AuthType shibboleth
# ShibRequestSetting requireSession 1
# ShibRequireSession on
# ShibUseHeaders On
# require shibboleth
#</Location>
|
Set the owner and permissions of the log dir
Code Block |
---|
At first, set it world writable
[root@ip-172-30-3-152 logs]# chmod -R 777 /opt/grouperContainer/logs |
We need to setup the docker run commands. There are bunch of choices here, e.g. are you running ui/ws/daemon in one container, or a container for each? This assumes the starting point on host is /opt/grouperContainer, but could be other places
Docker run option | Sample | Description |
---|
--detach | run in background | --mount for logs | --mount type=bind,src=/opt/grouperContainer/logs,dst=/opt/grouper/logs | mount logs if one grouper container on host |
--mount type=bind,src=/opt/grouperContainer/logs/grouper-ui-logs,dst=/opt/grouper/logs | mount ui logs if multiple grouper containers on host | --mount type=bind,src=/opt/grouperContainer/logs/grouper-ws-logs,dst=/opt/grouper/logs | mount ws logs if multiple grouper containers on host | --mount type=bind,src=/opt/grouperContainer/logs/grouper-daemon-logs,dst=/opt/grouper/logs | mount daemon logs if multiple grouper containers on host | --mount for overlays | --mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot | this slashRoot directory will take any files and overlay into the container e.g. to overlay the grouper-www.conf file, put it in the host in /opt/grouperContainer/slashRoot/etc/httpd/conf.d/grouper-www.conf |
--name | --name grouper-daemon --name grouper-ui --name grouper-ws | put a name label for the container that you can use to differentiate from other containers in your docker service. generally we use grouper-ui, grouper-daemon, grouper-ws you can use whatever you want |
-e | -e SELF_SIGNED_CERT=true -e GROUPER_MAX_MEMORY='3g' -e RUN_SHIB_SP=false | add in environment variables documented here |
timezone | -e TZ=America/New_York | might want to add a timezone |
network settings | --net=host | depending on how your containers need to talk to each other, adjust the docker network settings. See Docker documentation |
port mapping | --publish 443:443 | listen on the host port and translate that to the container port |
docker-image | i2incommon/grouper:2.5.XX | put the docker image label from grouper if you dont have a Dockerfile and subcontainer |
my-grouper-2.5.XX:latest | put the docker image label of you subcontainer if you made one from Dockerfile | command | ui
ws
daemon
scim
<none>
ui-ws
command documented here each for SEPARATE-CONTAINERS | -e GROUPER_DAEMON=true ui-ws | command to run ALL-IN-ONE container | (ALL-IN-ONE), you need one shell script. Use the table above to customize. The one below is just an example.
Code Block |
---|
grouperContainer $ vi /opt/grouperContainer/grouperAllDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --mount type=bind,src=/opt/grouperContainer/logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e RUN_SHIB_SP='false' \
-e SELF_SIGNED_CERT='true' -e GROUPER_DAEMON=true --name grouper-all --publish 443:443 my-grouper-2.5.XX:latest ui-ws
grouperContainer $ chmod +x /opt/grouperContainer/grouperAllDockerRun.sh |
(SEPARATE-CONTAINERS) Make your UI docker run command in a shell script. Use the table above to customize. The one below is just an example.
Code Block |
---|
grouperContainer $ vi /opt/grouperContainer/grouperUiDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --mount type=bind,src=/opt/grouperContainer/logs/grouper-ui-logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e RUN_SHIB_SP='false' \
-e SELF_SIGNED_CERT='true' --name grouper-ui --publish 443:443 my-grouper-2.5.XX:latest ui
grouperContainer $ chmod +x /opt/grouperContainer/grouperUiDockerRun.sh |
(SEPARATE-CONTAINERS) Make your UI docker run command in a shell script. Use the table above to customize. The one below is just an example.
Note, since the UI and WS are on the same host, we use the host port of 8443 for web services. In production they will have different domain names and 443 so this is for dev only
Code Block |
---|
2.5 $ vi /opt/grouperContainer/grouperWsDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --mount type=bind,src=/opt/grouperContainer/logs/grouper-ws-logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e SELF_SIGNED_CERT='true' \
--name grouper-ws --publish 8443:443 my-grouper-2.5.XX:latest ws
2.5 $ chmod +x /opt/grouperContainer/grouperWsDockerRun.sh |
(SEPARATE-CONTAINERS) Make your Daemon docker run command in a shell script. Use the table above to customize. The one below is just an example.
Code Block |
---|
grouperContainer $ vi /opt/grouperContainer/grouperDaemonDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --mount type=bind,src=/opt/grouperContainer/logs/grouper-daemon-logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot --name grouper-daemon my-grouper-2.5.XX:latest daemon
grouperContainer $ chmod +x /opt/grouperContainer/grouperDaemonDockerRun.sh |
(SEPARATE-CONTAINERS) Make your Scim docker container. Note, Scim is not a commonly used feature of Grouper. Until you need it you should not use it. Note, since the UI and Scim are on the same host, we use the host port of 8444 for scim. In production they will have different domain names and 443 so this is for dev only
Code Block |
---|
2.5 $ vi /opt/grouperContainer/grouperScimDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --mount type=bind,src=/opt/grouperContainer/logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e SELF_SIGNED_CERT='true' \
--name grouper-scim --publish 8444:443 my-grouper-2.5.XX:latest scim
2.5 $ chmod +x /opt/grouperContainer/grouperScimDockerRun.sh
2.5 $ /opt/grouperContainer/grouperScimDockerRun.sh
2.5 $ |
Start container init database, note if not creating new container with Dockerfile, just use the container label i2incommon/grouper:2.5.XX
Code Block |
---|
(SEPARATE-CONTAINERS)
grouperContainer $ /opt/grouperContainer/grouperDaemonDockerRun.sh
grouperContainer $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a63006217009 my-grouper-2.5.XX:latest "/usr/local/bin/entr…" 11 minutes ago Up 10 minutes 80/tcp, 443/tcp grouper-daemon
grouperContainer $
(ALL-IN-ONE)
grouperContainer $ /opt/grouperContainer/grouperAllDockerRun.sh
grouperContainer $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a63006217009 my-grouper-2.5.XX:latest "/usr/local/bin/entr…" 11 minutes ago Up 10 minutes 80/tcp, 443/tcp grouper-all
grouperContainer $ |
Set the owner and permissions of the log dir
Code Block |
---|
after running container, see what user the docker container used to write logs to the host. Find a log file and see the owner/group. Then change owner of logs folder to whatever the container writes as
(SEPARATE-CONTAINERS)
[root@ip-172-30-3-152 logs]# ls -latr /opt/grouperContainer/logs/grouper-daemon-logs/grouper.log
-rw-r-----. 1 polkitd systemd-coredump 0 Apr 8 05:56 grouper.log
(ALL-IN-ONE)
[root@ip-172-30-3-152 logs]# ls -latr /opt/grouperContainer/logs/grouper.log
-rw-r-----. 1 polkitd systemd-coredump 0 Apr 8 05:56 grouper.log
(BOTH)
[root@ip-172-30-3-152 logs]# chown -R polkitd.systemd-coredump /opt/grouperContainer/logs
[root@ip-172-30-3-152 logs]# chmod -R 755 /opt/grouperContainer/logs
[root@ip-172-30-3-152 logs]# |
Check logs if there is a problem. Look for errors. Shell into the container to troubleshoot
Code Block |
---|
(SEPARATE-CONTAINERS)
grouperContainer $ docker logs grouper-daemon | grep -i error
grouperContainer $ cat /opt/grouperContainer/logs/grouper-daemon-logs/grouper.log
(ALL-IN-ONE)
grouperContainer $ docker logs grouper-all | grep -i errorgrouperContainer $ cat /opt/grouperContainer/logs/grouper.log
(BOTH)
grouperContainer $ docker exec -it grouper-daemon /bin/bash
grouperContainer $ ps -ef | grep tomee
|
Note: the database is initialized. See the tables in the database
Image Removed
If tables arent there, go in and run gsh
Code Block |
---|
(SEPARATE-CONTAINERS)
grouperContainer $ docker exec -it grouper-daemon /bin/bash
[root@0d9054515bed WEB-INF]# cd /opt/grouper/grouperWebapp/WEB-INF/bin/
[root@0d9054515bed bin]# ./gsh.sh -registry -check -runscript
(ALL-IN-ONE)
grouperContainer $ docker exec -it grouper-all /bin/bash
[root@0d9054515bed WEB-INF]# cd /opt/grouper/grouperWebapp/WEB-INF/bin/
[root@0d9054515bed bin]# ./gsh.sh -registry -check -runscript
|
Shell in there
Code Block |
---|
(SEPARATE-CONTAINERS)
2.5 $ docker exec -it grouper-daemon /bin/bash
(ALL-IN-ONE)
2.5 $ docker exec -it grouper-all /bin/bash |
Create passwords for UI. Change the four asterisks (****) with the password you want. You can change "GrouperSystem" with another subject that resolves
Code Block |
---|
[root@d588628876f7 bin]# cd /opt/grouper/grouperWebapp/WEB-INF/bin
[root@d588628876f7 bin]# vi createUiPass.gsh
grouperPasswordSave = new GrouperPasswordSave();
grouperPasswordSave.assignUsername("GrouperSystem").assignPassword("****").assignEntityType("username");
grouperPasswordSave.assignApplication(GrouperPassword.Application.UI);
new Authentication().assignUserPassword(grouperPasswordSave);
[root@d588628876f7 bin]# ./gsh.sh createUiPass.gsh
[root@d588628876f7 bin]# rm createUiPass.gsh |
Create a WS/SCIM username and password in container (you should already be in there). Change the four asterisks (****) with the password you want. You can change "GrouperSystem" with another subject that resolves
Code Block |
---|
[root@d588628876f7 bin]# vi createWsPass.gsh
grouperPasswordSave = new GrouperPasswordSave();
grouperPasswordSave.assignUsername("GrouperSystem").assignPassword("****").assignEntityType("username");
grouperPasswordSave.assignApplication(GrouperPassword.Application.WS);
new Authentication().assignUserPassword(grouperPasswordSave);
[root@d588628876f7 bin]# ./gsh.sh createWsPass.gsh |
(SEPARATE-CONTAINERS) Run the UI container
Code Block |
---|
grouperContainer $ /opt/grouperContainer/grouperUiDockerRun.sh
|
- The Grouper UI should now be accessible at https://whatever.server.edu:8443/grouper and will prompt for credentials via basic auth.
/slashRoot/etc/httpd/conf.d/grouper-www.conf
slashRoot $ vi /opt/grouperContainer/slashRoot/etc/httpd/conf.d/grouper-www.conf
Timeout 2400
ProxyTimeout 2400
ProxyBadHeader Ignore
ProxyPass /grouper ajp://localhost:8009/grouper timeout=2400
ProxyPass /grouper-ws ajp://localhost:8009/grouper timeout=2400
ProxyPass /grouper-ws-scim ajp://localhost:8009/grouper timeout=2400
RewriteEngine on
RewriteCond %{REQUEST_URI} "^/$"
RewriteRule . %{REQUEST_SCHEME}://%{HTTP_HOST}/grouper/ [R=301,L]
#<Location /grouper>
# AuthType shibboleth
# ShibRequestSetting requireSession 1
# ShibRequireSession on
# ShibUseHeaders On
# require shibboleth
#</Location>
|
|
We need to setup the docker run commands. There are bunch of choices here, e.g. are you running ui/ws/daemon in one container, or a container for each? This assumes the starting point on host is /opt/grouperContainer, but could be other places
Docker run option | Sample | Description |
---|
--detach |
| run in background |
--mount for logs | --mount type=bind,src=/opt/grouperContainer/logs,dst=/opt/grouper/logs | mount logs if one grouper container on host |
| --mount type=bind,src=/opt/grouperContainer/logs/grouper-ui-logs,dst=/opt/grouper/logs | mount ui logs if multiple grouper containers on host |
| --mount type=bind,src=/opt/grouperContainer/logs/grouper-ws-logs,dst=/opt/grouper/logs | mount ws logs if multiple grouper containers on host |
| --mount type=bind,src=/opt/grouperContainer/logs/grouper-daemon-logs,dst=/opt/grouper/logs | mount daemon logs if multiple grouper containers on host |
--mount for overlays | --mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot | this slashRoot directory will take any files and overlay into the container e.g. to overlay the grouper-www.conf file, put it in the host in /opt/grouperContainer/slashRoot/etc/httpd/conf.d/grouper-www.conf |
--name | --name grouper-daemon --name grouper-ui --name grouper-ws | put a name label for the container that you can use to differentiate from other containers in your docker service. generally we use grouper-ui, grouper-daemon, grouper-ws you can use whatever you want |
--hostname | --hostname myGrouperUi2 | sets the hostname which is used in logs and audits |
-e | -e GROUPER_SELF_SIGNED_CERT=true -e GROUPER_MAX_MEMORY='3g' -e GROUPER_RUN_SHIB_SP=false | add in environment variables documented here |
timezone | -e TZ=America/New_York | might want to add a timezone |
network settings | --net=host | depending on how your containers need to talk to each other, adjust the docker network settings. See Docker documentation |
restart policies | --restart always | automatically start containers (e.g. after reboot). See Docker documentation for various options. |
port mapping | --publish 443:443 | listen on the host port and translate that to the container port generally you want apache 443 |
| --publish 80:80 | if you want apache non-ssl (maybe external load balancer on trusted network?) |
| --publish 8009:8009 | if you want to publish the jk tomcat port for an apache outside of the container |
| --publish 8443:443 | 8443 on outside if you have multiple containers on one host and 443 is already used |
docker-image | i2incommon/grouper:2.5.XX | put the docker image label from grouper if you dont have a Dockerfile and subcontainer |
| my-grouper-2.5.XX:latest | put the docker image label of you subcontainer if you made one from Dockerfile or grouper image |
command | ui ws daemon scim <none> ui-ws quickstart | command documented here each for SEPARATE-CONTAINERS |
| -e GROUPER_DAEMON='true ui-ws' | command to run ALL-IN-ONE container |
(ALL-IN-ONE), you need one shell script. Use the table above to customize. The one below is just an example.
Code Block |
---|
grouperContainer $ vi /opt/grouperContainer/grouperAllDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --restart always --mount type=bind,src=/opt/grouperContainer/logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e GROUPER_RUN_SHIB_SP='false' \
-e GROUPER_SELF_SIGNED_CERT='true' -e GROUPER_DAEMON=true --name grouper-all --publish 443:443 i2incommon/grouper:2.5.XX ui-ws
grouperContainer $ chmod +x /opt/grouperContainer/grouperAllDockerRun.sh |
(SEPARATE-CONTAINERS) Make your UI docker run command in a shell script. Use the table above to customize. The one below is just an example.
Code Block |
---|
grouperContainer $ vi /opt/grouperContainer/grouperUiDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --restart always --mount type=bind,src=/opt/grouperContainer/logs/grouper-ui-logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e GROUPER_RUN_SHIB_SP='false' \
-e GROUPER_SELF_SIGNED_CERT='true' --name grouper-ui --publish 443:443 i2incommon/grouper:2.5.XX ui
grouperContainer $ chmod +x /opt/grouperContainer/grouperUiDockerRun.sh |
(SEPARATE-CONTAINERS) Make your WS docker run command in a shell script. Use the table above to customize. The one below is just an example.
Note, since the UI and WS are on the same host, we use the host port of 8443 for web services. In production they will have different domain names and 443 so this is for dev only
Code Block |
---|
2.5 $ vi /opt/grouperContainer/grouperWsDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --restart always --mount type=bind,src=/opt/grouperContainer/logs/grouper-ws-logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e GROUPER_SELF_SIGNED_CERT='true' \
--name grouper-ws --publish 8443:443 i2incommon/grouper:2.5.XX ws
2.5 $ chmod +x /opt/grouperContainer/grouperWsDockerRun.sh |
(SEPARATE-CONTAINERS) Make your Daemon docker run command in a shell script. Use the table above to customize. The one below is just an example.
Code Block |
---|
grouperContainer $ vi /opt/grouperContainer/grouperDaemonDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --restart always --mount type=bind,src=/opt/grouperContainer/logs/grouper-daemon-logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot --name grouper-daemon i2incommon/grouper:2.5.XX daemon
grouperContainer $ chmod +x /opt/grouperContainer/grouperDaemonDockerRun.sh |
(SEPARATE-CONTAINERS) Make your Scim docker container. Note, Scim is not a commonly used feature of Grouper. Until you need it you should not use it. Note, since the UI and Scim are on the same host, we use the host port of 8444 for scim. In production they will have different domain names and 443 so this is for dev only
Code Block |
---|
2.5 $ vi /opt/grouperContainer/grouperScimDockerRun.sh
#!/bin/bash (or whatever shell)
docker run --detach --restart always --mount type=bind,src=/opt/grouperContainer/logs,dst=/opt/grouper/logs \
--mount type=bind,src=/opt/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot -e GROUPER_SELF_SIGNED_CERT='true' \
--name grouper-scim --publish 8444:443 i2incommon/grouper:2.5.XX scim
2.5 $ chmod +x /opt/grouperContainer/grouperScimDockerRun.sh
|
(SEPARATE-CONTAINERS) Run the WS container
Code Block |
---|
2.5 $ /opt/grouperContainer/grouperWsDockerRun.sh
2.5 $ |
(SEPARATE-CONTAINERS) Run the SCIM container (if using SCIM, you probably dont need this)
Code Block |
---|
2.5 $ /opt/grouperContainer/grouperScimDockerRun.sh
2.5 $ |
(SEPARATE-CONTAINERS) If daemon not running (it probably is), run the daemon
Start container init database, note if not creating new container with Dockerfile, just use the container label i2incommon/grouper:2.5.XX
Code Block |
---|
(SEPARATE-CONTAINERS)
grouperContainer |
Code Block |
---|
2.5 $ /opt/grouperContainer/grouperDaemonDockerRun.sh
|
If you need to make changes to run command, or get a new image, you can remove a container. Change the "run" shell script, and run it again
Code Block |
---|
/grouperDaemonDockerRun.sh
grouperContainer $ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a63006217009 IMAGE my-grouper-2.5.XX:latest "/usr/local/bin/entr…" 11 minutes ago Up 10 COMMANDminutes 80/tcp, 443/tcp CREATED grouper-daemon
grouperContainer $
(ALL-IN-ONE)
grouperContainer $ /opt/grouperContainer/grouperAllDockerRun.sh
grouperContainer $ docker STATUSps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a63006217009 my-grouper-2.5.XX:latest "/usr/local/bin/entr…" 11 minutes ago Up PORTS10 minutes 80/tcp, 443/tcp grouper-all
grouperContainer NAMES
058adff0568c my-grouper-2.5.XX:latest "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes 80/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:8443->443/tcp grouper-ui
grouperContainer $ docker rm -f 058adff0568c
058adff0568c
|
Want to use tomcat authn? Here is an example with tomcat ldap authn.
grouper.hibernate.properties configures which Grouper 2.5 built in basic authn, these should not be set or set to false
Set the owner and permissions of the log dir
Code Block |
---|
after running container, see what user the docker container used to write logs to the host. Find a log file and see the owner/group. Then change owner of logs folder to whatever the container writes as
(SEPARATE-CONTAINERS)
[root@ip-172-30-3-152 logs]# ls -latr /opt/grouperContainer/logs/grouper-daemon-logs/grouper.log
-rw-r-----. 1 polkitd systemd-coredump 0 Apr 8 05:56 grouper.log
(ALL-IN-ONE)
[root@ip-172-30-3-152 logs]# ls -latr /opt/grouperContainer/logs/grouper.log
-rw-r-----. 1 polkitd systemd-coredump 0 Apr 8 05:56 grouper.log
(BOTH)
[root@ip-172-30-3-152 logs]# chown -R polkitd.systemd-coredump /opt/grouperContainer/logs
[root@ip-172-30-3-152 logs]# chmod -R 755 /opt/grouperContainer/logs
[root@ip-172-30-3-152 logs]# |
Check logs if there is a problem. Look for errors. Shell into the container to troubleshoot
Code Block |
---|
(SEPARATE-CONTAINERS)
grouperContainer $ docker logs grouper-daemon | grep -i error
grouperContainer $ cat /opt/grouperContainer/logs/grouper-daemon-logs/grouper.log
(ALL-IN-ONE)
grouperContainer $ docker logs grouper-all | grep -i errorgrouperContainer $ cat /opt/grouperContainer/logs/grouper.log
(BOTH)
grouperContainer $ docker exec -it grouper-daemon /bin/bash
grouperContainer $ ps -ef | grep tomee
|
- Note: the database is initialized. See the tables in the database
Image Added
If tables arent there, go in and run gsh
Code Block |
---|
(SEPARATE-CONTAINERS)
grouperContainer $ docker exec -it grouper-daemon /bin/bash
[root@0d9054515bed WEB-INF]# cd /opt/grouper/grouperWebapp/WEB-INF/bin/
[root@0d9054515bed WEB-INF]# cd bin
[root@0d9054515bed bin]# ./gsh.sh -registry -check -runscript
(ALL-IN-ONE)
grouperContainer $ docker exec -it grouper-all /bin/bash
[root@0d9054515bed WEB-INF]# cd /opt/grouper/grouperWebapp/WEB-INF/bin/
[root@0d9054515bed bin]# ./gsh.sh -registry -check -runscript
|
Shell in there
Code Block |
---|
(SEPARATE-CONTAINERS)
2.5 $ docker exec -it grouper-daemon /bin/bash
(ALL-IN-ONE)
2.5 $ docker exec -it grouper-all /bin/bash |
Create passwords for UI. Change the four asterisks (****) with the password you want. You can change "GrouperSystem" with another subject that resolves
Code Block |
---|
[root@d588628876f7 bin]# sudo -u tomcat bash
[tomcat @d588628876f7 bin]> cd /opt/grouper/grouperWebapp/WEB-INF/bin
[tomcat @d588628876f7 bin]> ./gsh.sh
gsh % new GrouperPasswordSave().assignApplication(GrouperPassword.Application.UI).assignUsername("GrouperSystem").assignPassword("****").save(); |
Expand |
---|
title | The old long hand way |
---|
|
Code Block |
---|
[root@d588628876f7 bin]# cd /opt/grouper/grouperWebapp/WEB-INF/bin
[root@d588628876f7 bin]# sudo -u tomcat bash
[tomcat @d588628876f7 bin]> vi createUiPass.gsh
grouperPasswordSave = new GrouperPasswordSave();
grouperPasswordSave.assignUsername("GrouperSystem").assignPassword("****").assignEntityType("username");
grouperPasswordSave.assignApplication(GrouperPassword.Application.UI);
new Authentication().assignUserPassword(grouperPasswordSave);
[tomcat @d588628876f7 bin]> ./gsh.sh createUiPass.gsh
[tomcat @d588628876f7 bin]> rm createUiPass.gsh |
|
Create a WS/SCIM username and password in container (you should already be in there). Change the four asterisks (****) with the password you want. You can change "GrouperSystem" with another subject that resolves
Code Block |
---|
[root@d588628876f7 bin]# cd /opt/grouper/grouperWebapp/WEB-INF/bin
[root@d588628876f7 bin]# sudo -u tomcat bash
[tomcat @d588628876f7 bin]> ./gsh.sh
gsh % new GrouperPasswordSave().assignApplication(GrouperPassword.Application.WS).assignUsername("GrouperSystem").assignPassword("****").save(); |
Expand |
---|
title | The old longhand way |
---|
|
Code Block |
---|
[root@d588628876f7 bin]# sudo -u tomcat bash
[tomcat @d588628876f7 bin]> vi createWsPass.gsh
grouperPasswordSave = new GrouperPasswordSave();
grouperPasswordSave.assignUsername("GrouperSystem").assignPassword("****").assignEntityType("username");
grouperPasswordSave.assignApplication(GrouperPassword.Application.WS);
new Authentication().assignUserPassword(grouperPasswordSave);
[tomcat @d588628876f7 bin]> ./gsh.sh createWsPass.gsh |
|
(SEPARATE-CONTAINERS) Run the UI container
Code Block |
---|
grouperContainer $ /opt/grouperContainer/grouperUiDockerRun.sh
|
- The Grouper UI should now be accessible at https://whatever.server.edu:443/grouper and will prompt for credentials via basic auth.
(SEPARATE-CONTAINERS) Run the WS container
Code Block |
---|
2.5 $ /opt/grouperContainer/grouperWsDockerRun.sh
2.5 $ |
(SEPARATE-CONTAINERS) Run the SCIM container (if using SCIM, you probably dont need this)
Code Block |
---|
2.5 $ /opt/grouperContainer/grouperScimDockerRun.sh
2.5 $ |
(SEPARATE-CONTAINERS) If daemon not running (it probably is), run the daemon
Code Block |
---|
2.5 $ /opt/grouperContainer/grouperDaemonDockerRun.sh
|
If you need to make changes to run command, or get a new image, you can remove a container. Change the "run" shell script, and run it again
Code Block |
---|
grouperContainer $ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
058adff0568c my-grouper-2.5.XX:latest "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes 80/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:8443->443/tcp grouper-ui
grouperContainer $ docker rm -f 058adff0568c
058adff0568c
|
- Add a subject source
- Add Shibboleth
- Add members to the wheel group
Code Block |
---|
[root@ip-172-30-3-152 grouperContainer]# more slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/grouper.hibernate.properties
# skip the important stuff #
# added by grouper-installer
grouper.is.ui.basicAuthn = false
# added by grouper-installer
grouper.is.ws.basicAuthn = false
|
web.xml: Code Block |
---|
[root@ip-172-30-3-152 grouperContainer]# more slashRoot/opt/grouper/grouperWebapp/WEB-INF/web.xml (from host, inside container is /opt/grouper/slashRoot)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:j2ee="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<!-- FOR WS ONLY -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Web services</web-resource-name>
<url-pattern>/services/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>grouper_user</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Web services</web-resource-name>
<url-pattern>/servicesRest/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<!-- NOTE: This role is not present in the default users file -->
<role-name>grouper_user</role-name>
</auth-constraint>
</security-constraint>
<!-- FOR UI ONLY -->
<security-constraint>
<web-resource-collection>
<web-resource-name>UI</web-resource-name>
<url-pattern>/grouperUi/app/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>grouper_user</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>UI</web-resource-name>
<url-pattern>/grouperUi/appHtml/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>grouper_user</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>UI</web-resource-name>
<url-pattern>/grouperExternal/app/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>grouper_user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Grouper Application</realm-name>
</login-config>
<!-- FOR BOTH -->
<security-role>
<description>
The role that is required to log in to the Grouper UI
</description>
<role-name>grouper_user</role-name>
</security-role>
</web-app> |
tomcat server.xml has some settings too, copy from inside the container to outside, and adjust it a bit Code Block |
---|
[root@ip-172-30-3-152 grouperContainer]# this is slashRoot/opt/tomee/conf/server.xml
FROM:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" tomcatAuthentication="false" ...
TO:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" tomcatAuthentication="true" ...Might need to add something like this in the right place:
<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionURL="ldaps://ldap.ad.ufl.edu:636"
connectionName="CN=something-grouper,OU=Grouper,OU=Service Accounts,OU=somead,DC=ad,DC=school,DC=edu"
connectionPassword="XXXXX"
userBase="OU=users,DC=ad,DC=ufl,DC=edu"
userSubtree="true"
userSearch="(userPrincipalName={0})"
adCompat="true"
allRolesMode="authOnly"
/>
</Realm>
|
df