You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2018/04/16 22:45:06 UTC

[02/38] tomee git commit: small quick and dirty test

small quick and dirty test


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/d56dc9e9
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/d56dc9e9
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/d56dc9e9

Branch: refs/heads/master
Commit: d56dc9e98bc0db270413bbd553b1f13ef3a60b7c
Parents: e55b4dc
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Tue Feb 20 09:30:07 2018 +0100
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Tue Feb 20 09:30:07 2018 +0100

----------------------------------------------------------------------
 .../openejb/core/security/JwtSecurityTest.java  | 363 +++++++++++++++++++
 1 file changed, 363 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/d56dc9e9/container/openejb-core/src/test/java/org/apache/openejb/core/security/JwtSecurityTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/core/security/JwtSecurityTest.java b/container/openejb-core/src/test/java/org/apache/openejb/core/security/JwtSecurityTest.java
new file mode 100644
index 0000000..8708074
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/core/security/JwtSecurityTest.java
@@ -0,0 +1,363 @@
+/**
+ * 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.openejb.core.security;
+
+import org.apache.openejb.OpenEJB;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.EjbJarInfo;
+import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.StatelessSessionContainerInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.core.LocalInitialContextFactory;
+import org.apache.openejb.core.security.jaas.GroupPrincipal;
+import org.apache.openejb.core.security.jaas.UserPrincipal;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.StatelessBean;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import javax.annotation.Resource;
+import javax.annotation.security.DeclareRoles;
+import javax.annotation.security.DenyAll;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+import javax.annotation.security.RunAs;
+import javax.ejb.SessionContext;
+import javax.ejb.Singleton;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import java.security.Security;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.testng.AssertJUnit.assertFalse;
+
+public class JWTSecurityTest {
+
+    @AfterClass
+    public static void afterClass() throws Exception {
+        OpenEJB.destroy();
+        System.clearProperty(Context.INITIAL_CONTEXT_FACTORY);
+        Security.setProperty("login.configuration.provider", null);
+    }
+
+    private Assembler configureAssembler(final String defaultUser) throws Exception {
+        System.setProperty(Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName());
+        Security.setProperty("login.configuration.provider", JaasConfig.class.getName());
+
+        final ConfigurationFactory config = new ConfigurationFactory();
+        final Assembler assembler = new Assembler();
+
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+
+        final SecurityServiceInfo serviceInfo = new SecurityServiceInfo();
+        serviceInfo.service = "SecurityService";
+        serviceInfo.className = SecurityServiceImpl.class.getName();
+        serviceInfo.id = "New Security Service";
+        serviceInfo.properties = new Properties();
+        if (defaultUser != null) {
+            // override the default user
+            serviceInfo.properties.setProperty("DefaultUser", defaultUser);
+
+        }
+
+        assembler.createSecurityService(serviceInfo);
+
+        // containers
+        assembler.createContainer(config.configureService(StatelessSessionContainerInfo.class));
+
+        final EjbJar ejbJar = new EjbJar("JwtTest");
+
+        ejbJar.addEnterpriseBean(new StatelessBean(FooBean.class));
+        ejbJar.addEnterpriseBean(new StatelessBean(BarBean.class));
+
+        final EjbJarInfo ejbJarInfo = config.configureApplication(ejbJar);
+
+        assembler.createApplication(ejbJarInfo);
+
+        return assembler;
+    }
+
+    @Test
+    public void test() throws Exception {
+        final Assembler assembler = configureAssembler(null);
+
+        final Properties props = new Properties();
+        props.setProperty("openejb.authentication.realmName", "jwt-realm");
+        props.setProperty(Context.SECURITY_PRINCIPAL, JWTUtil.createValidJwtAccessToken("committer", "community"));
+        props.setProperty(Context.SECURITY_CREDENTIALS, "");
+
+        final InitialContext ctx = new InitialContext(props);
+
+        final Project foo = (Project) ctx.lookup("FooBeanLocal");
+
+        foo.svnCheckout("");
+        foo.svnCommit("");
+
+        try {
+            foo.deleteProject("");
+            fail("Should not be allowed");
+        } catch (final Exception e) {
+            // good.
+        }
+
+        assertTrue("not in role committer", foo.isCallerInRole("committer"));
+        assertTrue("not in role community", foo.isCallerInRole("community"));
+        assertFalse("in role contributor", foo.isCallerInRole("contributor"));
+        assertTrue("Caller is not jonathan", foo.isCaller("jonathan"));
+
+        ctx.close();
+        assembler.destroy();
+    }
+
+    // When no credentials are provided, the default user/role should be "guest"
+    @Test
+    public void testUnauthenticatedUser() throws Exception {
+        final Assembler assembler = configureAssembler(null);
+
+        // no credentials provided, the default user should be "guest"
+        final Properties props = new Properties();
+
+        final InitialContext ctx = new InitialContext(props);
+
+        final Project foo = (Project) ctx.lookup("FooBeanLocal");
+
+        foo.svnCheckout("");
+        try {
+            foo.svnCommit("");
+            fail("Should not be allowed");
+        } catch (final Exception e) {
+            // good.
+        }
+
+        assertFalse("in role committer", foo.isCallerInRole("committer"));
+        assertFalse("in role community", foo.isCallerInRole("community"));
+        assertFalse("in role contributor", foo.isCallerInRole("contributor"));
+        assertTrue("not in role guest", foo.isCallerInRole("guest"));
+        assertTrue("Caller is not guest", foo.isCaller("guest"));
+
+        ctx.close();
+        assembler.destroy();
+    }
+
+    // Just to be sure we can override the default user (ie. guest)
+    @Test
+    public void testDefaultUser() throws Exception {
+        final Assembler assembler = configureAssembler("public");
+
+        // no credentials provided, the default user should be "guest"
+        final Properties props = new Properties();
+
+        final InitialContext ctx = new InitialContext(props);
+
+        final Project foo = (Project) ctx.lookup("FooBeanLocal");
+
+        foo.svnCheckout("");
+        try {
+            foo.svnCommit("");
+            fail("Should not be allowed");
+        } catch (final Exception e) {
+            // good.
+        }
+
+        assertFalse("in role committer", foo.isCallerInRole("committer"));
+        assertFalse("in role community", foo.isCallerInRole("community"));
+        assertFalse("in role contributor", foo.isCallerInRole("contributor"));
+        assertFalse("in role guest", foo.isCallerInRole("guest"));
+        assertTrue("Caller is not public", foo.isCaller("public"));
+
+        ctx.close();
+        assembler.destroy();
+    }
+
+    @Singleton
+    @DeclareRoles({"committer", "contributor", "community", "guest", "public"})
+    public static class FooBean implements Project {
+
+        @Resource
+        private SessionContext context;
+
+        @Override
+        @RolesAllowed({"committer"})
+        public String svnCommit(final String s) {
+            return s;
+        }
+
+        @Override
+        @RolesAllowed({"committer", "contributor"})
+        public String submitPatch(final String s) {
+            return s;
+        }
+
+        @Override
+        @PermitAll
+        public String svnCheckout(final String s) {
+            return s;
+        }
+
+        @Override
+        @DenyAll
+        public String deleteProject(final String s) {
+            return s;
+        }
+
+        @Override
+        public boolean isCallerInRole(final String role) {
+            return context.isCallerInRole(role);
+        }
+
+        @Override
+        public boolean isCaller(final String user) {
+            return context.getCallerPrincipal().getName().equals(user);
+        }
+    }
+
+    @Singleton
+    @RunAs("contributor")
+    @DeclareRoles({"committer", "contributor", "community"})
+    public static class BarBean implements Project {
+
+        @Resource
+        private SessionContext context;
+
+        @Override
+        @RolesAllowed({"committer"})
+        public String svnCommit(final String s) {
+            return s;
+        }
+
+        @Override
+        @RolesAllowed({"committer", "contributor"})
+        public String submitPatch(final String s) {
+            return s;
+        }
+
+        @Override
+        @PermitAll
+        public String svnCheckout(final String s) {
+            return s;
+        }
+
+        @Override
+        @DenyAll
+        public String deleteProject(final String s) {
+            return s;
+        }
+
+        @Override
+        @PermitAll
+        public boolean isCallerInRole(final String role) {
+            return context.isCallerInRole(role);
+        }
+
+        @Override
+        @PermitAll
+        public boolean isCaller(final String user) {
+            return context.getCallerPrincipal().getName().equals(user);
+        }
+    }
+
+    public interface Project {
+
+        String svnCommit(String s);
+
+        String submitPatch(String s);
+
+        String svnCheckout(String s);
+
+        String deleteProject(String s);
+
+        boolean isCaller(String s);
+
+        boolean isCallerInRole(String s);
+    }
+
+    public static class JaasConfig extends Configuration {
+
+        @Override
+        public AppConfigurationEntry[] getAppConfigurationEntry(final String name) {
+            final Set<AppConfigurationEntry> entries = new HashSet<AppConfigurationEntry>();
+
+            final Map<String, Object> options = new HashMap<String, Object>();
+
+            entries.add(new AppConfigurationEntry(
+                    JWTLoginModule.class.getName(),
+                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+                    options
+            ));
+            return entries.toArray(new AppConfigurationEntry[entries.size()]);
+        }
+    }
+
+    public static class JWTLoginModule implements LoginModule {
+
+        private Subject subject;
+        private CallbackHandler callbackHandler;
+        private Map<String, ?> sharedState;
+        private Map<String, ?> options;
+
+        @Override
+        public void initialize(final Subject subject, final CallbackHandler callbackHandler, final Map<String, ?> sharedState, final Map<String, ?> options) {
+            this.subject = subject;
+            this.callbackHandler = callbackHandler;
+            this.sharedState = sharedState;
+            this.options = options;
+            System.out.println("JWTLoginModule.initialize");
+        }
+
+        @Override
+        public boolean login() throws LoginException {
+            System.out.println("JWTLoginModule.login");
+            subject.getPrincipals().add(new UserPrincipal("jonathan"));
+            subject.getPrincipals().add(new GroupPrincipal("committer"));
+            subject.getPrincipals().add(new GroupPrincipal("community"));
+            return true;
+        }
+
+        @Override
+        public boolean commit() throws LoginException {
+            System.out.println("JWTLoginModule.commit");
+            return true;
+        }
+
+        @Override
+        public boolean abort() throws LoginException {
+            System.out.println("JWTLoginModule.abort");
+            return true;
+        }
+
+        @Override
+        public boolean logout() throws LoginException {
+            System.out.println("JWTLoginModule.logout");
+            return true;
+        }
+    }
+}