Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenUnisonDocker

This file builds the base image for OpenUnison. There are two options for deploying OpenUnison into your Docker server:

  1. Deploy the OpenUnisonDockerDeploy deploy image
  2. Use shared volumes to start OpenUnison using an underlying environment

The first choice is the easiest for getting up and running, but offers several challenges for deployments and security (how do you secure artifacts? how do you store passwords?). The second option makes for a more manageable deployment, but requires more steps. See the OpenUnisonDockerDeploy project for details on how to deploy OpenUnison using the deploy Dockerfile.

For details on how to configure OpenUnison - https://www.tremolosecurity.com/docs/tremolosecurity-docs/1.0.6/openunison/openunison.html

Environment Variables and System Properties

OpenUnison will interpret any configuration options between #[] as either an environment variable or a system property (environment variable first, then if not an environment variable it will be checked for as a system property).

Create OpenUnison Files on the Host System

Prior to setting up OpenUnison create a directory on your Docker host for the OpenUnison configuration files and for the Tomcat configuration file. For the sake of simplicity, we'll asssume that all configuration files will go into /etc/openunison:

$ mkdir -p /etc/openunison
$ mkdir -p /etc/tomcat

Next, create the /etc/openunison/unisonService.props file based on the below template:

com.tremolosecurity.openunison.forceToSSL=true
com.tremolosecurity.openunison.openPort=8080
com.tremolosecurity.openunison.securePort=8443
com.tremolosecurity.openunison.externalOpenPort=8080
com.tremolosecurity.openunison.externalSecurePort=8443
#Uncomment and set for production deployments
com.tremolosecurity.openunison.activemqdir=/var/lib/unison-activemq

Now create the OpenUnison key store:

$ keytool -genkeypair -storetype JCEKS -alias unison-tls -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore /etc/openunison/unisonKeyStore.jks
$ keytool -genseckey -storetype JCEKS -alias session-unison -keyalg AES -keysize 256 -keystore /etc/openunison/unisonKeyStore.jks

We're assuming the same key aliases as the deploy image. Once these two files are created, next create the /etc/openunison/unison.xml file. The below file is a very basic starting point. Make sure to update the hosts (below its dockerhost.domain.com) and the keystore password.

