Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request docker#57 from docker/2.4.0-a31-u14-w3-p3-20190304
2.4.0 a31 u14 w3 p3 20190304
chubing committed Mar 7, 2019
2 parents 27f3d1c + dbfb509 commit f29ec9e
Showing 13 changed files with 325 additions and 187 deletions.
17 changes: 12 additions & 5 deletions Dockerfile
@@ -3,9 +3,12 @@ FROM centos:centos7 as installing
RUN yum update -y \
&& yum install -y wget tar unzip dos2unix \
&& yum clean all

ARG GROUPER_CONTAINER_VERSION

ENV GROUPER_VERSION=2.3.0 \
JAVA_HOME=/usr/lib/jvm/zulu-8/
ENV GROUPER_VERSION=2.4.0 \
JAVA_HOME=/usr/lib/jvm/zulu-8/ \
GROUPER_CONTAINER_VERSION=$GROUPER_CONTAINER_VERSION

# use Zulu package
RUN rpm --import http://repos.azulsystems.com/RPM-GPG-KEY-azulsystems \
@@ -46,7 +49,7 @@ RUN echo 'Installing Grouper'; \

FROM centos:centos7 as cleanup

ENV GROUPER_VERSION=2.3.0 \
ENV GROUPER_VERSION=2.4.0 \
TOMCAT_VERSION=8.5.12 \
TOMEE_VERSION=7.0.0

@@ -93,10 +96,13 @@ LABEL author="tier-packaging@internet2.edu <tier-packaging@internet2.edu>" \
ImageType="Grouper" \
ImageName=$imagename \
ImageOS=centos7

ARG GROUPER_CONTAINER_VERSION

ENV JAVA_HOME=/usr/lib/jvm/zulu-8/ \
PATH=$PATH:$JAVA_HOME/bin \
GROUPER_HOME=/opt/grouper/grouper.apiBinary
GROUPER_HOME=/opt/grouper/grouper.apiBinary \
GROUPER_CONTAINER_VERSION=$GROUPER_CONTAINER_VERSION

RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime

@@ -118,7 +124,8 @@ RUN groupadd -r tomcat \
&& chown -R tomcat:tomcat /opt/tomee/logs/ /opt/tomee/temp/ /opt/tomee/work/ \
&& ln -s $JAVA_HOME/bin/java /etc/alternatives/java

RUN rm /etc/shibboleth/sp-key.pem /etc/shibboleth/sp-cert.pem
# does shib sp3 not generate these files?
# RUN rm /etc/shibboleth/sp-key.pem /etc/shibboleth/sp-cert.pem

COPY container_files/tier-support/ /opt/tier-support/
COPY container_files/usr-local-bin/ /usr/local/bin/
61 changes: 52 additions & 9 deletions Jenkinsfile
@@ -27,6 +27,9 @@ pipeline {
sh 'rm -rf ../bin/*'
sh 'mv ./bin/* ../bin/.'
}
// Build and test scripts expect that 'tag' is present in common.bash. This is necessary for both Jenkins and standalone testing.
// We don't care if there are more 'tag' assignments there. The latest one wins.
sh "echo >> common.bash ; echo \"tag=\\\"${tag}\\\"\" >> common.bash ; echo common.bash ; cat common.bash"
}
}
}
@@ -47,15 +50,55 @@ pipeline {
stage('Build') {
steps {
script {
docker.withRegistry('https://registry.hub.docker.com/', "dockerhub-$maintainer") {
def baseImg = docker.build("$maintainer/$imagename", "--no-cache .")
// test the environment
sh 'cd test-compose && ./compose.sh'
// bring down after testing
sh 'cd test-compose && docker-compose down'
baseImg.push("$tag")
}
}
try{
docker.withRegistry('https://registry.hub.docker.com/', "dockerhub-$maintainer") {
baseImg = docker.build("$maintainer/$imagename", "--build-arg GROUPER_CONTAINER_VERSION=$tag --no-cache .")
}
} catch(error) {
def error_details = readFile('./debug');
def message = "BUILD ERROR: There was a problem building ${imagename}:${tag}. \n\n ${error_details}"
sh "rm -f ./debug"
handleError(message)
}
}
}
}
stage('Test') {
steps {
script {
try {
sh 'bin/test.sh 2>&1 | tee debug ; test ${PIPESTATUS[0]} -eq 0'
} catch (error) {
def error_details = readFile('./debug')
def message = "BUILD ERROR: There was a problem testing ${imagename}:${tag}. \n\n ${error_details}"
sh "rm -f ./debug"
handleError(message)
}
}
}
}

