Rework project's Docker test setup

- use Docker Compose instead of fabric8io
- don't use local paths to support running with remote Docker contexts
- use latest Keycloak Docker image and make sure test realm works out-of-the-box
- add flag to avoid failing on missing properties during JSON deserialisation
  (newer Keycloak versions offer more properties in IDM API response payloads)
This commit is contained in:
AFaust 2025-02-14 17:28:12 +01:00 committed by Axel Faust
parent 6f7910aa93
commit d6a6b3c2bd
32 changed files with 769 additions and 2034 deletions

367
docker-test/pom.xml Normal file
View File

@ -0,0 +1,367 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2019 - 2021 Acosix GmbH
Licensed 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.acosix.alfresco.keycloak</groupId>
<artifactId>de.acosix.alfresco.keycloak.parent</artifactId>
<version>1.2.0-rc1</version>
</parent>
<artifactId>de.acosix.alfresco.keycloak.docker.test</artifactId>
<name>Acosix Alfresco Keycloak - Docker Test Module</name>
<properties>
<maven.install.skip>true</maven.install.skip>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.repo</artifactId>
<version>${acosix.utility.version}</version>
<type>amp</type>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.share</artifactId>
<version>${acosix.utility.version}</version>
<type>amp</type>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>de.acosix.alfresco.keycloak.repo</artifactId>
<version>${project.version}</version>
<type>amp</type>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>de.acosix.alfresco.keycloak.share</artifactId>
<version>${project.version}</version>
<type>amp</type>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-repo</artifactId>
<classifier>amp</classifier>
<version>${ootbee.support-tools.version}</version>
<type>amp</type>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-share</artifactId>
<classifier>amp</classifier>
<version>${ootbee.support-tools.version}</version>
<type>amp</type>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.repo</artifactId>
<type>amp</type>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.share</artifactId>
<type>amp</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>de.acosix.alfresco.keycloak.repo</artifactId>
<type>amp</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>de.acosix.alfresco.keycloak.share</artifactId>
<type>amp</type>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-repo</artifactId>
<classifier>amp</classifier>
<type>amp</type>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-share</artifactId>
<classifier>amp</classifier>
<type>amp</type>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.directory}/classes</targetPath>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-toolchains-plugin</artifactId>
<configuration>
<paths>
<id>docker</id>
</paths>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-repo-dependencies</id>
<phase>process-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/repository</outputDirectory>
<includeTypes>amp</includeTypes>
<includeArtifactIds>activemq-broker,support-tools-repo,de.acosix.alfresco.utility.repo,de.acosix.alfresco.keycloak.repo</includeArtifactIds>
</configuration>
</execution>
<execution>
<id>copy-share-dependencies</id>
<phase>process-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/share</outputDirectory>
<includeTypes>amp</includeTypes>
<includeArtifactIds>support-tools-share,de.acosix.alfresco.utility.share,de.acosix.alfresco.keycloak.share</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<toolchain>docker</toolchain>
<executable>docker</executable>
</configuration>
<executions>
<execution>
<id>buildDocker</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<arguments>
<argument>compose</argument>
<argument>-f</argument>
<argument>${project.build.directory}/classes/docker-compose.yaml</argument>
<argument>build</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>startDocker</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<arguments>
<argument>compose</argument>
<argument>-f</argument>
<argument>${project.build.directory}/classes/docker-compose.yaml</argument>
<argument>up</argument>
<argument>-d</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-toolchains-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>clean-if-compose-present</id>
<activation>
<file>
<exists>target/classes/docker-compose.yaml</exists>
</file>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<toolchain>docker</toolchain>
<executable>docker</executable>
</configuration>
<executions>
<execution>
<id>cleanDocker</id>
<phase>pre-clean</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<arguments>
<argument>compose</argument>
<argument>-f</argument>
<argument>${project.build.directory}/classes/docker-compose.yaml</argument>
<argument>down</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id>purge</id>
<activation>
<file>
<exists>target/classes/docker-compose.yaml</exists>
</file>
<property>
<name>purge</name>
<value>true</value>
</property>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<toolchain>docker</toolchain>
<executable>docker</executable>
</configuration>
<executions>
<execution>
<id>purgeDocker</id>
<phase>pre-clean</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<arguments>
<argument>compose</argument>
<argument>-f</argument>
<argument>${project.build.directory}/classes/docker-compose.yaml</argument>
<argument>down</argument>
<argument>-v</argument>
<argument>--rmi</argument>
<argument>local</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,131 @@
version: '3.8'
services:
kc-pg:
image: postgres:${postgres.docker.version}
hostname: kc-pg
restart: unless-stopped
command: postgres -c max_connections=50
volumes:
- kc_psql:/srv/postgresql
environment:
PGDATA: /srv/postgresql/data
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: keycloak
alf-pg:
image: postgres:${postgres.docker.version}
hostname: alf-pg
restart: unless-stopped
command: postgres -c max_connections=300
volumes:
- alf_psql:/srv/postgresql
environment:
PGDATA: /srv/postgresql/data
POSTGRES_DB: alfresco
POSTGRES_USER: alfresco
POSTGRES_PASSWORD: alfresco
keycloak:
build:
context: ./keycloak
dockerfile: Dockerfile
hostname: keycloak
restart: unless-stopped
depends_on:
- kc-pg
command: start-dev --import-realm
ports:
- ${keycloak.docker.port}:8080
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_URL: "jdbc:postgresql://kc-pg:5432/keycloak"
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: "keycloak"
KC_DB_POOL_INITIAL_SIZE: 5
KC_DB_POOL_MAX_SIZE: 50
KC_HOSTNAME: http://localhost:${keycloak.docker.port}
KC_HOSTNAME_BACKCHANNEL_DYNAMIC: true
# in newer Keycloak versions, token-exchange does not work without admin-fine-grained-authz
# (even with properly set up resources, scopes, permissions, policies in realm-management)
KC_FEATURES: "token-exchange,admin-fine-grained-authz"
KC_FEATURES_DISABLED: "ciba,impersonation,kerberos,par,step-up-authentication,web-authn"
repository:
build:
context: ./repository
dockerfile: Dockerfile
hostname: repository
restart: unless-stopped
depends_on:
- alf-pg
volumes:
- contentstore:${alfresco.repo.docker.data.path}
- repo_logs:${alfresco.repo.docker.tomcat.path}/logs
ports:
- ${alfresco.repo.docker.port}:8080
- ${alfresco.repo.docker.debugPort}:8888
environment:
JAVA_OPTS: >-
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8888
-Xms2g -Xmx2g -XX:+UseG1GC -XX:+ParallelRefProcEnabled
-XX:+UseStringDeduplication -XX:+ScavengeBeforeFullGC
-XX:+DisableExplicitGC -XX:+AlwaysPreTouch
-Dencryption.keystore.type=JCEKS
-Dencryption.cipherAlgorithm=DESede/CBC/PKCS5Padding
-Dencryption.keyAlgorithm=DESede
-Dencryption.keystore.location=${alfresco.repo.docker.tomcat.path}/shared/classes/alfresco/extension/keystore/keystore
-Dmetadata-keystore.password=mp6yc0UD9e
-Dmetadata-keystore.aliases=metadata
-Dmetadata-keystore.metadata.password=oKIWzVdEdA
-Dmetadata-keystore.metadata.algorithm=DESede
-Dsolr.secureComms=secret
-Dsolr.sharedSecret=secret
share:
build:
context: ./share
dockerfile: Dockerfile
environment:
REPO_HOST: repository
REPO_PORT: 8080
JAVA_OPTS: >-
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8888
-Xms500m -Xmx500m
-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+UseStringDeduplication
-XX:+ScavengeBeforeFullGC -XX:+DisableExplicitGC -XX:+AlwaysPreTouch
ports:
- ${alfresco.share.docker.port}:8080
- ${alfresco.share.docker.debugPort}:8888
solr6:
image: alfresco/alfresco-search-services:${alfresco.solr6.docker.version}
environment:
SOLR_ALFRESCO_HOST: repository
SOLR_ALFRESCO_PORT: 8080
SOLR_SOLR_HOST: solr6
SOLR_SOLR_PORT: 8983
SOLR_CREATE_ALFRESCO_DEFAULTS: alfresco
ALFRESCO_SECURE_COMMS: secret
JAVA_TOOL_OPTIONS: -Dalfresco.secureComms.secret=secret
SOLR_JAVA_MEM: -Xms2g -Xmx2g
activemq:
image: alfresco/alfresco-activemq:${alfresco.activemq.docker.version}
transform-core-aio:
image: alfresco/alfresco-transform-core-aio:${alfresco.aio.docker.version}
environment:
JAVA_OPTS: " -Xms256m -Xmx1536m"
ACTIVEMQ_URL: nio://activemq:61616
volumes:
kc_psql:
alf_psql:
contentstore:
repo_logs:
share_logs:

