You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2019/04/26 13:32:48 UTC
[syncope] branch master updated: [SYNCOPE-1458] Docker verified
working
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new 6288660 [SYNCOPE-1458] Docker verified working
6288660 is described below
commit 628866065eab8e4445e5d1c0b191b536586d234a
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Fri Apr 26 15:32:39 2019 +0200
[SYNCOPE-1458] Docker verified working
---
.../zookeper/ZookeeperKeymasterClientContext.java | 39 ++++++-----
.../core/spring/security/AuthDataAccessor.java | 10 ++-
.../UsernamePasswordAuthenticationProvider.java | 77 +++++++++++++---------
.../core/spring/security/WebSecurityContext.java | 2 +
docker/console/pom.xml | 11 ++++
.../src/main/resources/keymaster.properties | 19 ++++++
docker/core/pom.xml | 21 ++++++
.../core/src/main/resources/keymaster.properties | 19 ++++++
docker/enduser/pom.xml | 11 ++++
.../src/main/resources/keymaster.properties | 19 ++++++
.../resources/docker-compose/docker-compose-ha.yml | 12 ++++
.../docker-compose/docker-compose-mariadb.yml | 9 +++
.../docker-compose/docker-compose-mssql.yml | 9 +++
.../docker-compose/docker-compose-myjson.yml | 9 +++
.../docker-compose/docker-compose-mysql.yml | 9 +++
.../docker-compose/docker-compose-pgjsonb.yml | 9 +++
.../docker-compose/docker-compose-postgresql.yml | 9 +++
...postgresql.yml => docker-compose-zookeeper.yml} | 18 ++++-
.../self/keymaster/cxf/SelfKeymasterContext.java | 10 +++
...sterUsernamePasswordAuthenticationProvider.java | 48 ++++++++++++++
20 files changed, 315 insertions(+), 55 deletions(-)
diff --git a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeper/ZookeeperKeymasterClientContext.java b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeper/ZookeeperKeymasterClientContext.java
index e42bc6d..507ccbc 100644
--- a/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeper/ZookeeperKeymasterClientContext.java
+++ b/common/keymaster/client-zookeeper/src/main/java/org/apache/syncope/common/keymaster/client/zookeper/ZookeeperKeymasterClientContext.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.security.auth.login.AppConfigurationEntry;
+import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.ACLProvider;
@@ -79,24 +80,30 @@ public class ZookeeperKeymasterClientContext {
@ConditionalOnExpression("#{'${keymaster.address}' matches '^(?!http).+'}")
@Bean
public CuratorFramework curatorFramework() throws InterruptedException {
- javax.security.auth.login.Configuration.setConfiguration(createJaasConfig());
+ if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
+ javax.security.auth.login.Configuration.setConfiguration(createJaasConfig());
+ }
- CuratorFramework client = CuratorFrameworkFactory.builder().
+ CuratorFrameworkFactory.Builder clientBuilder = CuratorFrameworkFactory.builder().
connectString(address).
- retryPolicy(new ExponentialBackoffRetry(baseSleepTimeMs, maxRetries)).
- authorization("digest", (username).getBytes()).
- aclProvider(new ACLProvider() {
-
- @Override
- public List<ACL> getDefaultAcl() {
- return ZooDefs.Ids.CREATOR_ALL_ACL;
- }
-
- @Override
- public List<ACL> getAclForPath(final String path) {
- return ZooDefs.Ids.CREATOR_ALL_ACL;
- }
- }).build();
+ retryPolicy(new ExponentialBackoffRetry(baseSleepTimeMs, maxRetries));
+ if (StringUtils.isNotBlank(username)) {
+ clientBuilder.
+ authorization("digest", (username).getBytes()).
+ aclProvider(new ACLProvider() {
+
+ @Override
+ public List<ACL> getDefaultAcl() {
+ return ZooDefs.Ids.CREATOR_ALL_ACL;
+ }
+
+ @Override
+ public List<ACL> getAclForPath(final String path) {
+ return ZooDefs.Ids.CREATOR_ALL_ACL;
+ }
+ });
+ }
+ CuratorFramework client = clientBuilder.build();
client.start();
client.blockUntilConnected(3, TimeUnit.SECONDS);
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
index 3226ff1..0e4851a 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
@@ -31,7 +31,6 @@ import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.BooleanUtils;
-import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
import org.apache.syncope.common.lib.SyncopeConstants;
@@ -67,7 +66,6 @@ import org.springframework.security.authentication.AuthenticationCredentialsNotF
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -237,7 +235,7 @@ public class AuthDataAccessor {
}
}
- return ImmutablePair.of(user, authenticated);
+ return Pair.of(user, authenticated);
}
protected boolean authenticate(final User user, final String password) {
@@ -360,10 +358,10 @@ public class AuthDataAccessor {
} else {
User user = userDAO.findByUsername(username);
if (user == null) {
- throw new UsernameNotFoundException("Could not find any user with id " + username);
+ authorities = Collections.emptySet();
+ } else {
+ authorities = getUserAuthorities(user);
}
-
- authorities = getUserAuthorities(user);
}
return authorities;
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java
index a1e77e2..a805b45 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java
@@ -19,6 +19,7 @@
package org.apache.syncope.core.spring.security;
import javax.annotation.Resource;
+import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.types.AuditElements;
@@ -50,7 +51,7 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro
protected UserProvisioningManager provisioningManager;
@Autowired
- private DefaultCredentialChecker credentialChecker;
+ protected DefaultCredentialChecker credentialChecker;
@Resource(name = "adminUser")
protected String adminUser;
@@ -90,10 +91,10 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro
@Override
public Authentication authenticate(final Authentication authentication) {
- String domainKey = SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).getDomain();
+ String domain = SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).getDomain();
- final String[] username = new String[1];
- Boolean authenticated;
+ String[] username = new String[1];
+ boolean authenticated;
if (anonymousUser.equals(authentication.getName())) {
username[0] = anonymousUser;
@@ -101,32 +102,31 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro
authenticated = authentication.getCredentials().toString().equals(anonymousKey);
} else if (adminUser.equals(authentication.getName())) {
username[0] = adminUser;
- if (SyncopeConstants.MASTER_DOMAIN.equals(domainKey)) {
+ if (SyncopeConstants.MASTER_DOMAIN.equals(domain)) {
credentialChecker.checkIsDefaultAdminPasswordInUse();
authenticated = ENCRYPTOR.verify(
authentication.getCredentials().toString(),
CipherAlgorithm.valueOf(adminPasswordAlgorithm),
adminPassword);
} else {
- final String domainToFind = domainKey;
authenticated = AuthContextUtils.callAsAdmin(SyncopeConstants.MASTER_DOMAIN, () -> {
- Domain domain = dataAccessor.findDomain(domainToFind);
+ Domain domainEntity = dataAccessor.findDomain(domain);
return ENCRYPTOR.verify(
authentication.getCredentials().toString(),
- domain.getAdminCipherAlgorithm(),
- domain.getAdminPwd());
+ domainEntity.getAdminCipherAlgorithm(),
+ domainEntity.getAdminPwd());
});
}
} else {
- Pair<User, Boolean> authResult = AuthContextUtils.callAsAdmin(domainKey,
- () -> dataAccessor.authenticate(domainKey, authentication));
- authenticated = authResult.getValue();
+ Pair<User, Boolean> authResult = AuthContextUtils.callAsAdmin(domain,
+ () -> dataAccessor.authenticate(domain, authentication));
+ authenticated = BooleanUtils.toBoolean(authResult.getRight());
if (authResult.getLeft() != null && authResult.getRight() != null) {
username[0] = authResult.getLeft().getUsername();
if (!authResult.getRight()) {
- AuthContextUtils.callAsAdmin(domainKey, () -> {
+ AuthContextUtils.callAsAdmin(domain, () -> {
provisioningManager.internalSuspend(authResult.getLeft().getKey());
return null;
});
@@ -137,45 +137,58 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro
username[0] = authentication.getPrincipal().toString();
}
- final boolean isAuthenticated = authenticated != null && authenticated;
+ return finalizeAuthentication(authenticated, domain, username[0], authentication);
+ }
+
+ protected Authentication finalizeAuthentication(
+ final boolean authenticated,
+ final String domain,
+ final String username,
+ final Authentication authentication) {
+
UsernamePasswordAuthenticationToken token;
- if (isAuthenticated) {
- token = AuthContextUtils.callAsAdmin(domainKey, () -> {
- UsernamePasswordAuthenticationToken token1 = new UsernamePasswordAuthenticationToken(
- username[0],
+ if (authenticated) {
+ token = AuthContextUtils.callAsAdmin(domain, () -> {
+ UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(
+ username,
null,
- dataAccessor.getAuthorities(username[0]));
- token1.setDetails(authentication.getDetails());
+ dataAccessor.getAuthorities(username));
+ upat.setDetails(authentication.getDetails());
dataAccessor.audit(
- username[0],
+ username,
AuditElements.EventCategoryType.LOGIC,
- AuditElements.AUTHENTICATION_CATEGORY, null,
- AuditElements.LOGIN_EVENT, Result.SUCCESS, null, isAuthenticated, authentication,
- "Successfully authenticated, with entitlements: " + token1.getAuthorities());
- return token1;
+ AuditElements.AUTHENTICATION_CATEGORY,
+ null,
+ AuditElements.LOGIN_EVENT,
+ Result.SUCCESS,
+ null,
+ authenticated,
+ authentication,
+ "User " + username + " successfully authenticated with entitlements: " + upat.getAuthorities());
+ return upat;
});
LOG.debug("User {} successfully authenticated, with entitlements {}",
- username[0], token.getAuthorities());
+ username, token.getAuthorities());
} else {
- AuthContextUtils.callAsAdmin(domainKey, () -> {
+ AuthContextUtils.callAsAdmin(domain, () -> {
dataAccessor.audit(
- username[0],
+ username,
AuditElements.EventCategoryType.LOGIC,
AuditElements.AUTHENTICATION_CATEGORY,
null,
AuditElements.LOGIN_EVENT,
Result.FAILURE,
null,
- isAuthenticated,
+ authenticated,
authentication,
- "User " + username[0] + " not authenticated");
+ "User " + username + " not authenticated");
return null;
});
- LOG.debug("User {} not authenticated", username[0]);
+ LOG.debug("User {} not authenticated", username);
- throw new BadCredentialsException("User " + username[0] + " not authenticated");
+ throw new BadCredentialsException("User " + username + " not authenticated");
}
return token;
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/WebSecurityContext.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/WebSecurityContext.java
index f6db336..29e9e5c 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/WebSecurityContext.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/WebSecurityContext.java
@@ -19,6 +19,7 @@
package org.apache.syncope.core.spring.security;
import javax.annotation.Resource;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
@@ -60,6 +61,7 @@ public class WebSecurityContext extends WebSecurityConfigurerAdapter {
web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
}
+ @ConditionalOnMissingBean
@Bean
public UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider() {
return new UsernamePasswordAuthenticationProvider();
diff --git a/docker/console/pom.xml b/docker/console/pom.xml
index 8ecfb3e..5016a0f 100644
--- a/docker/console/pom.xml
+++ b/docker/console/pom.xml
@@ -50,6 +50,17 @@ under the License.
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.self-keymaster</groupId>
+ <artifactId>syncope-ext-self-keymaster-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.common.keymaster</groupId>
+ <artifactId>syncope-common-keymaster-client-zookeeper</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.syncope.ext.flowable</groupId>
<artifactId>syncope-ext-flowable-client-console</artifactId>
<version>${project.version}</version>
diff --git a/docker/console/src/main/resources/keymaster.properties b/docker/console/src/main/resources/keymaster.properties
new file mode 100644
index 0000000..14e8ca6
--- /dev/null
+++ b/docker/console/src/main/resources/keymaster.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+keymaster.address=${KEYMASTER_ADDRESS}
+keymaster.username=${KEYMASTER_USERNAME}
+keymaster.password=${KEYMASTER_PASSWORD}
diff --git a/docker/core/pom.xml b/docker/core/pom.xml
index d81bb19..b58170c 100644
--- a/docker/core/pom.xml
+++ b/docker/core/pom.xml
@@ -53,6 +53,27 @@ under the License.
<artifactId>syncope-core-idm-rest-cxf</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.syncope.core.am</groupId>
+ <artifactId>syncope-core-am-rest-cxf</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.self-keymaster</groupId>
+ <artifactId>syncope-ext-self-keymaster-rest-cxf</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.self-keymaster</groupId>
+ <artifactId>syncope-ext-self-keymaster-persistence-jpa</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.common.keymaster</groupId>
+ <artifactId>syncope-common-keymaster-client-zookeeper</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.syncope.core</groupId>
diff --git a/docker/core/src/main/resources/keymaster.properties b/docker/core/src/main/resources/keymaster.properties
new file mode 100644
index 0000000..14e8ca6
--- /dev/null
+++ b/docker/core/src/main/resources/keymaster.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+keymaster.address=${KEYMASTER_ADDRESS}
+keymaster.username=${KEYMASTER_USERNAME}
+keymaster.password=${KEYMASTER_PASSWORD}
diff --git a/docker/enduser/pom.xml b/docker/enduser/pom.xml
index 2600cb3..e58ab48 100644
--- a/docker/enduser/pom.xml
+++ b/docker/enduser/pom.xml
@@ -50,6 +50,17 @@ under the License.
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.self-keymaster</groupId>
+ <artifactId>syncope-ext-self-keymaster-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.common.keymaster</groupId>
+ <artifactId>syncope-common-keymaster-client-zookeeper</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.syncope.ext.flowable</groupId>
<artifactId>syncope-ext-flowable-client-enduser</artifactId>
<version>${project.version}</version>
diff --git a/docker/enduser/src/main/resources/keymaster.properties b/docker/enduser/src/main/resources/keymaster.properties
new file mode 100644
index 0000000..14e8ca6
--- /dev/null
+++ b/docker/enduser/src/main/resources/keymaster.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+keymaster.address=${KEYMASTER_ADDRESS}
+keymaster.username=${KEYMASTER_USERNAME}
+keymaster.password=${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-ha.yml b/docker/src/main/resources/docker-compose/docker-compose-ha.yml
index c5857ba..1c08942 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-ha.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-ha.yml
@@ -44,6 +44,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: tcp(Addresses=syncope1;syncope2)
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope2:
depends_on:
@@ -60,6 +63,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: tcp(Addresses=syncope1;syncope2)
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-console:
depends_on:
@@ -72,6 +78,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope1
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: http://syncope1:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-enduser:
depends_on:
@@ -85,3 +94,6 @@ services:
CORE_HOST: syncope1
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: http://syncope1:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml b/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml
index e39ff8b..11ad7c1 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml
@@ -44,6 +44,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: sjvm
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-console:
depends_on:
@@ -56,6 +59,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-enduser:
depends_on:
@@ -69,3 +75,6 @@ services:
CORE_HOST: syncope
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-mssql.yml b/docker/src/main/resources/docker-compose/docker-compose-mssql.yml
index 32a9300..daeed50 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-mssql.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-mssql.yml
@@ -46,6 +46,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: sjvm
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-console:
depends_on:
@@ -58,6 +61,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-enduser:
depends_on:
@@ -71,3 +77,6 @@ services:
CORE_HOST: syncope
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-myjson.yml b/docker/src/main/resources/docker-compose/docker-compose-myjson.yml
index b5922b8..4c4abb9 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-myjson.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-myjson.yml
@@ -44,6 +44,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: sjvm
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-console:
depends_on:
@@ -56,6 +59,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-enduser:
depends_on:
@@ -69,3 +75,6 @@ services:
CORE_HOST: syncope
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-mysql.yml b/docker/src/main/resources/docker-compose/docker-compose-mysql.yml
index e9e25c7..510440a 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-mysql.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-mysql.yml
@@ -44,6 +44,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: sjvm
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-console:
depends_on:
@@ -56,6 +59,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-enduser:
depends_on:
@@ -69,3 +75,6 @@ services:
CORE_HOST: syncope
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-pgjsonb.yml b/docker/src/main/resources/docker-compose/docker-compose-pgjsonb.yml
index 8af76b7..745931e 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-pgjsonb.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-pgjsonb.yml
@@ -43,6 +43,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: sjvm
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-console:
depends_on:
@@ -55,6 +58,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-enduser:
depends_on:
@@ -68,3 +74,6 @@ services:
CORE_HOST: syncope
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml b/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
index 5911083..3509caa 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
@@ -43,6 +43,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: sjvm
+ KEYMASTER_ADDRESS: http://localhost:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-console:
depends_on:
@@ -55,6 +58,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
syncope-enduser:
depends_on:
@@ -68,3 +74,6 @@ services:
CORE_HOST: syncope
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: http://syncope:8080/syncope/rest/keymaster
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD}
diff --git a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml b/docker/src/main/resources/docker-compose/docker-compose-zookeeper.yml
similarity index 72%
copy from docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
copy to docker/src/main/resources/docker-compose/docker-compose-zookeeper.yml
index 5911083..a4be37a 100644
--- a/docker/src/main/resources/docker-compose/docker-compose-postgresql.yml
+++ b/docker/src/main/resources/docker-compose/docker-compose-zookeeper.yml
@@ -15,11 +15,18 @@
# specific language governing permissions and limitations
# under the License.
-# Full deployment (Core, Console, Enduser) on PostgreSQL
+# Full deployment (Core, Console, Enduser) on PostgreSQL, with Keymaster on Zookeeper
+
+# Zookeeper is configured without JAAS, hence empty KEYMASTER_USERNAME / KEYMASTER_PASSWORD
+# are passed to other containers
version: '3.3'
services:
+ keymaster:
+ image: zookeeper:3.4.14
+ restart: always
+
db:
image: postgres:11.2
restart: always
@@ -43,6 +50,9 @@ services:
DB_POOL_MAX: 10
DB_POOL_MIN: 2
OPENJPA_REMOTE_COMMIT: sjvm
+ KEYMASTER_ADDRESS: keymaster:2181
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME:-}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD:-}
syncope-console:
depends_on:
@@ -55,6 +65,9 @@ services:
CORE_SCHEME: http
CORE_HOST: syncope
CORE_PORT: 8080
+ KEYMASTER_ADDRESS: keymaster:2181
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME:-}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD:-}
syncope-enduser:
depends_on:
@@ -68,3 +81,6 @@ services:
CORE_HOST: syncope
CORE_PORT: 8080
DOMAIN: Master
+ KEYMASTER_ADDRESS: keymaster:2181
+ KEYMASTER_USERNAME: ${KEYMASTER_USERNAME:-}
+ KEYMASTER_PASSWORD: ${KEYMASTER_PASSWORD:-}
diff --git a/ext/self-keymaster/rest-cxf/src/main/java/org/apache/syncope/ext/self/keymaster/cxf/SelfKeymasterContext.java b/ext/self-keymaster/rest-cxf/src/main/java/org/apache/syncope/ext/self/keymaster/cxf/SelfKeymasterContext.java
index 6071bd6..4b16893 100644
--- a/ext/self-keymaster/rest-cxf/src/main/java/org/apache/syncope/ext/self/keymaster/cxf/SelfKeymasterContext.java
+++ b/ext/self-keymaster/rest-cxf/src/main/java/org/apache/syncope/ext/self/keymaster/cxf/SelfKeymasterContext.java
@@ -31,8 +31,12 @@ import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationOutInterceptor;
import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;
import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
+import org.apache.syncope.core.spring.security.UsernamePasswordAuthenticationProvider;
+import org.apache.syncope.core.spring.security.WebSecurityContext;
import org.apache.syncope.ext.self.keymaster.cxf.client.SelfKeymasterInternalConfParamOps;
+import org.apache.syncope.ext.self.keymaster.cxf.security.SelfKeymasterUsernamePasswordAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -44,6 +48,7 @@ import org.springframework.context.annotation.PropertySource;
@PropertySource(value = "file:${conf.directory}/keymaster.properties", ignoreResourceNotFound = true)
@ComponentScan("org.apache.syncope.ext.self.keymaster.cxf.service")
@Configuration
+@AutoConfigureBefore(WebSecurityContext.class)
@ConditionalOnExpression("'${keymaster.address}' matches '^http.+'")
public class SelfKeymasterContext {
@@ -109,6 +114,11 @@ public class SelfKeymasterContext {
}
@Bean
+ public UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider() {
+ return new SelfKeymasterUsernamePasswordAuthenticationProvider();
+ }
+
+ @Bean
public ConfParamOps internalConfParamOps() {
return new SelfKeymasterInternalConfParamOps();
}
diff --git a/ext/self-keymaster/rest-cxf/src/main/java/org/apache/syncope/ext/self/keymaster/cxf/security/SelfKeymasterUsernamePasswordAuthenticationProvider.java b/ext/self-keymaster/rest-cxf/src/main/java/org/apache/syncope/ext/self/keymaster/cxf/security/SelfKeymasterUsernamePasswordAuthenticationProvider.java
new file mode 100644
index 0000000..2068326
--- /dev/null
+++ b/ext/self-keymaster/rest-cxf/src/main/java/org/apache/syncope/ext/self/keymaster/cxf/security/SelfKeymasterUsernamePasswordAuthenticationProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.self.keymaster.cxf.security;
+
+import org.apache.syncope.core.spring.security.SyncopeAuthenticationDetails;
+import org.apache.syncope.core.spring.security.UsernamePasswordAuthenticationProvider;
+import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+
+@Configurable
+public class SelfKeymasterUsernamePasswordAuthenticationProvider extends UsernamePasswordAuthenticationProvider {
+
+ @Value("${keymaster.username}")
+ private String keymasterUsername;
+
+ @Value("${keymaster.password}")
+ private String keymasterPassword;
+
+ @Override
+ public Authentication authenticate(final Authentication authentication) {
+ if (keymasterUsername.equals(authentication.getName())) {
+ return finalizeAuthentication(
+ authentication.getCredentials().toString().equals(keymasterPassword),
+ SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).getDomain(),
+ keymasterUsername,
+ authentication);
+ }
+
+ return super.authenticate(authentication);
+ }
+}