- Install docker
See if docker is running
bin $ docker info Client: Debug Mode: false Server: Containers: 5 Running: 0 Paused: 0
List containers
bin $ docker ps --all CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ca762df952a6 tier/gte:101.1.1-201906 "/usr/local/bin/entr…" 9 months ago Exited (137) 9 months ago 101.1.1 bin $
Remove unneeded containers if necessary
bin $ docker rm -f ca762df952a6 ca762df952a6
- See which version of Grouper to run
Pull the image
bin $ docker pull i2incommon/grouper:2.5.20
(Reference command) List images
[root@ip-172-30-3-152 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE my-grouper-2.5.19 latest 918f5dd01bd5 6 hours ago 1.23GB i2incommon/grouper 2.5.19 f939770b7d91 34 hours ago 1.23GB [root@ip-172-30-3-152 ~]#
(Reference command) Remove old images
[root@ip-172-30-3-152 ~]# docker rmi 918f5dd01bd5 [root@ip-172-30-3-152 ~]# docker rmi f939770b7d91
Create a directory to mount files and folder in and out of container
2.5 $ mkdir -p /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot 2.5 $ mkdir -p /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes
- Create a local database (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
2.5 $ vi /Users/mchyzer/grouper/2.5/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 ui is running in container grouper.is.ui = false # if ws is running in container grouper.is.ws = false # if scim is running in container grouper.is.scim = false # if daemon is running in container grouper.is.daemon = true
- The container contains jdbc drivers for hsql, msyql and postgres. If you're using Oracle, you'll need to add the jar.
2.5 $ ls -al /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/lib/ojdbc6_g.jar
Set morphString.properties unique key for encryption
2.5 $ vi /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/morphString.properties # random 16 char alphanumeric upper/lower encrypt.key = *******************
Configure logging
2.5 $ mkdir -p /Users/mchyzer/grouper/2.5/grouperContainer/logs 2.5 $ vi /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot/opt/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 log4j.appender.grouper_error = org.apache.log4j.DailyRollingFileAppender log4j.appender.grouper_error.File = /opt/grouper/logs/grouper.log log4j.appender.grouper_error.DatePattern = '.'yyyy-MM-dd log4j.appender.grouper_error.MaxBackupIndex = 30 log4j.appender.grouper_error.layout = org.apache.log4j.PatternLayout log4j.appender.grouper_error.layout.ConversionPattern = %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n log4j.appender.grouper_daemon = org.apache.log4j.DailyRollingFileAppender log4j.appender.grouper_daemon.File = /opt/grouper/logs/grouperDaemon.log log4j.appender.grouper_daemon.DatePattern = '.'yyyy-MM-dd log4j.appender.grouper_daemon.MaxBackupIndex = 30 log4j.appender.grouper_daemon.layout = org.apache.log4j.PatternLayout log4j.appender.grouper_daemon.layout.ConversionPattern = %d{ISO8601}: [%t] %-5p %C{1}.%M(%L) - %x - %m%n log4j.appender.grouper_pspng = 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
(UI ONLY) Allow grouper db config from all (dev only)
2.5 $ vi /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes/grouper-ui.properties grouperUi.configurationEditor.sourceIpAddresses = 0.0.0.0/0
Self-signed SSL
slashRoot $ mkdir -p /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot/etc/httpd/conf.d slashRoot $ vi /Users/mchyzer/grouper/2.5/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
slashRoot $ vi /Users/mchyzer/grouper/2.5/grouperContainer/Dockerfile # this matches the version you decided on from release notes FROM i2incommon/grouper:2.5.19 # temporary 2.5.19 fix RUN chown -R tomcat:tomcat /opt/grouper/grouperWebapp # set how much memory you want. 3g is good for WS and UI, 12g for a large ldap provisioning daemon env ENV CATALINA_OPTS="-XX:+UseG1GC -Xmx3000m -XX:+UseStringDeduplication"
Make container
grouperContainer $ docker build -t my-grouper-2.5.20 . Sending build context to Docker daemon 216.1kB Step 1/2 : FROM i2incommon/grouper:2.5.15 ---> 04ced0374ad5 ---> Running in 7bd1a51c3552 Removing intermediate container 7bd1a51c3552 ---> ff79b4b2afb9 Successfully built ff79b4b2afb9 Successfully tagged my-grouper-2.5.15:latest
Temporarily start container to copy files out
grouperContainer $ docker run --detach --publish 8080:8080 --publish 8443:443 \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/logs,dst=/opt/grouper/logs \ --restart always --name grouper-daemon i2incommon/grouper:2.5.19 daemon grouperContainer $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 058adff0568c my-grouper-2.5.15:latest "/usr/local/bin/entr…" 3 seconds ago Up 2 seconds 80/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:8443->443/tcp grouper-daemon grouperContainer $
Go into the container and check logs
grouperContainer $ docker logs grouper-daemon grouperContainer $ docker exec -it grouper-daemon /bin/bash
- Note: the database is initialized. See the tables in the database
If tables arent there, go in and run gsh
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
(UI/WS/SCIM) Take out shib, adjust the proxy directives
slashRoot $ docker cp 058adff0568c:/etc/httpd/conf.d/grouper-www.conf /Users/mchyzer/grouper/2.5/grouperContainer/slashRoot/etc/httpd/conf.d/grouper-www.conf slashRoot $ vi /Users/mchyzer/grouper/2.5/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>
(UI ONLY) Run the container
Don't forget to change your grouper.hibernate.properties file:grouper.is.ui = true
grouperContainer $ docker ps --all CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 058adff0568c my-grouper-2.5.15: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 grouperContainer $ docker run --detach --publish 8080:8080 --publish 8443:443 \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/logs,dst=/opt/grouper/logs \ --restart always -e CATALINA_OPTS="-Xmx3000m" --name grouper-ui my-grouper-2.5.15:latest ui
Shell in there
2.5 $ docker exec -it grouper-ui /bin/bash
(UI ONLY) Create a UI username and password
cd /opt/grouper/grouperWebapp/WEB-INF/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
- (UI ONLY) The Grouper UI should now be accessible at https://localhost:8443/grouper and will prompt for credentials via basic auth.
(WS/SCIM ONLY) Create a WS/SCIM username and password
cd /opt/grouper/grouperWebapp/WEB-INF/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
(WS ONLY) Run the container
2.5 $ docker run --detach --publish 8080:8080 --publish 8443:443 \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/logs,dst=/opt/grouper/logs \ --restart always --name grouper-ws my-grouper-2.5.15:latest ws
(SCIM ONLY) Run the container
2.5 $ docker run --detach --publish 8080:8080 --publish 8443:443 \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/logs,dst=/opt/grouper/logs \ --restart always --name grouper-scim my-grouper-2.5.15:latest scim
(DAEMON ONLY) Run the daemon
2.5 $ docker run --detach --publish 8080:8080 --publish 8443:443 \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/slashRoot,dst=/opt/grouper/slashRoot \ --mount type=bind,src=/Users/mchyzer/grouper/2.5/grouperContainer/logs,dst=/opt/grouper/logs \ --restart always --name grouper-daemon my-grouper-2.5.15:latest daemon# tomee needs to run for the daemon to operate docker exec -it grouper-daemon /bin/bash /opt/tomee/bin/startup.sh
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[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:[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[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