View File

@ -0,0 +1,5 @@
FROM ${keycloak.docker.image}:${keycloak.docker.version}
COPY test-realm.json /opt/keycloak/data/import/
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

View File

@ -495,62 +495,6 @@
}
]
},
{
"name": "alfresco",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "false",
"display.on.consent.screen": "false"
},
"protocolMappers": [
{
"name": "Alfresco Audience",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"consentRequired": false,
"config": {
"included.client.audience": "alfresco",
"id.token.claim": "false",
"access.token.claim": "true"
}
}
]
},
{
"name": "alfresco-share",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "false",
"display.on.consent.screen": "false"
},
"protocolMappers": [
{
"name": "Alfresco Share Audience",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"consentRequired": false,
"config": {
"included.client.audience": "alfresco-share",
"id.token.claim": "false",
"access.token.claim": "true"
}
},
{
"name": "username",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "username",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "preferred_username",
"jsonType.label": "String"
}
}
]
},
{
"name": "web-origins",
"description": "OpenID Connect scope for add allowed web origins to the access token",
@ -588,12 +532,6 @@
"roles": [
"offline_access"
]
},
{
"clientScope": "alfresco",
"roles": [
"user"
]
}
],
"clientScopeMappings": {
@ -621,14 +559,6 @@
"manage-account"
]
}
],
"alfresco": [
{
"clientScope": "alfresco",
"roles": [
"admin"
]
}
]
},
"clients": [
@ -636,8 +566,8 @@
"id": "alfresco",
"clientId": "alfresco",
"name": "Alfresco Repository",
"rootUrl": "http://localhost:${docker.tests.repositoryPort}/alfresco",
"adminUrl": "http://localhost:${docker.tests.repositoryPort}/alfresco/keycloak",
"rootUrl": "http://localhost:${alfresco.repo.docker.port}/alfresco",
"adminUrl": "http://localhost:${alfresco.repo.docker.port}/alfresco/keycloak",
"baseUrl": "/",
"redirectUris": [
"/*"
@ -652,26 +582,51 @@
"serviceAccountsEnabled": true,
"publicClient": false,
"protocol": "openid-connect",
"attributes": {
"exclude.issuer.from.auth.response": "true"
},
"fullScopeAllowed": false,
"defaultClientScopes": [
"profile",
"email",
"address",
"phone",
"roles",
"alfresco"
"roles"
],
"optionalClientScopes": [
"alfresco-authority-sync",
"alfresco-role-service"
],
"protocolMappers": [
{
"name": "Alfresco Audience",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"consentRequired": false,
"config": {
"included.client.audience": "alfresco",
"id.token.claim": "false",
"access.token.claim": "true"
}
},
{
"name": "sub",
"protocol": "openid-connect",
"protocolMapper": "oidc-sub-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"access.token.claim": "true"
}
}
]
},
{
"id": "alfresco-share",
"clientId": "alfresco-share",
"name": "Alfresco Share",
"rootUrl": "http://localhost:${docker.tests.sharePort}/share",
"adminUrl": "http://localhost:${docker.tests.sharePort}/share/keycloak",
"rootUrl": "http://localhost:${alfresco.share.docker.port}/share",
"adminUrl": "http://localhost:${alfresco.share.docker.port}/share/keycloak",
"baseUrl": "/",
"redirectUris": [
"/*"
@ -684,11 +639,50 @@
"secret": "a5b3e8bc-39cc-4ddd-8c8f-1c34e7a35975",
"publicClient": false,
"protocol": "openid-connect",
"attributes": {
"exclude.issuer.from.auth.response": "true"
},
"alwaysDisplayInConsole": true,
"fullScopeAllowed": false,
"defaultClientScopes": [
"roles",
"alfresco-share"
"roles"
],
"protocolMappers": [
{
"name": "Alfresco Share Audience",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"consentRequired": false,
"config": {
"included.client.audience": "alfresco-share",
"id.token.claim": "false",
"access.token.claim": "true"
}
},
{
"name": "sub",
"protocol": "openid-connect",
"protocolMapper": "oidc-sub-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"access.token.claim": "true"
}
},
{
"name": "username",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "username",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "preferred_username",
"jsonType.label": "String"
}
}
]
},
{

View File

@ -0,0 +1,36 @@
FROM ${alfresco.repo.docker.image}:${alfresco.repo.docker.version}
${alfresco.repo.docker.build.preRun}
COPY support-tools-repo*.amp ${alfresco.repo.docker.amp.path}/
COPY de.acosix.alfresco.utility.repo*.amp ${alfresco.repo.docker.amp.path}/
COPY de.acosix.alfresco.keycloak.repo*.amp ${alfresco.repo.docker.amp.path}/
RUN java -jar ${alfresco.repo.docker.mmt.path}/alfresco-mmt*.jar install \
${alfresco.repo.docker.amp.path}/support-tools-repo*.amp \
${alfresco.repo.docker.tomcat.path}/webapps/alfresco -nobackup
RUN java -jar ${alfresco.repo.docker.mmt.path}/alfresco-mmt*.jar install \
${alfresco.repo.docker.amp.path}/de.acosix.alfresco.utility.repo*.amp \
${alfresco.repo.docker.tomcat.path}/webapps/alfresco -nobackup
RUN java -jar ${alfresco.repo.docker.mmt.path}/alfresco-mmt*.jar install \
${alfresco.repo.docker.amp.path}/de.acosix.alfresco.keycloak.repo*.amp \
${alfresco.repo.docker.tomcat.path}/webapps/alfresco -nobackup
COPY alfresco.xml ${alfresco.repo.docker.tomcat.path}/conf/Catalina/localhost/
COPY alfresco-global.addition.properties ${alfresco.repo.docker.tomcat.path}/shared/classes/alfresco/
COPY dev-log4j.properties dev-log4j2.properties ${alfresco.repo.docker.tomcat.path}/shared/classes/alfresco/extension/
# merge additions to alfresco-global.properties
RUN echo "" >> ${alfresco.repo.docker.tomcat.path}/shared/classes/alfresco-global.properties \
&& cat ${alfresco.repo.docker.tomcat.path}/shared/classes/alfresco/alfresco-global.addition.properties >> ${alfresco.repo.docker.tomcat.path}/shared/classes/alfresco-global.properties \
&& sed -i 's/<secure>true<\/secure>/<secure>false<\/secure>/' ${alfresco.repo.docker.tomcat.path}/conf/web.xml
RUN chown -R ${alfresco.repo.docker.chown.mask} \
${alfresco.repo.docker.tomcat.path}/webapps/alfresco \
${alfresco.repo.docker.tomcat.path}/shared/classes/*
${alfresco.repo.docker.build.postRun}

View File

@ -0,0 +1,33 @@
db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://alf-pg:5432/alfresco
db.username=alfresco
db.password=alfresco
solr.host=solr6
solr.port=8983
csrf.filter.enabled=false
messaging.broker.url=failover:(nio://activemq:61616)?timeout=3000&jms.useCompression=true
transform.service.enabled=false
local.transform.service.enabled=true
localTransform.core-aio.url=http://transform-core-aio:8090/
authentication.chain=alfrescoNtlm1:alfrescoNtlm,keycloak1:keycloak
keycloak.adapter.auth-server-url=http://localhost:${keycloak.docker.port}
keycloak.adapter.realm=test
keycloak.adapter.resource=alfresco
keycloak.adapter.credentials.provider=secret
keycloak.adapter.credentials.secret=6f70a28f-98cd-41ca-8f2f-368a8797d708
# localhost in auth-server-url won't work for direct access in a Docker deployment
keycloak.adapter.proxy-url=http://keycloak:8080
keycloak.roles.requiredClientScopes=alfresco-role-service
keycloak.synchronization.userFilter.containedInGroup.property.groupPaths=/Test A
keycloak.synchronization.groupFilter.containedInGroup.property.groupPaths=/Test A
keycloak.synchronization.requiredClientScopes=alfresco-authority-sync

View File

@ -0,0 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<Context crossContext="true" useHttpOnly="true">
<Resources cacheMaxSize="51200" cacheObjectMaxSize="1024" />
</Context>

View File

@ -0,0 +1,22 @@
FROM ${alfresco.share.docker.image}:${alfresco.share.docker.version}
COPY support-tools-share*.amp ${alfresco.share.docker.amp.path}/
COPY de.acosix.alfresco.utility.share*.amp ${alfresco.share.docker.amp.path}/
COPY de.acosix.alfresco.keycloak.share*.amp ${alfresco.share.docker.amp.path}/
RUN java -jar ${alfresco.share.docker.mmt.path}/alfresco-mmt*.jar install \
${alfresco.share.docker.amp.path}/support-tools-share*.amp \
${alfresco.share.docker.tomcat.path}/webapps/share -nobackup
RUN java -jar ${alfresco.share.docker.mmt.path}/alfresco-mmt*.jar install \
${alfresco.share.docker.amp.path}/de.acosix.alfresco.utility.share*.amp \
${alfresco.share.docker.tomcat.path}/webapps/share -nobackup
RUN java -jar ${alfresco.share.docker.mmt.path}/alfresco-mmt*.jar install \
${alfresco.share.docker.amp.path}/de.acosix.alfresco.keycloak.share*.amp \
${alfresco.share.docker.tomcat.path}/webapps/share -nobackup
RUN sed -i 's/<secure>true<\/secure>/<secure>false<\/secure>/' ${alfresco.share.docker.tomcat.path}/conf/web.xml
COPY share.xml ${alfresco.repo.docker.tomcat.path}/conf/Catalina/localhost/share.xml
COPY share-config-custom.xml ${alfresco.repo.docker.tomcat.path}/shared/classes/alfresco/web-extension/share-config-custom.xml

View File

@ -76,7 +76,7 @@
</keycloak-auth-config>
<keycloak-adapter-config>
<forced-route-url>http://keycloak:8080</forced-route-url>
<auth-server-url>http://localhost:${docker.tests.keycloakPort}/auth</auth-server-url>
<auth-server-url>http://localhost:${keycloak.docker.port}</auth-server-url>
<realm>test</realm>
<resource>alfresco-share</resource>
<ssl-required>none</ssl-required>

View File

@ -0,0 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<Context crossContext="true" useHttpOnly="true">
<Resources cacheMaxSize="51200" cacheObjectMaxSize="1024" />
</Context>

121
pom.xml
View File

@ -80,8 +80,8 @@
<maven.compiler.version>3.13.0</maven.compiler.version>
<maven.shade.version>3.6.0</maven.shade.version>
<!-- last available Java adapter library version -->
<keycloak.version>22.0.3</keycloak.version>
<resteasy.version>3.15.1.Final</resteasy.version>
<!-- lowest common denominator of Repository / Share in 6.0 -->
<apache.httpclient.version>4.5.13</apache.httpclient.version>
<apache.httpcore.version>4.4.16</apache.httpcore.version>
@ -89,28 +89,38 @@
<surf.version>9.0</surf.version>
<acosix.utility.version>1.4.3</acosix.utility.version>
<ootbee.support-tools.version>1.1.0.0</ootbee.support-tools.version>
<ootbee.support-tools.version>1.2.2.0</ootbee.support-tools.version>
<docker.tests.repositoryImageBuilder.preRun></docker.tests.repositoryImageBuilder.preRun>
<docker.tests.repositoryImageBuilder.postRun></docker.tests.repositoryImageBuilder.postRun>
<keycloak.docker.image>keycloak/keycloak</keycloak.docker.image>
<keycloak.docker.version>26.0</keycloak.docker.version>
<keycloak.docker.port>8081</keycloak.docker.port>
<!-- for when we run tests with ACS 7.0+ -->
<activemq.version>5.16.1</activemq.version>
<postgres.docker.version>16</postgres.docker.version>
<!-- Uncomment to test with latest release(s) -->
<!--
<docker.tests.repositoryBaseImage>alfresco/alfresco-content-repository-community:7.0.0</docker.tests.repositoryBaseImage>
<docker.tests.shareBaseImage>alfresco/alfresco-share:7.0.0</docker.tests.shareBaseImage>
<docker.tests.searchBaseImage>alfresco/alfresco-search-services:2.0.0.1</docker.tests.searchBaseImage>
<alfresco.activemq.docker.version>5.18-jre17-rockylinux8</alfresco.activemq.docker.version>
<docker.tests.repositoryVersionSpecificJavaOpts><![CDATA[-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:${docker.tests.repositoryDebugPort} -Dencryption.keystore.type=JCEKS -Dencryption.cipherAlgorithm=DESede/CBC/PKCS5Padding -Dencryption.keyAlgorithm=DESede -Dencryption.keystore.location=/usr/local/tomcat/shared/classes/alfresco/extension/keystore/keystore -Dmetadata-keystore.password=mp6yc0UD9e -Dmetadata-keystore.aliases=metadata -Dmetadata-keystore.metadata.password=oKIWzVdEdA -Dmetadata-keystore.metadata.algorithm=DESede -Dmessaging.broker.url=vm://localhost?broker.persistent=false]]></docker.tests.repositoryVersionSpecificJavaOpts>
<docker.tests.shareVersionSpecificJavaOpts>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:${docker.tests.shareDebugPort}</docker.tests.shareVersionSpecificJavaOpts>
<alfresco.repo.docker.image>alfresco/alfresco-content-repository-community</alfresco.repo.docker.image>
<alfresco.repo.docker.version>23.2.0</alfresco.repo.docker.version>
<alfresco.repo.docker.tomcat.path>/usr/local/tomcat</alfresco.repo.docker.tomcat.path>
<alfresco.repo.docker.amp.path>/usr/local/tomcat/amps</alfresco.repo.docker.amp.path>
<alfresco.repo.docker.mmt.path>/usr/local/tomcat/alfresco-mmt</alfresco.repo.docker.mmt.path>
<alfresco.repo.docker.data.path>/usr/local/tomcat/alf_data</alfresco.repo.docker.data.path>
<alfresco.repo.docker.port>8080</alfresco.repo.docker.port>
<alfresco.repo.docker.debugPort>8888</alfresco.repo.docker.debugPort>
<alfresco.repo.docker.build.preRun>USER root</alfresco.repo.docker.build.preRun>
<alfresco.repo.docker.build.postRun>USER alfresco</alfresco.repo.docker.build.postRun>
<alfresco.repo.docker.chown.mask>alfresco:Alfresco</alfresco.repo.docker.chown.mask>
<docker.tests.repositoryImageBuilder.preRun>USER root</docker.tests.repositoryImageBuilder.preRun>
<docker.tests.repositoryImageBuilder.postRun>USER alfresco</docker.tests.repositoryImageBuilder.postRun>
<acosix.utility.version>1.3.0</acosix.utility.version>
-->
<alfresco.share.docker.image>alfresco/alfresco-share</alfresco.share.docker.image>
<alfresco.share.docker.version>23.2.0</alfresco.share.docker.version>
<alfresco.share.docker.tomcat.path>/usr/local/tomcat</alfresco.share.docker.tomcat.path>
<alfresco.share.docker.amp.path>/usr/local/tomcat/share_amps</alfresco.share.docker.amp.path>
<alfresco.share.docker.mmt.path>/usr/local/tomcat/alfresco-mmt</alfresco.share.docker.mmt.path>
<alfresco.share.docker.port>8180</alfresco.share.docker.port>
<alfresco.share.docker.debugPort>8889</alfresco.share.docker.debugPort>
<alfresco.aio.docker.version>5.1.5</alfresco.aio.docker.version>
<alfresco.solr6.docker.version>2.0.12</alfresco.solr6.docker.version>
</properties>
<dependencyManagement>
@ -163,24 +173,6 @@
<artifactId>keycloak-admin-client-jakarta</artifactId>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
<!-- HttpClient already bundled by both Repository and Share web apps -->
<dependency>
@ -218,14 +210,6 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.core.repo</artifactId>
<version>${acosix.utility.version}</version>
<classifier>installable</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.core.share</artifactId>
@ -233,14 +217,6 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.core.share</artifactId>
<version>${acosix.utility.version}</version>
<classifier>installable</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.repo</artifactId>
@ -263,14 +239,6 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.share</artifactId>
<version>${acosix.utility.version}</version>
<classifier>installable</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-repo</artifactId>
@ -284,21 +252,6 @@
<version>${ootbee.support-tools.version}</version>
<scope>test</scope>
</dependency>
<!-- relevant to support vm: transport for non-AMQ-Docker setup -->
<!-- transitive dependencies are already part of ACS -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
<version>${activemq.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
@ -312,6 +265,11 @@
</repository>
</repositories>
<modules>
<module>repository</module>
<module>share</module>
</modules>
<build>
<pluginManagement>
<plugins>
@ -330,9 +288,14 @@
</plugins>
</pluginManagement>
</build>
<profiles>
<profile>
<id>dockerTest</id>
<modules>
<module>repository</module>
<module>share</module>
</modules>
<modules>
<module>docker-test</module>
</modules>
</profile>
</profiles>
</project>

View File

@ -27,11 +27,6 @@
<artifactId>de.acosix.alfresco.keycloak.repo</artifactId>
<name>Acosix Alfresco Keycloak - Repository Module</name>
<properties>
<docker.tests.keycloakPort>8380</docker.tests.keycloakPort>
<docker.tests.skipSearchImage>false</docker.tests.skipSearchImage>
</properties>
<dependencies>
<dependency>
@ -74,7 +69,7 @@
<!-- use default from Alfresco Repository -->
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
@ -103,7 +98,7 @@
<!-- use default from Alfresco Repository -->
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcomponents-client</artifactId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
@ -136,98 +131,11 @@
</exclusions>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.core.repo</artifactId>
<classifier>installable</classifier>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.repo</artifactId>
<classifier>installable</classifier>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-repo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<!-- some image customisations -->
<!-- Maven + docker-maven-plugin result in somewhat weird inheritance handling -->
<!-- (relying on positional order of images for overrides) -->
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<images>
<image>
<!-- no change to postgres image (first image in parent POM) -->
</image>
<image>
<!-- customise repository image (second image in parent POM) -->
<run>
<!-- add log directory mount to just the contentstore -->
<!-- (cannot be done in parent POM due to hard requirement on specific project structure -->
<!-- for tests to easily check contentstore files, we also mount alf_data locally, not in a volume -->
<volumes>
<bind>
<volume>${moduleId}-repository-test-contentstore:/usr/local/tomcat/alf_data</volume>
<volume>${project.build.directory}/docker/repository-logs:/usr/local/tomcat/logs</volume>
</bind>
</volumes>
<dependsOn>
<container>postgres</container>
<container>keycloak</container>
</dependsOn>
</run>
</image>
<image>
<!-- no change to Share image (we don't use it) -->
</image>
<image>
<!-- no change to Search image -->
</image>
<image>
<name>jboss/keycloak:${keycloak.version}</name>
<alias>keycloak</alias>
<run>
<hostname>keycloak</hostname>
<env>
<KEYCLOAK_USER>admin</KEYCLOAK_USER>
<KEYCLOAK_PASSWORD>admin</KEYCLOAK_PASSWORD>
<KEYCLOAK_IMPORT>/tmp/test-realm.json</KEYCLOAK_IMPORT>
<DB_VENDOR>h2</DB_VENDOR>
</env>
<ports>
<port>${docker.tests.keycloakPort}:8080</port>
</ports>
<network>
<mode>custom</mode>
<name>${moduleId}-test</name>
<alias>keycloak</alias>
</network>
<volumes>
<bind>
<volume>${project.build.directory}/docker/test-realm.json:/tmp/test-realm.json</volume>
</bind>
</volumes>
</run>
</image>
</images>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
@ -320,11 +228,6 @@
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
</plugin>

View File

@ -15,6 +15,7 @@
*/
package de.acosix.alfresco.keycloak.repo.client;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MappingIterator;
@ -53,6 +54,12 @@ public abstract class AbstractIDMClientImpl implements InitializingBean
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractIDMClientImpl.class);
static
{
// newer Keycloak versions may introduce properties the libraries included in this project do not support
JsonSerialization.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
protected KeycloakDeployment deployment;
protected AccessTokenService accessTokenService;

View File

@ -288,7 +288,7 @@ public class KeycloakAdapterConfigBeanFactory implements FactoryBean<ExtendedAda
{
throw new IllegalStateException("Value " + trimmedValue + " has more than one character");
}
effectiveValue = new Character(trimmedValue.charAt(0));
effectiveValue = Character.valueOf(trimmedValue.charAt(0));
}
else if (String.class.equals(valueType))
{

View File

@ -1,12 +0,0 @@
FROM ${docker.tests.repositoryBaseImage}
COPY maven ${docker.tests.repositoryWebappPath}
${docker.tests.repositoryImageBuilder.preRun}
# merge additions to alfresco-global.properties
RUN echo "" >> ${docker.tests.repositoryWebappPath}/../../shared/classes/alfresco-global.properties \
&& echo "#MergeGlobalProperties" >> ${docker.tests.repositoryWebappPath}/../../shared/classes/alfresco-global.properties \
&& sed -i '/#MergeGlobalProperties/r ${docker.tests.repositoryWebappPath}/WEB-INF/classes/alfresco/extension/alfresco-global.addition.properties' ${docker.tests.repositoryWebappPath}/../../shared/classes/alfresco-global.properties \
&& sed -i 's/<secure>true<\/secure>/<secure>false<\/secure>/' $CATALINA_HOME/conf/web.xml
${docker.tests.repositoryImageBuilder.postRun}

View File

@ -1,35 +0,0 @@
#
# Copyright 2019 - 2021 Acosix GmbH
#
# Licensed 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: this file is not named alfresco-global.properties to not override the default file in the image
# instead it relies on Dockerfile post-processing to merge with the default file
authentication.chain=keycloak1:keycloak,alfrescoNtlm1:alfrescoNtlm
keycloak.adapter.auth-server-url=http://localhost:${docker.tests.keycloakPort}/auth
keycloak.adapter.realm=test
keycloak.adapter.resource=alfresco
keycloak.adapter.credentials.provider=secret
keycloak.adapter.credentials.secret=6f70a28f-98cd-41ca-8f2f-368a8797d708
# localhost in auth-server-url won't work for direct access in a Docker deployment
keycloak.adapter.proxy-url=http://keycloak:8080
keycloak.roles.requiredClientScopes=alfresco-role-service
keycloak.synchronization.userFilter.containedInGroup.property.groupPaths=/Test A
keycloak.synchronization.groupFilter.containedInGroup.property.groupPaths=/Test A
keycloak.synchronization.requiredClientScopes=alfresco-authority-sync

View File

@ -1,101 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Copyright 2019 - 2021 Acosix GmbH
Licensed 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.
-->
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>repository-it-docker</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<include>${project.artifactId}-${project.version}-installable.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/test/resources</directory>
<outputDirectory>WEB-INF/classes</outputDirectory>
<includes>
<include>*.properties</include>
<include>**/*.properties</include>
</includes>
<filtered>true</filtered>
<lineEnding>lf</lineEnding>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/test/docker/alfresco</directory>
<outputDirectory>WEB-INF/classes/alfresco</outputDirectory>
<includes>
<include>*</include>
<include>**/*</include>
</includes>
<excludes>
<exclude>*.js</exclude>
<exclude>**/*.js</exclude>
<exclude>*.ftl</exclude>
<exclude>**/*.ftl</exclude>
<exclude>*.keystore</exclude>
<exclude>**/*.keystore</exclude>
</excludes>
<filtered>true</filtered>
<lineEnding>lf</lineEnding>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/test/docker/alfresco</directory>
<outputDirectory>WEB-INF/classes/alfresco</outputDirectory>
<includes>
<include>*.js</include>
<include>**/*.js</include>
<include>*.ftl</include>
<include>**/*.ftl</include>
<include>*.keystore</include>
<include>**/*.keystore</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<include>${project.groupId}:${project.artifactId}.deps:*</include>
</includes>
<scope>compile</scope>
</dependencySet>
<dependencySet>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<!-- TODO: Report bug against Maven PatternIncludesArtifactFilter#matchAgainst for incorrect return false-->
<!-- when patterns with 5 tokens are listed in includes (like the installable JAR of Acosix Utility Core Repo), they may prevent evaluation of any additional patterns -->
<!-- this cost me half a day to track down when the following three patterns were sorted last -->
<include>org.orderofthebee.support-tools:*</include>
<include>com.cronutils:*</include>
<include>net.time4j:*</include>
<include>org.apache.activemq:activemq-broker</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.common:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.core.repo.quartz1:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.core.repo.quartz2:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.core.repo:jar:installable:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.repo:jar:installable:*</include>
</includes>
<scope>test</scope>
</dependencySet>
</dependencySets>
</assembly>

View File

@ -1 +0,0 @@
# only exists to ensure Maven creates path in project ./target

File diff suppressed because it is too large Load Diff

View File

@ -35,18 +35,10 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>de.acosix.alfresco.keycloak.repo</artifactId>
<version>${project.version}</version>
<classifier>installable</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.77</version>
<version>1.80</version>
</dependency>
</dependencies>
@ -135,145 +127,21 @@
<artifactId>bcpkix-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.core.repo</artifactId>
<classifier>installable</classifier>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.repo</artifactId>
<classifier>installable</classifier>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.core.share</artifactId>
</dependency>
<dependency>
<groupId>de.acosix.alfresco.utility</groupId>
<artifactId>de.acosix.alfresco.utility.core.share</artifactId>
<classifier>installable</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>de.acosix.alfresco.keycloak.repo</artifactId>
<classifier>installable</classifier>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-repo</artifactId>
</dependency>
<dependency>
<groupId>org.orderofthebee.support-tools</groupId>
<artifactId>support-tools-share</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<!-- some image customisations -->
<!-- Maven + docker-maven-plugin result in somewhat weird inheritance handling -->
<!-- (relying on positional order of images for overrides) -->
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<images>
<image>
<!-- no change to postgres image (first image in parent POM) -->
</image>
<image>
<!-- customise repository image (second image in parent POM) -->
<run>
<env>
<DOCKER_HOST_NAME>${docker.tests.host.name}</DOCKER_HOST_NAME>
</env>
<!-- add log directory mount to just the contentstore -->
<!-- (cannot be done in parent POM due to hard requirement on specific project structure -->
<!-- for tests to easily check contentstore files, we also mount alf_data locally, not in a volume -->
<volumes>
<bind>
<volume>${moduleId}-repository-test-contentstore:/usr/local/tomcat/alf_data</volume>
<volume>${project.build.directory}/docker/repository-logs:/usr/local/tomcat/logs</volume>
</bind>
</volumes>
<dependsOn>
<container>postgres</container>
<container>keycloak</container>
</dependsOn>
</run>
</image>
<image>
<run>
<volumes>
<bind>
<volume>${project.build.directory}/docker/share-logs:/usr/local/tomcat/logs</volume>
</bind>
</volumes>
</run>
</image>
<image>
<!-- no change to Search image -->
</image>
<image>
<name>jboss/keycloak:${keycloak.version}</name>
<alias>keycloak</alias>
<run>
<hostname>keycloak</hostname>
<env>
<KEYCLOAK_USER>admin</KEYCLOAK_USER>
<KEYCLOAK_PASSWORD>admin</KEYCLOAK_PASSWORD>
<KEYCLOAK_IMPORT>/tmp/test-realm.json</KEYCLOAK_IMPORT>
<DB_VENDOR>h2</DB_VENDOR>
</env>
<ports>
<port>${docker.tests.keycloakPort}:8080</port>
</ports>
<network>
<mode>custom</mode>
<name>${moduleId}-test</name>
<alias>keycloak</alias>
</network>
<volumes>
<bind>
<volume>${project.build.directory}/docker/keycloakProfile.properties:/opt/jboss/keycloak/standalone/configuration/profile.properties</volume>
<volume>${project.build.directory}/docker/test-realm.json:/tmp/test-realm.json</volume>
</bind>
</volumes>
</run>
</image>
</images>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
@ -398,11 +266,6 @@
<artifactId>yuicompressor-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
</plugin>

View File

@ -102,7 +102,7 @@ public class KeycloakAdapterConfigElementReader implements ConfigElementReader
{
throw new IllegalStateException("Value " + textTrim + " has more than one character");
}
configElement.setFieldValue(subElementName, new Character(textTrim.charAt(0)));
configElement.setFieldValue(subElementName, Character.valueOf(textTrim.charAt(0)));
}
else if (String.class.equals(valueType))
{

View File

@ -38,17 +38,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.PropertyCheck;
@ -57,7 +46,6 @@ import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
@ -70,7 +58,6 @@ import org.apache.http.conn.routing.HttpRoutePlanner;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.OAuth2Constants;
@ -139,6 +126,16 @@ import de.acosix.alfresco.keycloak.share.remote.AccessTokenAwareSlingshotAlfresc
import de.acosix.alfresco.keycloak.share.util.HttpClientBuilder;
import de.acosix.alfresco.keycloak.share.util.NameValueMapAdapter;
import de.acosix.alfresco.keycloak.share.util.RefreshableAccessTokenHolder;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
/**
* Keycloak-based authentication filter class which can act as a standalone filter or a facade to the default {@link SSOAuthenticationFilter
@ -534,19 +531,19 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
private HttpClient client;
@Override
public HttpClient call() throws Exception {
if (client == null) {
if (this.client == null) {
synchronized (this) {
if (client == null) {
client = new HttpClientBuilder()
.routePlanner(createForcedRoutePlanner(adapterConfiguration))
if (this.client == null) {
this.client = new HttpClientBuilder()
.routePlanner(KeycloakAuthenticationFilter.this.createForcedRoutePlanner(adapterConfiguration))
.build(adapterConfiguration);
}
}
}
return client;
return this.client;
}
});
this.deploymentContext = new AdapterDeploymentContext(this.keycloakDeployment);
}
@ -1773,7 +1770,7 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
throw new IllegalStateException(
"Either an active security context or access token should be present in the session, or previous validations have caught their non-existence and prevented this operation form being called");
}
final List<Header> headers = new LinkedList<>();
ClientCredentialsProviderUtils.setClientCredentials(
@ -1782,8 +1779,10 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
new NameValueMapAdapter<>(headers, BasicHeader.class),
new NameValueMapAdapter<>(formParams, BasicNameValuePair.class));
for (Header header : headers)
for (final Header header : headers)
{
post.addHeader(header);
}
final UrlEncodedFormEntity form = new UrlEncodedFormEntity(formParams, "UTF-8");
post.setEntity(form);
@ -1901,45 +1900,42 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
params.setParameter(ConnRoutePNames.FORCED_ROUTE, route);
}
protected HttpRoute createRoute(ExtendedAdapterConfig adapterConfig, HttpHost routeHost) throws UnknownHostException, MalformedURLException {
boolean secure = "https".equalsIgnoreCase(routeHost.getSchemeName());
protected HttpRoute createRoute(final ExtendedAdapterConfig adapterConfig, final HttpHost routeHost) throws UnknownHostException, MalformedURLException {
final boolean secure = "https".equalsIgnoreCase(routeHost.getSchemeName());
if (adapterConfig.getProxyUrl() != null) {
// useful in parsing the URL for just what is needed for HttpHost
URL proxyUrl = new URL(adapterConfig.getProxyUrl());
HttpHost proxyHost = new HttpHost(proxyUrl.getHost(), proxyUrl.getPort(), proxyUrl.getProtocol());
final URL proxyUrl = new URL(adapterConfig.getProxyUrl());
final HttpHost proxyHost = new HttpHost(proxyUrl.getHost(), proxyUrl.getPort(), proxyUrl.getProtocol());
return new HttpRoute(routeHost, InetAddress.getLocalHost(), proxyHost, secure);
} else {
return new HttpRoute(routeHost, InetAddress.getLocalHost(), secure);
}
}
protected HttpRoute createForcedRoute(ExtendedAdapterConfig adapterConfig) throws UnknownHostException, MalformedURLException {
protected HttpRoute createForcedRoute(final ExtendedAdapterConfig adapterConfig) throws UnknownHostException, MalformedURLException {
// useful in parsing the URL for just what is needed for HttpHost
URL forcedRouteUrl = new URL(adapterConfig.getForcedRouteUrl());
HttpHost forcedRouteHost = new HttpHost(forcedRouteUrl.getHost(), forcedRouteUrl.getPort(), forcedRouteUrl.getProtocol());
final URL forcedRouteUrl = new URL(adapterConfig.getForcedRouteUrl());
final HttpHost forcedRouteHost = new HttpHost(forcedRouteUrl.getHost(), forcedRouteUrl.getPort(), forcedRouteUrl.getProtocol());
return this.createRoute(adapterConfig, forcedRouteHost);
}
protected HttpRoutePlanner createForcedRoutePlanner(ExtendedAdapterConfig adapterConfig) throws MalformedURLException {
URL authServerUrl = new URL(adapterConfig.getAuthServerUrl());
protected HttpRoutePlanner createForcedRoutePlanner(final ExtendedAdapterConfig adapterConfig) throws MalformedURLException {
final URL authServerUrl = new URL(adapterConfig.getAuthServerUrl());
final HttpHost authServerHost = new HttpHost(authServerUrl.getHost(), authServerUrl.getPort(), authServerUrl.getProtocol());
return new HttpRoutePlanner() {
@Override
public HttpRoute determineRoute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
try {
if (authServerHost.equals(target)) {
LOGGER.trace("Rerouting to forced route");
HttpRoute route = createForcedRoute(adapterConfig);
LOGGER.trace("Rerouting to forced route: {}", route);
return route;
} else {
return createRoute(adapterConfig, target);
}
} catch (IOException ie) {
throw new HttpException(ie.getMessage(), ie);
return (target, request, context) -> {
try {
if (authServerHost.equals(target)) {
LOGGER.trace("Rerouting to forced route");
final HttpRoute route = KeycloakAuthenticationFilter.this.createForcedRoute(adapterConfig);
LOGGER.trace("Rerouting to forced route: {}", route);
return route;
} else {
return KeycloakAuthenticationFilter.this.createRoute(adapterConfig, target);
}
} catch (final IOException ie) {
throw new HttpException(ie.getMessage(), ie);
}
};
}

View File

@ -1,12 +0,0 @@
FROM ${docker.tests.repositoryBaseImage}
COPY maven ${docker.tests.repositoryWebappPath}
${docker.tests.repositoryImageBuilder.preRun}
# merge additions to alfresco-global.properties
RUN echo "" >> ${docker.tests.repositoryWebappPath}/../../shared/classes/alfresco-global.properties \
&& echo "#MergeGlobalProperties" >> ${docker.tests.repositoryWebappPath}/../../shared/classes/alfresco-global.properties \
&& sed -i '/#MergeGlobalProperties/r ${docker.tests.repositoryWebappPath}/WEB-INF/classes/alfresco/extension/alfresco-global.addition.properties' ${docker.tests.repositoryWebappPath}/../../shared/classes/alfresco-global.properties \
&& sed -i 's/<secure>true<\/secure>/<secure>false<\/secure>/' $CATALINA_HOME/conf/web.xml
${docker.tests.repositoryImageBuilder.postRun}

View File

@ -1,35 +0,0 @@
#
# Copyright 2019 - 2021 Acosix GmbH
#
# Licensed 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: this file is not named alfresco-global.properties to not override the default file in the image
# instead it relies on Dockerfile post-processing to merge with the default file
authentication.chain=keycloak1:keycloak,alfrescoNtlm1:alfrescoNtlm
keycloak.adapter.auth-server-url=http://localhost:${docker.tests.keycloakPort}/auth
keycloak.adapter.realm=test
keycloak.adapter.resource=alfresco
keycloak.adapter.credentials.provider=secret
keycloak.adapter.credentials.secret=6f70a28f-98cd-41ca-8f2f-368a8797d708
# localhost in auth-server-url won't work for direct access in a Docker deployment
keycloak.adapter.forced-route-url=http://keycloak:8080
keycloak.roles.requiredClientScopes=alfresco-role-service
keycloak.synchronization.userFilter.containedInGroup.property.groupPaths=/Test A
keycloak.synchronization.groupFilter.containedInGroup.property.groupPaths=/Test A
keycloak.synchronization.requiredClientScopes=alfresco-authority-sync

View File

@ -1,25 +0,0 @@
#
# Copyright 2019 - 2021 Acosix GmbH
#
# Licensed 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.
log4j.rootLogger=error, File
log4j.appender.File=org.apache.log4j.DailyRollingFileAppender
log4j.appender.File.File=\${catalina.base}/logs/share.log
log4j.appender.File.Append=true
log4j.appender.File.DatePattern='.'yyyy-MM-dd
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d{yyyy-MM-dd} %d{ABSOLUTE} %-5p [%c] [%t] %m%n
log4j.logger.${project.artifactId}=DEBUG

View File

@ -1 +0,0 @@
feature.token_exchange=enabled

View File

@ -1,80 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Copyright 2019 - 2021 Acosix GmbH
Licensed 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.
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>repository-it-docker</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/test/docker/alfresco</directory>
<outputDirectory>WEB-INF/classes/alfresco</outputDirectory>
<includes>
<include>*</include>
<include>**/*</include>
</includes>
<excludes>
<exclude>*.js</exclude>
<exclude>**/*.js</exclude>
<exclude>*.ftl</exclude>
<exclude>**/*.ftl</exclude>
<exclude>*.keystore</exclude>
<exclude>**/*.keystore</exclude>
</excludes>
<filtered>true</filtered>
<lineEnding>lf</lineEnding>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/test/docker/alfresco</directory>
<outputDirectory>WEB-INF/classes/alfresco</outputDirectory>
<includes>
<include>*.js</include>
<include>**/*.js</include>
<include>*.ftl</include>
<include>**/*.ftl</include>
<include>*.keystore</include>
<include>**/*.keystore</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<!-- TODO: Report bug against Maven PatternIncludesArtifactFilter#matchAgainst for incorrect return false-->
<!-- when patterns with 5 tokens are listed in includes (like the installable JAR of Acosix Utility Core Repo), they may prevent evaluation of any additional patterns -->
<!-- this cost me half a day to track down when the following three patterns were sorted last -->
<include>com.cronutils:*</include>
<include>net.time4j:*</include>
<include>org.apache.activemq:activemq-broker</include>
<include>org.orderofthebee.support-tools:support-tools-repo:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.common:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.core.repo.quartz1:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.core.repo.quartz2:*</include>
<include>${project.groupId}:de.acosix.alfresco.keycloak.repo.deps:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.core.repo:jar:installable:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.repo:jar:installable:*</include>
<include>${project.groupId}:de.acosix.alfresco.keycloak.repo:jar:installable:*</include>
</includes>
<scope>test</scope>
</dependencySet>
</dependencySets>
</assembly>

View File

@ -1 +0,0 @@
# only exists to ensure Maven creates path in project ./target

View File

@ -1,84 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Copyright 2019 - 2021 Acosix GmbH
Licensed 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.
-->
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>share-it-docker</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<include>${project.artifactId}-${project.version}-installable.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/test/docker/alfresco</directory>
<outputDirectory>WEB-INF/classes/alfresco</outputDirectory>
<includes>
<include>*</include>
<include>**/*</include>
</includes>
<excludes>
<exclude>*.js</exclude>
<exclude>**/*.js</exclude>
<exclude>*.ftl</exclude>
<exclude>**/*.ftl</exclude>
<exclude>*.keystore</exclude>
<exclude>**/*.keystore</exclude>
</excludes>
<filtered>true</filtered>
<lineEnding>lf</lineEnding>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/test/docker/alfresco</directory>
<outputDirectory>WEB-INF/classes/alfresco</outputDirectory>
<includes>
<include>*.js</include>
<include>**/*.js</include>
<include>*.ftl</include>
<include>**/*.ftl</include>
<include>*.keystore</include>
<include>**/*.keystore</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<include>${project.groupId}:de.acosix.alfresco.keycloak.share.deps:*</include>
<include>org.bouncycastle:*</include>
</includes>
<scope>compile</scope>
</dependencySet>
<dependencySet>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
<include>org.slf4j:slf4j-log4j12:*</include>
<include>org.orderofthebee.support-tools:support-tools-share:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.common:*</include>
<include>de.acosix.alfresco.utility:de.acosix.alfresco.utility.core.share:jar:installable:*</include>
</includes>
<scope>test</scope>
</dependencySet>
</dependencySets>
</assembly>

View File

@ -1 +0,0 @@
# only exists to ensure Maven creates path in project ./target