<?xml version="1.0" encoding="UTF-8"?>
<tremoloConfigxmlns="http://www.tremolosecurity.com/tremoloConfig"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.tremolosecurity.com/tremoloConfig tremoloConfig.xsd">
<applicationsopenSessionCookieName="openSession"openSessionTimeout="9000">
<applicationname="LoginTest"azTimeoutMillis="30000" >
<urls>
<!-- The regex attribute defines if the proxyTo tag should be interpreted with a regex or not --><!-- The authChain attribute should be the name of an authChain -->
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.LoginTest">
<!-- The path of the logout URI -->
<paramname="logoutURI"value="/logout"/>
</filter>
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>
</azSuccess>
<azFail>Invalid Login</azFail>
<auFail>Invalid Login</auFail>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
<urlregex="false"authChain="formloginFilter"overrideHost="true"overrideReferer="true">
<!-- Any number of host tags may be specified to allow for an application to work on multiple hosts. Additionally an asterick (*) can be specified to make this URL available for ALL hosts -->
<host>dockerhost.domain.com</host>
<!-- The filterChain allows for transformations of the request such as manipulating attributes and injecting headers -->
<filterChain>
<filterclass="com.tremolosecurity.prelude.filters.StopProcessing" />
</filterChain>
<!-- The URI (aka path) of this URL -->
<uri>/logout</uri>
<!-- Tells OpenUnison how to reach the downstream application. The ${} lets you set any request variable into the URI, but most of the time ${fullURI} is sufficient -->
<proxyTo>http://dnm${fullURI}</proxyTo>
<!-- List the various results that should happen -->
<results>
<azSuccess>Logout</azSuccess>
</results>
<!-- Determine if the currently logged in user may access the resource. If ANY rule succeeds, the authorization succeeds. The scope may be one of group, dn, filter, dynamicGroup or custom The constraint identifies what needs to be satisfied for the authorization to pass and is dependent on the scope: * group - The DN of the group in OpenUnison's virtual directory (must be an instance of groupOfUniqueNames) * dn - The base DN of the user or users in OpenUnison's virtual directory * dynamicGroup - The DN of the dynamic group in OpenUnison's virtual directory (must be an instance of groupOfUrls) * custom - An implementation of com.tremolosecurity.proxy.az.CustomAuthorization -->
<azRules>
<rulescope="dn"constraint="o=Tremolo" />
</azRules>
</url>
</urls>
<!-- The cookie configuration determines how sessions are managed for this application -->
<cookieConfig>
<!-- The name of the session cookie for this application. Applications that want SSO between them should have the same cookie name -->
<sessionCookieName>tremolosession</sessionCookieName>
<!-- The domain of component of the cookie -->
<domain>dockerhost.domain.com</domain>
<!-- The URL that OpenUnison will interpret as the URL to end the session -->
<logoutURI>/logout</logoutURI>
<!-- The name of the AES-256 key in the keystore to use to encrypt this session -->
<keyAlias>session-unison</keyAlias>
<!-- If set to true, the cookie's secure flag is set to true and the browser will only send this cookie over https connections -->
<secure>false</secure>
<!-- The number of secconds that the session should be allowed to be idle before no longer being valid -->
<timeout>900</timeout>
<!-- required but ignored -->
<scope>-1</scope>
</cookieConfig>
</application>
<!-- Uncomment this block for web services --><!-- <application name="WebServices"> <urls> <url regex="false" authChain="sslCert"> <host>dockerhost.domain.com</host> <filterChain /> <uri>/services</uri> <results /> <azRules> <rule scope="dn" constraint="ou=CertAuth,o=Tremolo" /> </azRules> </url> </urls> <cookieConfig> <sessionCookieName>tremoloWSSession</sessionCookieName> <domain>dockerhost.domain.com</domain> <scope>-1</scope> <logoutURI>/logout</logoutURI> <keyAlias>session-wssession</keyAlias> <keyPassword> </keyPassword> <secure>true</secure> <timeout>900</timeout> </cookieConfig> </application>-->
</applications>
<myvdConfig>/etc/openunison/myvd.conf</myvdConfig>
<authMechs>
<mechanismname="loginForm">
<uri>/auth/formLogin</uri>
<className>com.tremolosecurity.proxy.auth.FormLoginAuthMech</className>
<init>
</init>
<params>
<param>FORMLOGIN_JSP</param>
</params>
</mechanism>
<mechanismname="anonymous">
<uri>/auth/anon</uri>
<className>com.tremolosecurity.proxy.auth.AnonAuth</className>
<init>
<!-- The RDN of unauthenticated users -->
<paramname="userName"value="uid=Anonymous"/>
<!-- Any number of attributes can be added to the anonymous user -->
<paramname="role"value="Users" />
</init>
<params>
</params>
</mechanism>
<mechanismname="certAuth">
<uri>/auth/ssl</uri>
<className>com.tremolosecurity.proxy.auth.CertAuth</className>
<init>
<!-- Comma seperated list of CRLs to check -->
<paramname="crl.names"value=""/>
</init>
<params>
</params>
</mechanism>
</authMechs>
<authChains>
<!-- An anonymous authentication chain MUST be level 0 -->
<chainname="anon"level="0">
<authMech>
<name>anonymous</name>
<required>required</required>
<params>
</params>
</authMech>
</chain>
<chainname="formloginFilter"level="20">
<authMech>
<name>loginForm</name>
<required>required</required>
<params>
<!-- Path to the login form -->
<paramname="FORMLOGIN_JSP"value="/auth/forms/defaultForm.jsp"/>
<!-- Either an attribute name OR an ldap filter mapping the form parameters. If this is an ldap filter, form parameters are identified by ${parameter} -->
<paramname="uidAttr"value="uid"/>
<!-- If true, the user is determined based on an LDAP filter rather than a simple user lookup -->
<paramname="uidIsFilter"value="false"/>
</params>
</authMech>
</chain>
<!-- Uncomment to support web services --><!-- <chain name="certClientAuth" level="40"> <authMech> <name>certAuth</name> <required>required</required> <params> <param name="uidAttr" value="(uid=${CN})" /> <param name="uidIsFilter" value="true"/> <param name="rdnAttribute" value="CN" /> <param name="defaultOC" value="inetOrgPerson" /> <param name="dnLabel" value="ou=CertAuth"/> <param name="issuer" value="OU=Dev, O=Tremolo Security Inc., C=US, ST=Virginia, CN=Root CA"/> </params> </authMech> </chain>-->
</authChains>
<resultGroups>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Logout">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/logout.jsp</value>
</result>
</resultGroup>
<!-- The name attribute is how the resultGroup is referenced in the URL -->
<resultGroupname="Invalid Login">
<!-- Each result should be listed -->
<result>
<!-- The type of result, one of cookie, header or redirect -->
<type>redirect</type>
<!-- The source of the result value, one of user, static, custom -->
<source>static</source>
<!-- Name of the resuler (in this case a cookie) and the value -->
<value>/auth/forms/defaultFailedLogin.jsp</value>
</result>
</resultGroup>
</resultGroups>
<keyStorePath>/etc/openunison/unisonKeyStore.jks</keyStorePath>
<keyStorePassword>start123</keyStorePassword>
</tremoloConfig>