stage('Push') {
steps {
script {
//// scan the image with clair
// sh 'docker run -p 5432:5432 -d --name clairdb arminc/clair-db:latest'
// sh 'docker run -p 6060:6060 --link clairdb:postgres -d --name clair arminc/clair-local-scan:v2.0.5'
// sh 'curl -L -o clair-scanner https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64'
// sh 'chmod 755 clair-scanner'
// sh "./clair-scanner --ip 172.17.0.1 -r test.out $maintainer/$imagename:latest"
//// test the environment
// sh 'docker kill clairdb'
// sh 'docker rm clairdb'
// sh 'docker kill clair'
// sh 'docker rm clair'
// sh 'cd test-compose && ./compose.sh'
//// bring down after testing
//sh 'cd test-compose && docker-compose down'
docker.withRegistry('https://registry.hub.docker.com/', "dockerhub-$maintainer") {
baseImg.push("$tag")
}
}
}
}
stage('Notify') {
12 changes: 11 additions & 1 deletion README.md
@@ -1,6 +1,16 @@
[![Build Status](https://jenkins.testbed.tier.internet2.edu/job/docker/job/grouper/job/master/badge/icon)](https://jenkins.testbed.tier.internet2.edu/job/docker/job/grouper/job/master/)
[![Build Status](https://jenkins.testbed.tier.internet2.edu/buildStatus/icon?job=docker/grouper/2.4.0-a29-u14-w3-p2-20190217)](https://jenkins.testbed.tier.internet2.edu/buildStatus/icon?job=docker/grouper/2.4.0-a29-u14-w3-p2-20190217)



# Upgrading from 2.3 to 2.4

If upgrading from Grouper version 2.3 to 2.4 and using LDAP, modifications will be needed in subject.properties and grouper-loaders.proprties. Further details about this can be found at the following URL:
https://spaces.at.internet2.edu/display/Grouper/vt-ldap+to+ldaptive+migration+for+LDAP+access

In particular, in subject.properties, *.param.base.value should be adjusted to only contain the RDN (Relative Distinguished Name), not the full DN. For example, "OU=People", not "OU=People,DC=domain,DC=edu"

Additional upgrade information can be found at the following URL: https://spaces.at.internet2.edu/display/Grouper/v2.4+Upgrade+Instructions+from+v2.3

# Supported tags

- latest
15 changes: 10 additions & 5 deletions container_files/grouper.installer.properties
@@ -1,7 +1,7 @@
# this should be before the version number
download.server.url = https://software.internet2.edu/grouper
# default version to install
grouper.version = 2.3.0
grouper.version = 2.4.0
# print out autorun keys in prompts so you can easily see how to configure the autorun
grouperInstaller.print.autorunKeys = true
# default to install or upgrade (default is install)
@@ -16,7 +16,8 @@ grouperInstaller.default.installOrUpgrade = install

grouperInstaller.autorun.installAllPatches = false
grouperInstaller.autorun.installPatchesUpToACertainPatchLevel = true
grouperInstaller.autorun.installPatchesUpToThesePatchLevels = grouper_v2_3_0_api_patch_109,grouper_v2_3_0_ui_patch_47,grouper_v2_3_0_ws_patch_13,grouper_v2_3_0_pspng_patch_24
grouperInstaller.autorun.installPatchesUpToThesePatchLevels = grouper_v2_4_0_api_patch_31,grouper_v2_4_0_ui_patch_14,grouper_v2_4_0_ws_patch_3,grouper_v2_4_0_pspng_patch_3


#### set this to true to try to use defaults for everything. Only things without default values will need to be set
grouperInstaller.autorun.useDefaultsAsMuchAsAvailable = true
@@ -30,10 +31,14 @@ grouperInstaller.autorun.addQuickstartData = f
grouperInstaller.autorun.installClient = f

grouperInstaller.autorun.installGrouperActiveMqMessaging = f
grouperInstaller.autorun.activeMqWhereInstalled = /opt/grouper/2.3.0/grouper.apiBinary-2.3.0/
grouperInstaller.autorun.activeMqWhereInstalled = /opt/grouper/2.4.0/grouper.apiBinary-2.4.0/

grouperInstaller.autorun.installGrouperAwsSqsMessaging = t
grouperInstaller.autorun.AwsSqsWhereInstalled = /opt/grouper/2.3.0/grouper.apiBinary-2.3.0/
grouperInstaller.autorun.AwsSqsWhereInstalled = /opt/grouper/2.4.0/grouper.apiBinary-2.4.0/

grouperInstaller.autorun.installGrouperRabbitMqMessaging = t
grouperInstaller.autorun.rabbitMqWhereInstalled = /opt/grouper/2.3.0/grouper.apiBinary-2.3.0/
grouperInstaller.autorun.rabbitMqWhereInstalled = /opt/grouper/2.4.0/grouper.apiBinary-2.4.0/

# disable installing pspng, for now
grouperInstaller.autorun.installPspng = t
grouperInstaller.autorun.installPsp = f
174 changes: 30 additions & 144 deletions container_files/ui/web.xml
@@ -1,203 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:j2ee="http://java.sun.com/xml/ns/j2ee" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.s
un.com/xml/ns/j2ee/web-app_2_4.xsd">
<!--DO NOT EDIT THIS FILE. IT WILL BE OVERWRITTEN. CHANGE YOUR FILE specified by the build.properties value [additional.web.xml]. The contents of that file are merged into ${grouper-ui}/w
ebapp/WEB-INF/web.core.xml-->
<!--In webapp-->
<!--Processing context-param-->
<!--Processing filter-->
<!--Inserting tag from merge file-->
<filter>
<web-app xmlns:j2ee="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<filter>
<filter-name>GrouperUi</filter-name>
<filter-class>edu.internet2.middleware.grouper.ui.GrouperUiFilter</filter-class>
</filter>
<!--Inserting tag from merge file-->
<filter>
<filter-name>Error Catcher</filter-name>
<filter-class>edu.internet2.middleware.grouper.ui.ErrorFilter</filter-class>
</filter>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter>
<filter-name>Login check</filter-name>
<filter-class>edu.internet2.middleware.grouper.ui.LoginCheckFilter</filter-class>
<init-param>
<param-name>failureUrl</param-name>
<param-value>/index.jsp</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>:/populateIndex.do:/callLogin.do:/error.do:/logout.do:/status:</param-value>
</init-param>
<init-param>
<param-name>grouperRole</param-name>
<param-value>*</param-value>
</init-param>
</filter>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter>
<filter-name>Caller page</filter-name>
<filter-class>edu.internet2.middleware.grouper.ui.CallerPageFilter</filter-class>
</filter>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter>
<filter>
<filter-name>CSRFGuard</filter-name>
<filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
</filter>
<!--Processing filter-mapping-->
<!--Inserting tag from merge file-->
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!--Inserting tag from merge file-->
<filter-mapping>
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<!--Inserting tag from merge file-->
<filter-mapping>
<filter-name>Error Catcher</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!--Inserting tag from merge file-->
<filter-mapping>
<filter-name>Error Catcher</filter-name>
<url-pattern>/gotoCallerPage</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>/grouperUi/app/*</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>/grouperUi/appHtml/*</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>/grouperExternal/app/*</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>/grouperExternal/appHtml/*</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>/grouperExternal/public/UiV2Public.index</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-mapping>
<filter-name>GrouperUi</filter-name>
<url-pattern>/grouperExternal/public/UiV2Public.postIndex</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-name>Caller page</filter-name>
<url-pattern>/gotoCallerPage</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-name>Login check</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<filter-mapping>
<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Processing listener-->
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<listener>
<listener-class>edu.internet2.middleware.grouper.ui.GrouperSessionAttributeListener</listener-class>
</listener>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<listener>
<listener>
<listener-class>edu.internet2.middleware.grouper.ui.GrouperSessionAttributeListener</listener-class>
</listener>
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardServletContextListener</listener-class>
</listener>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<listener>
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardHttpSessionListener</listener-class>
</listener>
<!--Processing servlet-->
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet>
<servlet>
<servlet-name>StatusServlet</servlet-name>
<display-name>Status Servlet</display-name>
<servlet-class>edu.internet2.middleware.grouper.j2ee.status.GrouperStatusServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet>
<!-- Map the filter to a Servlet or URL -->

<servlet>
<servlet-name>UiServlet</servlet-name>
<servlet-class>edu.internet2.middleware.grouper.j2ee.GrouperUiRestServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet>
<servlet-name>OwaspJavaScriptServlet</servlet-name>
<servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
<servlet>
<servlet-name>OwaspJavaScriptServlet</servlet-name>
<servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>
<!--Processing servlet-mapping-->
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet-mapping>
<servlet-mapping>
<servlet-name>StatusServlet</servlet-name>
<url-pattern>/status</url-pattern>
</servlet-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet-mapping>
<servlet-mapping>
<servlet-name>UiServlet</servlet-name>
<url-pattern>/grouperUi/app/*</url-pattern>
</servlet-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet-mapping>
<servlet-mapping>
<servlet-name>UiServlet</servlet-name>
<url-pattern>/grouperExternal/app/*</url-pattern>
</servlet-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet-mapping>
<servlet-mapping>
<servlet-name>UiServlet</servlet-name>
<url-pattern>/grouperExternal/public/UiV2Public.index</url-pattern>
</servlet-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet-mapping>
<servlet-mapping>
<servlet-name>UiServlet</servlet-name>
<url-pattern>/grouperExternal/public/UiV2Public.postIndex</url-pattern>
</servlet-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet-mapping>
<servlet-name>OwaspJavaScriptServlet</servlet-name>
<url-pattern>/grouperExternal/public/OwaspJavaScriptServlet</url-pattern>
</servlet-mapping>
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
<servlet-mapping>
<servlet-name>OwaspJavaScriptServlet</servlet-name>
<url-pattern>/grouperExternal/public/OwaspJavaScriptServlet</url-pattern>
</servlet-mapping>
<!--Processing mime-mapping-->
<!--Processing error-page-->
<!--Processing error-page-->
<!--Processing taglib-->
<!--Processing resource-env-ref-->
<!--Processing resource-ref-->
<!--Processing security-constraint-->
<!--Inserting tag from base file. Merge file was file:/opt/grouper.ui-2.3.0/temp/99.web.core-filters.xml-->
<!--Processing env-entry-->
<!--Processing ejb-ref-->
<!--Processing ejb-local-ref-->
</web-app>
@@ -4,17 +4,18 @@
# specify the ldap connection with user, pass, url
# the string after "ldap." is the ID of the connection, and it should not have
# spaces or other special chars in it. In this case is it "personLdap"

#note the URL should start with ldap: or ldaps: if it is SSL.
#It should contain the server and port (optional if not default), and baseDn,
#e.g. ldaps://ldapserver.school.edu:636/dc=school,dc=edu
ldap.demo.url = ldap://data:389/dc=example,dc=edu
ldap.demo.url = ldap://data:389/dc=internet2,dc=edu

#optional, if authenticated
ldap.demo.user = cn=admin,dc=internet2,dc=edu

#optional, if authenticated note the password can be stored encrypted in an external file
ldap.demo.pass = ${java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD')}
ldap.demo.pass.elConfig = ${java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD')}
#ldap.demo.pass = password

#optional, if you are using tls, set this to true. Generally you will not be using an SSL URL to use TLS...
ldap.demo.tls = false
26 changes: 16 additions & 10 deletions test-compose/configs-and-secrets/grouper/subject.properties
@@ -1,19 +1,25 @@
subject.sources.xml.location =
#subject.sources.xml.location =

subjectApi.source.ldap.param.ldapServerId.value = demo


subjectApi.source.ldap.id = ldap
subjectApi.source.ldap.name = EDU Ldap
subjectApi.source.ldap.types = person
subjectApi.source.ldap.adapterClass = edu.internet2.middleware.grouper.subj.GrouperJndiSourceAdapter
subjectApi.source.ldap.param.INITIAL_CONTEXT_FACTORY.value = com.sun.jndi.ldap.LdapCtxFactory
subjectApi.source.ldap.param.PROVIDER_URL.value = ldap://data:389
subjectApi.source.ldap.param.SECURITY_AUTHENTICATION.value = simple
subjectApi.source.ldap.param.SECURITY_PRINCIPAL.value = cn=admin,dc=internet2,dc=edu
subjectApi.source.ldap.param.SECURITY_CREDENTIALS.value.elConfig = ${java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD')}

## replaced with new LDAPTIVE lib
#subjectApi.source.ldap.param.INITIAL_CONTEXT_FACTORY.value = com.sun.jndi.ldap.LdapCtxFactory
#subjectApi.source.ldap.param.PROVIDER_URL.value = ldap://data:389
#subjectApi.source.ldap.param.SECURITY_AUTHENTICATION.value = simple
#subjectApi.source.ldap.param.SECURITY_PRINCIPAL.value = cn=admin,dc=internet2,dc=edu
#subjectApi.source.ldap.param.SECURITY_CREDENTIALS.value.elConfig = ${java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD')}
#subjectApi.source.ldap.param.VTLDAP_VALIDATOR.value = ConnectLdapValidator

subjectApi.source.ldap.param.SubjectID_AttributeType.value = uid
subjectApi.source.ldap.param.SubjectID_formatToLowerCase.value = false
subjectApi.source.ldap.param.Name_AttributeType.value = cn
subjectApi.source.ldap.param.Description_AttributeType.value = cn
subjectApi.source.ldap.param.VTLDAP_VALIDATOR.value = ConnectLdapValidator
subjectApi.source.ldap.param.subjectVirtualAttribute_0_searchAttribute0.value = ${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('uid'), "")},${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('cn'), "")},${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('exampleEduRegId'), "")}
subjectApi.source.ldap.param.sortAttribute0.value = cn
subjectApi.source.ldap.param.searchAttribute0.value = searchAttribute0
@@ -55,21 +61,21 @@ subjectApi.source.ldap.param.searchAttribute0.value = searchAttribute0
# Each subject has one and only on ID. Returns one result when searching for one ID.
subjectApi.source.ldap.search.searchSubject.param.filter.value = (&(uid=%TERM%)(objectclass=person))
subjectApi.source.ldap.search.searchSubject.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.searchSubject.param.base.value = ou=people,dc=internet2,dc=edu
subjectApi.source.ldap.search.searchSubject.param.base.value = ou=people

#searchSubjectByIdentifier: find a subject by identifier. Identifier is anything that uniquely
# identifies the user, e.g. jsmith or jsmith@institution.edu.
# Subjects can have multiple identifiers. Note: it is nice to have if identifiers are unique
# even across sources. Returns one result when searching for one identifier.
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.filter.value = (&(|(uid=%TERM%)(employeeNumber=%TERM%))(objectclass=person))
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.base.value = ou=people,dc=internet2,dc=edu
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.base.value = ou=people

# search: find subjects by free form search. Returns multiple results.

subjectApi.source.ldap.search.search.param.filter.value = (&(|(|(uid=%TERM%)(cn=*%TERM%*))(uid=%TERM%*))(objectclass=person))
subjectApi.source.ldap.search.search.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.search.param.base.value = ou=people,dc=internet2,dc=edu
subjectApi.source.ldap.search.search.param.base.value = ou=people

subjectApi.source.ldap.attributes = givenName, sn, uid, mail, employeeNumber
subjectApi.source.ldap.internalAttributes = searchAttribute0
64 changes: 64 additions & 0 deletions test-compose/data/container_files/conf/grouper-loader.properties
@@ -0,0 +1,64 @@
#################################
## LDAP connections
#################################
# specify the ldap connection with user, pass, url
# the string after "ldap." is the ID of the connection, and it should not have
# spaces or other special chars in it. In this case is it "personLdap"

#note the URL should start with ldap: or ldaps: if it is SSL.
#It should contain the server and port (optional if not default), and baseDn,
#e.g. ldaps://ldapserver.school.edu:636/dc=school,dc=edu
ldap.demo.url = ldap://localhost:389/dc=internet2,dc=edu

#optional, if authenticated
ldap.demo.user = cn=admin,dc=internet2,dc=edu
#ldap.demo.user = cn=admin

#optional, if authenticated note the password can be stored encrypted in an external file
#ldap.demo.pass = ${java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD')}
ldap.demo.pass = password

#optional, if you are using tls, set this to true. Generally you will not be using an SSL URL to use TLS...
ldap.demo.tls = false

#optional, if using sasl
#ldap.personLdap.saslAuthorizationId =
#ldap.personLdap.saslRealm =

#optional (note, time limit is for search operations, timeout is for connection timeouts),
#most of these default to vt-ldap defaults. times are in millis
#validateOnCheckout defaults to true if all other validate methods are false
#ldap.personLdap.batchSize =
#ldap.personLdap.countLimit =
#ldap.personLdap.timeLimit =
#ldap.personLdap.timeout =
#ldap.personLdap.minPoolSize =
#ldap.personLdap.maxPoolSize =
#ldap.personLdap.validateOnCheckIn =
#ldap.personLdap.validateOnCheckOut =
#ldap.personLdap.validatePeriodically =
#ldap.personLdap.validateTimerPeriod =
#ldap.personLdap.pruneTimerPeriod =
#if connections expire after a certain amount of time, this is it, in millis, defaults to 300000 (5 minutes)
#ldap.personLdap.expirationTime =

#make the paths fully qualified and not relative to the loader group.
loader.ldap.requireTopStemAsStemFromConfigGroup=false

#####################################
## Messaging integration with change log
#####################################
changeLog.consumer.rabbitMqMessagingSample.quartzCron = 0 * * * * ?

# note, change "messagingSample" in key to be the name of the consumer. e.g. changeLog.consumer.someNameAnyName.class
changeLog.consumer.rabbitMqMessagingSample.class = edu.internet2.middleware.grouper.changeLog.esb.consumer.EsbConsumer

changeLog.consumer.rabbitMqMessagingSample.publisher.class = edu.internet2.middleware.grouper.changeLog.esb.consumer.EsbMessagingPublisher
changeLog.consumer.rabbitMqMessagingSample.publisher.messagingSystemName = rabbitmq
# note, routingKey property is valid only for rabbitmq. For other messaging systems, it is ignored.
changeLog.consumer.rabbitMqMessagingSample.publisher.routingKey =
## queue or topic
changeLog.consumer.rabbitMqMessagingSample.publisher.messageQueueType = queue
changeLog.consumer.rabbitMqMessagingSample.publisher.queueOrTopicName = sampleQueue
## this is optional if not using "id" for subjectId, need to be a subject attribute in the sources.xml
#changeLog.consumer.rabbitMqMessagingSample.publisher.addSubjectAttributes = email
26 changes: 16 additions & 10 deletions test-compose/data/container_files/conf/subject.properties
@@ -1,19 +1,25 @@
subject.sources.xml.location =
#subject.sources.xml.location =

subjectApi.source.ldap.param.ldapServerId.value = demo


subjectApi.source.ldap.id = ldap
subjectApi.source.ldap.name = EDU Ldap
subjectApi.source.ldap.types = person
subjectApi.source.ldap.adapterClass = edu.internet2.middleware.grouper.subj.GrouperJndiSourceAdapter
subjectApi.source.ldap.param.INITIAL_CONTEXT_FACTORY.value = com.sun.jndi.ldap.LdapCtxFactory
subjectApi.source.ldap.param.PROVIDER_URL.value = ldap://localhost:389
subjectApi.source.ldap.param.SECURITY_AUTHENTICATION.value = simple
subjectApi.source.ldap.param.SECURITY_PRINCIPAL.value = cn=admin,dc=internet2,dc=edu
subjectApi.source.ldap.param.SECURITY_CREDENTIALS.value = password

## replaced with new LDAPTIVE lib
#subjectApi.source.ldap.param.INITIAL_CONTEXT_FACTORY.value = com.sun.jndi.ldap.LdapCtxFactory
#subjectApi.source.ldap.param.PROVIDER_URL.value = ldap://data:389
#subjectApi.source.ldap.param.SECURITY_AUTHENTICATION.value = simple
#subjectApi.source.ldap.param.SECURITY_PRINCIPAL.value = cn=admin,dc=internet2,dc=edu
#subjectApi.source.ldap.param.SECURITY_CREDENTIALS.value.elConfig = ${java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE') != null ? org.apache.commons.io.FileUtils.readFileToString(java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD_FILE'), "utf-8") : java.lang.System.getenv().get('SUBJECT_SOURCE_LDAP_PASSWORD')}
#subjectApi.source.ldap.param.VTLDAP_VALIDATOR.value = ConnectLdapValidator

subjectApi.source.ldap.param.SubjectID_AttributeType.value = uid
subjectApi.source.ldap.param.SubjectID_formatToLowerCase.value = false
subjectApi.source.ldap.param.Name_AttributeType.value = cn
subjectApi.source.ldap.param.Description_AttributeType.value = cn
subjectApi.source.ldap.param.VTLDAP_VALIDATOR.value = ConnectLdapValidator
subjectApi.source.ldap.param.subjectVirtualAttribute_0_searchAttribute0.value = ${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('uid'), "")},${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('cn'), "")},${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('exampleEduRegId'), "")}
subjectApi.source.ldap.param.sortAttribute0.value = cn
subjectApi.source.ldap.param.searchAttribute0.value = searchAttribute0
@@ -55,21 +61,21 @@ subjectApi.source.ldap.param.searchAttribute0.value = searchAttribute0
# Each subject has one and only on ID. Returns one result when searching for one ID.
subjectApi.source.ldap.search.searchSubject.param.filter.value = (&(uid=%TERM%)(objectclass=person))
subjectApi.source.ldap.search.searchSubject.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.searchSubject.param.base.value = ou=people,dc=internet2,dc=edu
subjectApi.source.ldap.search.searchSubject.param.base.value = ou=people

#searchSubjectByIdentifier: find a subject by identifier. Identifier is anything that uniquely
# identifies the user, e.g. jsmith or jsmith@institution.edu.
# Subjects can have multiple identifiers. Note: it is nice to have if identifiers are unique
# even across sources. Returns one result when searching for one identifier.
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.filter.value = (&(|(uid=%TERM%)(employeeNumber=%TERM%))(objectclass=person))
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.base.value = ou=people,dc=internet2,dc=edu
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.base.value = ou=people

# search: find subjects by free form search. Returns multiple results.

subjectApi.source.ldap.search.search.param.filter.value = (&(|(|(uid=%TERM%)(cn=*%TERM%*))(uid=%TERM%*))(objectclass=person))
subjectApi.source.ldap.search.search.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.search.param.base.value = ou=people,dc=internet2,dc=edu
subjectApi.source.ldap.search.search.param.base.value = ou=people

subjectApi.source.ldap.attributes = givenName, sn, uid, mail, employeeNumber
subjectApi.source.ldap.internalAttributes = searchAttribute0
7 changes: 7 additions & 0 deletions test-compose/data/container_files/seed-data/bootstrap.gsh
@@ -1,3 +1,10 @@
gs = GrouperSession.startRootSession()

addStem("","app", "app")
addStem("","basis", "basis")
addStem("","bundle", "bundle")
addStem("","org", "org")
addStem("","ref", "ref")
addStem("","test", "test")

addMember("etc:sysadmingroup","banderson");
15 changes: 15 additions & 0 deletions test-compose/docker-compose.yml
@@ -198,7 +198,22 @@ services:
ports:
- "389:389"
- "3306:3306"
secrets:
- database_password.txt
- rabbitmq_password.txt
- source: grouper.hibernate.properties
target: grouper_grouper.hibernate.properties
- source: grouper-loader.properties
target: grouper_grouper-loader.properties
- source: subject.properties
target: grouper_subject.properties
volumes:
- type: bind
source: ./configs-and-secrets/grouper/grouper.properties
target: /opt/grouper/conf/grouper.properties
- type: bind
source: ./configs-and-secrets/grouper/grouper.client.properties
target: /opt/grouper/conf/grouper.client.properties
- grouper_mysql:/var/lib/mysql
- grouper_ldap:/var/lib/dirsrv

72 changes: 72 additions & 0 deletions tests/clairscan.sh
@@ -0,0 +1,72 @@
#!/bin/bash

startsecs=$(date +'%s')
starttime=$(date +%H:%M:%S)

echo 'starting:' ${starttime}

#ensure clair-scanner
if [ ! -s ./clair-scanner ]; then
echo 'downloading curl-scanner...'
curl -s -L -o ./clair-scanner https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
chmod 755 clair-scanner
else
echo 'using existing clair-scanner...'
fi

#ensure DB container
echo 'ensuring a fresh clair-db container...'
docker ps | grep clair-db &>/dev/null
if [ $? == "0" ]; then
echo 'removing existing clair-db container...'
docker kill db &>/dev/null
docker rm db &>/dev/null
docker run -p 5432:5432 -d --name db arminc/clair-db:latest &>/dev/null
else
docker run -p 5432:5432 -d --name db arminc/clair-db:latest &>/dev/null
fi
sleep 30

#ensure clair-scan container
echo 'ensuring a fresh clair-scan container...'
docker ps | grep clair-local-scan &>/dev/null
if [ $? == "0" ]; then
echo 'removing existing clair-scan container...'
docker kill clair &>/dev/null
docker rm clair &>/dev/null
docker run -p 6060:6060 --link db:postgres -d --name clair arminc/clair-local-scan:v2.0.5 &>/dev/null
else
docker run -p 6060:6060 --link db:postgres -d --name clair arminc/clair-local-scan:v2.0.5 &>/dev/null
fi
sleep 30

#get ip where clair-scanner will listen
clairip=$(/sbin/ifconfig docker0 | grep 'inet ' | sed 's/^[[:space:]]*//g' | cut -f 2 -d ' ' | sed 's/^[[:space:]]*//g')
echo 'sending ip addr' ${clairip} 'to clair-scan server...'

#run scan
echo 'running scan...'
./clair-scanner --ip ${clairip} $1
retcode=$?

#eval results
if [ $retcode == '0' ]; then
echo 'scan found nothing.'
else
echo 'scan found issues.'
fi

#cleanup
echo 'removing temporary containers...'
docker kill clair &>/dev/null
docker rm clair &>/dev/null
docker kill db &>/dev/null
docker rm db &>/dev/null

endsecs=$(date +'%s')
endtime=$(date +%H:%M:%S)
echo 'finished:' $endtime ' ('$((endsecs - startsecs)) 'seconds)'
echo ""

#pass along return code from scan
exit $retcode
16 changes: 16 additions & 0 deletions tests/main.bats
@@ -0,0 +1,16 @@
#!/usr/bin/env bats

load ../common

@test "010 Image is present and healthy" {
docker image inspect ${maintainer}/${imagename}
}

@test "030 Test Compose the environment" {
cd test-compose && ./compose.sh && docker-compose down
}


@test "070 There are no known security vulnerabilities" {
./tests/clairscan.sh ${maintainer}/${imagename}:latest
}

0 comments on commit f29ec9e

Please sign in to comment.