You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2019/08/01 09:47:39 UTC
[isis] branch v2 updated: ISIS-2156 adds smoketest for Isis'
Shiro/Ldap integration
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/v2 by this push:
new 8bd3f24 ISIS-2156 adds smoketest for Isis' Shiro/Ldap integration
8bd3f24 is described below
commit 8bd3f246eab21ff2c2e2bcac74f574fd48baaf09
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Aug 1 11:47:30 2019 +0200
ISIS-2156 adds smoketest for Isis' Shiro/Ldap integration
---
examples/smoketest/log4j2-test.xml | 3 +
.../isis/testdomain/jdo/JdoTestDomainModule.java | 4 +-
...ity.java => JdoTestDomainModule_withShiro.java} | 18 ++----
.../testdomain/ldap/LdapEmbeddedServerTest.java | 56 ++++++++++++++-----
...ShiroIsisSecmanTest.java => ShiroLdapTest.java} | 56 +++++++++++++++----
...iroIsisSecmanTest.java => ShiroSecmanTest.java} | 50 ++++++++++++++---
.../smoketest/src/test/resources/shiro-ldap.ini | 64 ++++++++++++++++++++++
.../resources/{shiro-isis.ini => shiro-secman.ini} | 0
8 files changed, 201 insertions(+), 50 deletions(-)
diff --git a/examples/smoketest/log4j2-test.xml b/examples/smoketest/log4j2-test.xml
index 3cb094e..56e8ad6 100644
--- a/examples/smoketest/log4j2-test.xml
+++ b/examples/smoketest/log4j2-test.xml
@@ -23,6 +23,9 @@
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
+ <logger name="org.apache.directory" level="warn"/>
+ <logger name="org.apache.directory.api.ldap.model.entry.Value" level="off"/>
+
<logger name="DataNucleus.Persistence" level="info"/>
<logger name="DataNucleus.Transaction" level="info"/>
<logger name="DataNucleus.Datastore.Schema" level="info"/>
diff --git a/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule.java b/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule.java
index 7f05ca8..3a44b12 100644
--- a/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule.java
+++ b/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule.java
@@ -56,8 +56,8 @@ import org.springframework.context.annotation.PropertySources;
@PropertySource(name=Presets.H2InMemory, factory = Presets.Factory.class, value = { "" }),
@PropertySource(name=Presets.NoTranslations, factory = Presets.Factory.class, value = { "" }),
})
-//by default disable security specific config to be picked up by Spring
-@ConditionalOnProperty(value = "smoketest.withSecurity", havingValue = "false", matchIfMissing = true)
+//by default disable shiro specific config to be picked up by Spring
+@ConditionalOnProperty(value = "smoketest.withShiro", havingValue = "false", matchIfMissing = true)
public class JdoTestDomainModule {
@Bean @Singleton
diff --git a/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule_withSecurity.java b/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule_withShiro.java
similarity index 81%
rename from examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule_withSecurity.java
rename to examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule_withShiro.java
index b57c29d..76470b3 100644
--- a/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule_withSecurity.java
+++ b/examples/smoketest/src/main/java/org/apache/isis/testdomain/jdo/JdoTestDomainModule_withShiro.java
@@ -27,10 +27,6 @@ import org.apache.isis.extensions.fixtures.IsisBootFixtures;
import org.apache.isis.extensions.secman.api.SecurityModuleConfig;
import org.apache.isis.extensions.secman.api.permission.PermissionsEvaluationService;
import org.apache.isis.extensions.secman.api.permission.PermissionsEvaluationServiceAllowBeatsVeto;
-import org.apache.isis.extensions.secman.encryption.jbcrypt.IsisBootSecmanEncryptionJbcrypt;
-import org.apache.isis.extensions.secman.jdo.IsisBootSecmanPersistenceJdo;
-import org.apache.isis.extensions.secman.model.IsisBootSecmanModel;
-import org.apache.isis.extensions.secman.shiro.IsisBootSecmanRealmShiro;
import org.apache.isis.jdo.IsisBootDataNucleus;
import org.apache.isis.runtime.spring.IsisBoot;
import org.apache.isis.security.shiro.IsisBootSecurityShiro;
@@ -50,18 +46,12 @@ import org.springframework.context.annotation.PropertySources;
IsisBootSecurityShiro.class,
- // Security Manager Extension (secman)
- IsisBootSecmanModel.class,
- IsisBootSecmanRealmShiro.class,
- IsisBootSecmanPersistenceJdo.class,
- IsisBootSecmanEncryptionJbcrypt.class,
-
IsisBootDataNucleus.class,
IsisBootFixtures.class
})
@ComponentScan(
basePackageClasses= {
- JdoTestDomainModule_withSecurity.class
+ JdoTestDomainModule_withShiro.class
},
includeFilters= {
@Filter(type = FilterType.CUSTOM, classes= {IsisBeanScanInterceptorForSpring.class})
@@ -71,9 +61,9 @@ import org.springframework.context.annotation.PropertySources;
@PropertySource(name=Presets.H2InMemory, factory = Presets.Factory.class, value = { "" }),
@PropertySource(name=Presets.NoTranslations, factory = Presets.Factory.class, value = { "" }),
})
-// enable security specific config to be picked up by Spring
-@ConditionalOnProperty(value = "smoketest.withSecurity", havingValue = "true", matchIfMissing = false)
-public class JdoTestDomainModule_withSecurity {
+// enable shiro specific config to be picked up by Spring
+@ConditionalOnProperty(value = "smoketest.withShiro", havingValue = "true", matchIfMissing = false)
+public class JdoTestDomainModule_withShiro {
@Bean @Singleton
public WebAppConfigBean webAppConfigBean() {
diff --git a/examples/smoketest/src/test/java/org/apache/isis/testdomain/ldap/LdapEmbeddedServerTest.java b/examples/smoketest/src/test/java/org/apache/isis/testdomain/ldap/LdapEmbeddedServerTest.java
index 69a665d..2d658d8 100644
--- a/examples/smoketest/src/test/java/org/apache/isis/testdomain/ldap/LdapEmbeddedServerTest.java
+++ b/examples/smoketest/src/test/java/org/apache/isis/testdomain/ldap/LdapEmbeddedServerTest.java
@@ -18,7 +18,7 @@
*/
package org.apache.isis.testdomain.ldap;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.Hashtable;
@@ -26,28 +26,27 @@ import java.util.Hashtable;
import javax.inject.Inject;
import javax.naming.Context;
import javax.naming.InitialContext;
-import javax.naming.NameClassPair;
-import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import org.junit.jupiter.api.Test;
import org.junit.runners.model.InitializationError;
import org.springframework.boot.test.context.SpringBootTest;
+import lombok.val;
+
@SpringBootTest(
classes = {LdapServerService.class},
properties = {
"logging.config=log4j2-test.xml",
- "logging.level.org.apache.directory.api.ldap.model.entry.Value=OFF",
})
class LdapEmbeddedServerTest {
@Inject LdapServerService ldapServerService;
@Test
- void authenticateAgainstLdap() throws InitializationError, InterruptedException {
+ void authenticate_Sven() throws InitializationError, InterruptedException {
- Hashtable<String, String> env = new Hashtable<>();
+ val env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:" + LdapEmbeddedServer.PORT);
@@ -56,16 +55,47 @@ class LdapEmbeddedServerTest {
env.put(Context.SECURITY_CREDENTIALS, "pass");
try {
- Context ctx = new InitialContext(env);
- NamingEnumeration<NameClassPair> enm = ctx.list("");
+ val ctx = new InitialContext(env);
+ val namingEnumeration = ctx.list("");
+
+ int entryCount = 0;
+ while (namingEnumeration.hasMore()) {
+ namingEnumeration.next();
+ ++entryCount;
+ }
+ assertEquals(3, entryCount);
+
+ namingEnumeration.close();
+ ctx.close();
+ } catch (NamingException e) {
+ fail(e.getMessage());
+ }
+
+ }
+
+ @Test
+ void authenticate_Admin() throws InitializationError, InterruptedException {
+
+ val env = new Hashtable<String, String>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put(Context.PROVIDER_URL, "ldap://localhost:" + LdapEmbeddedServer.PORT);
+
+ env.put( Context.SECURITY_AUTHENTICATION, "simple" );
+ env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
+ env.put( Context.SECURITY_CREDENTIALS, "secret" );
+
+ try {
+ val ctx = new InitialContext(env);
+ val namingEnumeration = ctx.list("");
- assertTrue(enm.hasMore());
-
- while (enm.hasMore()) {
- System.out.println(enm.next());
+ int entryCount = 0;
+ while (namingEnumeration.hasMore()) {
+ namingEnumeration.next();
+ ++entryCount;
}
+ assertEquals(3, entryCount);
- enm.close();
+ namingEnumeration.close();
ctx.close();
} catch (NamingException e) {
fail(e.getMessage());
diff --git a/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroIsisSecmanTest.java b/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroLdapTest.java
similarity index 69%
copy from examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroIsisSecmanTest.java
copy to examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroLdapTest.java
index c2f1e72..6cbcf4a 100644
--- a/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroIsisSecmanTest.java
+++ b/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroLdapTest.java
@@ -23,8 +23,10 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import org.apache.isis.extensions.secman.jdo.seed.scripts.IsisModuleSecurityAdminUser;
-import org.apache.isis.testdomain.jdo.JdoTestDomainModule_withSecurity;
+import javax.inject.Inject;
+
+import org.apache.isis.testdomain.jdo.JdoTestDomainModule_withShiro;
+import org.apache.isis.testdomain.ldap.LdapServerService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
@@ -33,25 +35,33 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
import lombok.val;
+import lombok.extern.log4j.Log4j2;
@SpringBootTest(
classes = {
- JdoTestDomainModule_withSecurity.class,
+ JdoTestDomainModule_withShiro.class,
},
properties = {
"logging.config=log4j2-test.xml",
- "smoketest.withSecurity=true", // enable security specific config to be picked up by Spring
+ "smoketest.withShiro=true", // enable shiro specific config to be picked up by Spring
})
-class ShiroIsisSecmanTest extends AbstractShiroTest {
+@Import({
+ LdapServerService.class,
+})
+@Log4j2
+class ShiroLdapTest extends AbstractShiroTest {
+
+ @Inject LdapServerService ldapServerService;
@BeforeAll
static void beforeClass() {
//0. Build and set the SecurityManager used to build Subject instances used in your tests
// This typically only needs to be done once per class if your shiro.ini doesn't change,
// otherwise, you'll need to do this logic in each test that is different
- val factory = new IniSecurityManagerFactory("classpath:shiro-isis.ini");
+ val factory = new IniSecurityManagerFactory("classpath:shiro-ldap.ini");
setSecurityManager(factory.getInstance());
}
@@ -62,6 +72,8 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
@Test
void loginLogoutRoundtrip() {
+
+ log.info("starting login/logout roundtrip");
val secMan = SecurityUtils.getSecurityManager();
assertNotNull(secMan);
@@ -71,8 +83,8 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
assertFalse(subject.isAuthenticated());
val token = (AuthenticationToken) new UsernamePasswordToken(
- IsisModuleSecurityAdminUser.USER_NAME,
- IsisModuleSecurityAdminUser.PASSWORD);
+ "cn=Sven Tester,ou=Users,dc=myorg,dc=com",
+ "pass");
subject.login(token);
assertTrue(subject.isAuthenticated());
@@ -83,7 +95,29 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
}
@Test
- void invalidLogin() {
+ void login_withInvalidPassword() {
+
+ val secMan = SecurityUtils.getSecurityManager();
+ assertNotNull(secMan);
+
+ val subject = SecurityUtils.getSubject();
+ assertNotNull(subject);
+ assertFalse(subject.isAuthenticated());
+
+ val token = (AuthenticationToken) new UsernamePasswordToken(
+ "cn=Sven Tester,ou=Users,dc=myorg,dc=com",
+ "invalid-pass");
+
+ assertThrows(Exception.class, ()->{
+ subject.login(token);
+ });
+
+ assertFalse(subject.isAuthenticated());
+
+ }
+
+ @Test
+ void login_withNonExistentUser() {
val secMan = SecurityUtils.getSecurityManager();
assertNotNull(secMan);
@@ -94,7 +128,7 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
val token = (AuthenticationToken) new UsernamePasswordToken(
"non-existent-user",
- "pass");
+ "invalid-pass");
assertThrows(Exception.class, ()->{
subject.login(token);
@@ -105,7 +139,5 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
}
-
-
}
diff --git a/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroIsisSecmanTest.java b/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroSecmanTest.java
similarity index 67%
rename from examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroIsisSecmanTest.java
rename to examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroSecmanTest.java
index c2f1e72..0f0d64c 100644
--- a/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroIsisSecmanTest.java
+++ b/examples/smoketest/src/test/java/org/apache/isis/testdomain/shiro/ShiroSecmanTest.java
@@ -23,8 +23,12 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import org.apache.isis.extensions.secman.encryption.jbcrypt.IsisBootSecmanEncryptionJbcrypt;
+import org.apache.isis.extensions.secman.jdo.IsisBootSecmanPersistenceJdo;
import org.apache.isis.extensions.secman.jdo.seed.scripts.IsisModuleSecurityAdminUser;
-import org.apache.isis.testdomain.jdo.JdoTestDomainModule_withSecurity;
+import org.apache.isis.extensions.secman.model.IsisBootSecmanModel;
+import org.apache.isis.extensions.secman.shiro.IsisBootSecmanRealmShiro;
+import org.apache.isis.testdomain.jdo.JdoTestDomainModule_withShiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
@@ -33,25 +37,33 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
import lombok.val;
@SpringBootTest(
classes = {
- JdoTestDomainModule_withSecurity.class,
+ JdoTestDomainModule_withShiro.class,
},
properties = {
"logging.config=log4j2-test.xml",
- "smoketest.withSecurity=true", // enable security specific config to be picked up by Spring
+ "smoketest.withShiro=true", // enable shiro specific config to be picked up by Spring
})
-class ShiroIsisSecmanTest extends AbstractShiroTest {
+@Import({
+ // Security Manager Extension (secman)
+ IsisBootSecmanModel.class,
+ IsisBootSecmanRealmShiro.class,
+ IsisBootSecmanPersistenceJdo.class,
+ IsisBootSecmanEncryptionJbcrypt.class,
+})
+class ShiroSecmanTest extends AbstractShiroTest {
@BeforeAll
static void beforeClass() {
//0. Build and set the SecurityManager used to build Subject instances used in your tests
// This typically only needs to be done once per class if your shiro.ini doesn't change,
// otherwise, you'll need to do this logic in each test that is different
- val factory = new IniSecurityManagerFactory("classpath:shiro-isis.ini");
+ val factory = new IniSecurityManagerFactory("classpath:shiro-secman.ini");
setSecurityManager(factory.getInstance());
}
@@ -83,7 +95,29 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
}
@Test
- void invalidLogin() {
+ void login_withInvalidPassword() {
+
+ val secMan = SecurityUtils.getSecurityManager();
+ assertNotNull(secMan);
+
+ val subject = SecurityUtils.getSubject();
+ assertNotNull(subject);
+ assertFalse(subject.isAuthenticated());
+
+ val token = (AuthenticationToken) new UsernamePasswordToken(
+ IsisModuleSecurityAdminUser.USER_NAME,
+ "invalid-pass");
+
+ assertThrows(Exception.class, ()->{
+ subject.login(token);
+ });
+
+ assertFalse(subject.isAuthenticated());
+
+ }
+
+ @Test
+ void login_withNonExistentUser() {
val secMan = SecurityUtils.getSecurityManager();
assertNotNull(secMan);
@@ -94,7 +128,7 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
val token = (AuthenticationToken) new UsernamePasswordToken(
"non-existent-user",
- "pass");
+ "invalid-pass");
assertThrows(Exception.class, ()->{
subject.login(token);
@@ -105,7 +139,5 @@ class ShiroIsisSecmanTest extends AbstractShiroTest {
}
-
-
}
diff --git a/examples/smoketest/src/test/resources/shiro-ldap.ini b/examples/smoketest/src/test/resources/shiro-ldap.ini
new file mode 100644
index 0000000..02d1bb8
--- /dev/null
+++ b/examples/smoketest/src/test/resources/shiro-ldap.ini
@@ -0,0 +1,64 @@
+#
+# 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.
+#
+
+[main]
+
+contextFactory = org.apache.isis.security.shiro.IsisLdapContextFactory
+contextFactory.url = ldap://localhost:10389
+contextFactory.authenticationMechanism = simple
+contextFactory.systemAuthenticationMechanism = simple
+contextFactory.systemUsername = uid=admin,ou=system
+contextFactory.systemPassword = secret
+
+ldapRealm = org.apache.isis.security.shiro.IsisLdapRealm
+ldapRealm.contextFactory = $contextFactory
+
+ldapRealm.searchBase = ou=groups,o=mojo
+ldapRealm.groupObjectClass = groupOfUniqueNames
+ldapRealm.uniqueMemberAttribute = uniqueMember
+ldapRealm.uniqueMemberAttributeValueTemplate = uid={0}
+
+# optional mapping from physical groups to logical application roles
+ldapRealm.rolesByGroup = \
+ LDN_USERS: user_role,\
+ NYK_USERS: user_role,\
+ HKG_USERS: user_role,\
+ GLOBAL_ADMIN: admin_role,\
+ DEMOS: self-install_role
+
+ldapRealm.permissionsByRole=\
+ user_role = *:SimpleObjectMenu:*:*,\
+ *:SimpleObject:*:*; \
+ self-install_role = *:FixtureScriptsDefault:*:* ; \
+ admin_role = *
+
+securityManager.realms = $ldapRealm
+
+#authenticationStrategy=org.apache.isis.extensions.secman.shiro.AuthenticationStrategyForIsisModuleSecurityRealm
+#isisModuleSecurityRealm=org.apache.isis.extensions.secman.shiro.IsisModuleSecurityRealm
+
+#securityManager.authenticator.authenticationStrategy = $authenticationStrategy
+#securityManager.realms = $isisModuleSecurityRealm
+
+[users]
+[roles]
+
+
+
+
diff --git a/examples/smoketest/src/test/resources/shiro-isis.ini b/examples/smoketest/src/test/resources/shiro-secman.ini
similarity index 100%
rename from examples/smoketest/src/test/resources/shiro-isis.ini
rename to examples/smoketest/src/test/resources/shiro-secman.ini