Next create /etc/openunison/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPElog4j:configuration SYSTEM "log4j.dtd">
<log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/">
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Target"value="System.out"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="info" />
<appender-refref="console" />
</root>
</log4j:configuration>

Finally, create an /etc/openunison/myvd.conf

#Global AuthMechConfigserver.globalChain=
server.nameSpaces=rootdse,myvdroot,testuser
server.rootdse.chain=dse
server.rootdse.nameSpace=
server.rootdse.weight=0
server.rootdse.dse.className=net.sourceforge.myvd.inserts.RootDSE
server.rootdse.dse.config.namingContexts=o=Tremolo
server.myvdroot.chain=root
server.myvdroot.nameSpace=o=Tremolo
server.myvdroot.weight=0
server.myvdroot.root.className=net.sourceforge.myvd.inserts.RootObject
server.testuser.chain=admin
server.testuser.nameSpace=ou=testuser,o=Tremolo
server.testuser.weight=0
server.testuser.admin.className=com.tremolosecurity.proxy.myvd.inserts.admin.AdminInsert
server.testuser.admin.config.uid=test
server.testuser.admin.config.password=test

Create the Tomcat /etc/tomcat/server.xml File

The below server.xml file is tested with the OpenUnison image. It points to the /etc/openunison/unisonKeystore.jks file and the unison-tls key generated earlier. Make sure to replace the password with what you used to protect the unisonKeystore.jks file.

<?xml version='1.0' encoding='utf-8'?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html-->
<Serverport="8005"shutdown="SHUTDOWN">
<ListenerclassName="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html -->
<ListenerclassName="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<ListenerclassName="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<ListenerclassName="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users-->
<Resourcename="UserDatabase"auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html-->
<Servicename="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>--><!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080-->
<Connectorport="8080"protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
<!-- A "Connector" using the shared thread pool--><!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation that requires the JSSE style configuration. When using the APR/native implementation, the OpenSSL style configuration is required as described in the APR/native documentation -->
<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150"SSLEnabled="true"scheme="https"secure="true"clientAuth="want"sslProtocol="TLS"keystoreFile="/etc/openunison/unisonKeyStore.jks"keystoreType="JCEKS"keystorePass="start123"keyAlias="unison-tls"/>
<!-- Define an AJP 1.3 Connector on port 8009 --><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> --><!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --><!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">-->
<Enginename="Catalina"defaultHost="localhost">
<!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --><!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
<RealmclassName="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. -->
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Hostname="localhost"appBase="webapps"unpackWARs="true"autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --><!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" -->
<ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"prefix="localhost_access_log"suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

Run the Docker Image

Once all of the configuraiton files are deployed to the host, run the docker image:

$ docker run -ti -p 8080:8080 -p 8443:8443 -v /etc/openunison/:/etc/openunison/ -v /etc/tomcat/server.xml:/usr/local/tomcat/conf/server.xml tremolosecurity/openunison:1.0.6

About

Base image for OpenUnison

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors