| /** |
| * 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.activemq.shiro; |
| |
| import org.apache.activemq.broker.BrokerPlugin; |
| import org.apache.activemq.broker.BrokerService; |
| import org.apache.activemq.broker.MutableBrokerFilter; |
| import org.apache.activemq.shiro.authc.AuthenticationFilter; |
| import org.apache.activemq.shiro.authc.DefaultAuthenticationPolicy; |
| import org.apache.activemq.shiro.authz.AuthorizationFilter; |
| import org.apache.activemq.shiro.env.IniEnvironment; |
| import org.apache.activemq.shiro.subject.DefaultConnectionSubjectFactory; |
| import org.apache.activemq.shiro.subject.SubjectFilter; |
| import org.apache.activemq.test.JmsResourceProvider; |
| import org.apache.activemq.test.TestSupport; |
| import org.apache.shiro.authc.AuthenticationException; |
| import org.apache.shiro.config.Ini; |
| import org.apache.shiro.env.DefaultEnvironment; |
| import org.apache.shiro.env.Environment; |
| import org.apache.shiro.mgt.DefaultSecurityManager; |
| import org.apache.shiro.realm.text.IniRealm; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import javax.jms.Connection; |
| import javax.jms.ConnectionFactory; |
| import javax.jms.Destination; |
| import javax.jms.JMSException; |
| import javax.jms.MessageConsumer; |
| import javax.jms.MessageProducer; |
| import javax.jms.Session; |
| |
| /** |
| * @since 5.10.0 |
| */ |
| public class ShiroPluginTest extends TestSupport { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(ShiroPluginTest.class); |
| |
| protected BrokerService broker; |
| protected SecureJmsResourceProvider resourceProvider; |
| protected ConnectionFactory connectionFactory; |
| protected Connection connection; |
| protected Session session; |
| protected Destination destination; |
| protected MessageConsumer consumer; |
| protected MessageProducer producer; |
| |
| @Override |
| protected void setUp() throws Exception { |
| resourceProvider = new SecureJmsResourceProvider(); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| LOG.info("Shutting down broker..."); |
| |
| if (session != null) { |
| session.close(); |
| } |
| session = null; |
| |
| if (connection != null) { |
| connection.close(); |
| } |
| connection = null; |
| |
| if (broker != null) { |
| broker.stop(); |
| broker.waitUntilStopped(); |
| } |
| broker = null; |
| |
| LOG.info("Broker shut down."); |
| } |
| |
| protected void reconnect() throws Exception { |
| reconnect(null, null); |
| } |
| |
| protected void reconnect(String username, String password) throws Exception { |
| if (connection != null) { |
| // Close the prev connection. |
| connection.close(); |
| } |
| session = null; |
| if (username == null && password == null) { |
| connection = resourceProvider.createConnection(connectionFactory); |
| } else { |
| connection = resourceProvider.createConnection(connectionFactory, username, password); |
| } |
| reconnectSession(); |
| connection.start(); |
| } |
| |
| protected void reconnectSession() throws JMSException { |
| if (session != null) { |
| session.close(); |
| } |
| session = resourceProvider.createSession(connection); |
| destination = resourceProvider.createDestination(session, getSubject()); |
| producer = resourceProvider.createProducer(session, destination); |
| consumer = resourceProvider.createConsumer(session, destination); |
| } |
| |
| protected ConnectionFactory newConnectionFactory() throws Exception { |
| return resourceProvider.createConnectionFactory(); |
| } |
| |
| protected void start() throws Exception { |
| startBroker(); |
| topic = resourceProvider.isTopic(); |
| connectionFactory = newConnectionFactory(); |
| } |
| |
| protected void startBroker() throws Exception { |
| broker.start(); |
| broker.waitUntilStarted(); |
| } |
| |
| protected BrokerService createBroker(BrokerPlugin... plugins) throws Exception { |
| return createBroker(plugins, resourceProvider.getServerUri()); |
| } |
| |
| protected BrokerService createBroker(BrokerPlugin[] plugins, String... connectorUris) throws Exception { |
| BrokerService brokerService = new BrokerService(); |
| if (plugins != null && plugins.length > 0) { |
| brokerService.setPlugins(plugins); |
| } |
| if (connectorUris != null) { |
| for (String uri : connectorUris) { |
| brokerService.addConnector(uri); |
| } |
| } |
| return brokerService; |
| } |
| |
| protected ShiroPlugin createPlugin(String iniPath) { |
| Ini ini = Ini.fromResourcePath(iniPath); |
| Environment env = new IniEnvironment(ini); |
| ShiroPlugin plugin = new ShiroPlugin(); |
| plugin.setEnvironment(env); |
| return plugin; |
| } |
| |
| public void testNoEnvironmentOrSecurityManager() throws Exception { |
| //should build IniEnvironment from shiro.ini in the classpath at the least: |
| ShiroPlugin plugin = new ShiroPlugin(); |
| plugin.installPlugin(new MutableBrokerFilter(null)); |
| |
| Ini ini = Ini.fromResourcePath("classpath:shiro.ini"); |
| IniRealm realm = (IniRealm) ((DefaultSecurityManager) plugin.getEnvironment().getSecurityManager()).getRealms().iterator().next(); |
| assertEquals(ini, realm.getIni()); |
| } |
| |
| public void testSetIni() throws Exception { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| Ini ini = Ini.fromResourcePath("classpath:minimal.shiro.ini"); |
| plugin.setIni(ini); |
| plugin.installPlugin(new MutableBrokerFilter(null)); |
| |
| IniRealm realm = (IniRealm) ((DefaultSecurityManager) plugin.getEnvironment().getSecurityManager()).getRealms().iterator().next(); |
| assertSame(ini, realm.getIni()); |
| } |
| |
| public void testSetIniString() throws Exception { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| plugin.setIniConfig( |
| "[users]\n" + |
| "system = manager, system\n" + |
| "[roles]\n" + |
| "system = *"); |
| plugin.installPlugin(new MutableBrokerFilter(null)); |
| |
| IniRealm realm = (IniRealm) ((DefaultSecurityManager) plugin.getEnvironment().getSecurityManager()).getRealms().iterator().next(); |
| Ini ini = realm.getIni(); |
| assertEquals(1, ini.getSection("users").size()); |
| assertEquals("manager, system", ini.getSection("users").get("system")); |
| assertEquals(1, ini.getSection("roles").size()); |
| assertEquals("*", ini.getSection("roles").get("system")); |
| } |
| |
| public void testSetIniResourcePath() throws Exception { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| |
| String path = "classpath:minimal.shiro.ini"; |
| |
| plugin.setIniResourcePath(path); |
| plugin.installPlugin(new MutableBrokerFilter(null)); |
| |
| Ini ini = Ini.fromResourcePath(path); |
| |
| IniRealm realm = (IniRealm) ((DefaultSecurityManager) plugin.getEnvironment().getSecurityManager()).getRealms().iterator().next(); |
| assertEquals(ini, realm.getIni()); |
| } |
| |
| public void testSetSubjectFilter() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| SubjectFilter filter = new SubjectFilter(); |
| plugin.setSubjectFilter(filter); |
| assertSame(filter, plugin.getSubjectFilter()); |
| //assert that the AuthenticationFilter is always the next filter in the chain after the SubjectFilter: |
| assertSame(plugin.getAuthenticationFilter(), filter.getNext()); |
| } |
| |
| public void testSetAuthenticationFilter() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| AuthenticationFilter filter = new AuthenticationFilter(); |
| plugin.setAuthenticationFilter(filter); |
| assertSame(filter, plugin.getAuthenticationFilter()); |
| //assert that the AuthenticationFilter is always the next filter in the chain after the SubjectFilter: |
| assertSame(plugin.getSubjectFilter().getNext(), filter); |
| } |
| |
| public void testSetAuthorizationFilter() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| AuthorizationFilter filter = new AuthorizationFilter(); |
| plugin.setAuthorizationFilter(filter); |
| assertSame(filter, plugin.getAuthorizationFilter()); |
| //assert that the AuthenticationFilter is always the next filter in the chain after the AuthenticationFilter: |
| assertSame(plugin.getAuthenticationFilter().getNext(), filter); |
| } |
| |
| public void testSetEnvironment() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| Environment env = new DefaultEnvironment(); |
| plugin.setEnvironment(env); |
| assertSame(env, plugin.getEnvironment()); |
| } |
| |
| public void testSetSecurityManager() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| org.apache.shiro.mgt.SecurityManager securityManager = new DefaultSecurityManager(); |
| plugin.setSecurityManager(securityManager); |
| assertSame(securityManager, plugin.getSecurityManager()); |
| } |
| |
| public void testSecurityManagerWhenInstalled() throws Exception { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| org.apache.shiro.mgt.SecurityManager securityManager = new DefaultSecurityManager(); |
| plugin.setSecurityManager(securityManager); |
| |
| assertNull(plugin.getEnvironment()); //we will auto-create one when only a sm is provided |
| |
| plugin.installPlugin(new MutableBrokerFilter(null)); |
| |
| assertSame(securityManager, plugin.getSecurityManager()); |
| assertNotNull(plugin.getEnvironment()); |
| assertSame(securityManager, plugin.getEnvironment().getSecurityManager()); |
| } |
| |
| public void testEnabledWhenNotInstalled() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| assertTrue(plugin.isEnabled()); //enabled by default |
| |
| plugin.setEnabled(false); |
| assertFalse(plugin.isEnabled()); |
| |
| plugin.setEnabled(true); |
| assertTrue(plugin.isEnabled()); |
| } |
| |
| public void testEnabledWhenInstalled() throws Exception { |
| ShiroPlugin plugin = createPlugin("classpath:minimal.shiro.ini"); |
| this.broker = createBroker(plugin); |
| start(); |
| assertTrue(plugin.isEnabled()); |
| |
| plugin.setEnabled(false); |
| assertFalse(plugin.isEnabled()); |
| |
| plugin.setEnabled(true); |
| assertTrue(plugin.isEnabled()); |
| } |
| |
| public void testAuthenticationEnabledWhenNotInstalled() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| assertTrue(plugin.isAuthenticationEnabled()); |
| |
| plugin.setAuthenticationEnabled(false); |
| assertFalse(plugin.isAuthenticationEnabled()); |
| |
| plugin.setAuthenticationEnabled(true); |
| assertTrue(plugin.isAuthenticationEnabled()); |
| } |
| |
| public void testAuthenticationEnabledWhenInstalled() throws Exception { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| plugin.setEnvironment(new DefaultEnvironment()); |
| plugin.installPlugin(new MutableBrokerFilter(null)); |
| |
| assertTrue(plugin.isAuthenticationEnabled()); |
| |
| plugin.setAuthenticationEnabled(false); |
| assertFalse(plugin.isAuthenticationEnabled()); |
| |
| plugin.setAuthenticationEnabled(true); |
| assertTrue(plugin.isAuthenticationEnabled()); |
| } |
| |
| public void testSetAuthenticationPolicy() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| DefaultAuthenticationPolicy policy = new DefaultAuthenticationPolicy(); |
| plugin.setAuthenticationPolicy(policy); |
| assertSame(policy, plugin.getAuthenticationPolicy()); |
| assertSame(policy, plugin.getAuthenticationFilter().getAuthenticationPolicy()); |
| assertSame(policy, ((DefaultConnectionSubjectFactory) plugin.getSubjectFilter().getConnectionSubjectFactory()).getAuthenticationPolicy()); |
| } |
| |
| public void testAuthorizationEnabledWhenNotInstalled() { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| assertTrue(plugin.isAuthorizationEnabled()); |
| |
| plugin.setAuthorizationEnabled(false); |
| assertFalse(plugin.isAuthorizationEnabled()); |
| |
| plugin.setAuthorizationEnabled(true); |
| assertTrue(plugin.isAuthorizationEnabled()); |
| } |
| |
| public void testAuthorizationEnabledWhenInstalled() throws Exception { |
| ShiroPlugin plugin = new ShiroPlugin(); |
| plugin.setEnvironment(new DefaultEnvironment()); |
| plugin.installPlugin(new MutableBrokerFilter(null)); |
| |
| assertTrue(plugin.isAuthorizationEnabled()); |
| |
| plugin.setAuthorizationEnabled(false); |
| assertFalse(plugin.isAuthorizationEnabled()); |
| |
| plugin.setAuthorizationEnabled(true); |
| assertTrue(plugin.isAuthorizationEnabled()); |
| } |
| |
| |
| public void testSimple() throws Exception { |
| ShiroPlugin plugin = createPlugin("classpath:minimal.shiro.ini"); |
| this.broker = createBroker(plugin); |
| start(); |
| reconnect(); |
| } |
| |
| public void testDisabled() throws Exception { |
| ShiroPlugin plugin = createPlugin("classpath:nosystem.shiro.ini"); |
| plugin.setEnabled(false); |
| this.broker = createBroker(plugin); |
| start(); |
| } |
| |
| public void testRuntimeDisableEnableChanges() throws Exception { |
| ShiroPlugin plugin = createPlugin("classpath:nosystem.shiro.ini"); |
| ((DefaultAuthenticationPolicy) plugin.getAuthenticationPolicy()).setVmConnectionAuthenticationRequired(true); |
| plugin.setEnabled(false); |
| this.broker = createBroker(plugin); |
| start(); |
| |
| //connection has no credentials. When disabled, this should succeed: |
| reconnect(); |
| |
| //now enable the plugin and assert that credentials are required: |
| plugin.setEnabled(true); |
| |
| try { |
| reconnect(); |
| fail("Connections without passwords in this configuration should fail."); |
| } catch (JMSException expected) { |
| assertTrue(expected.getCause() instanceof AuthenticationException); |
| } |
| |
| //this should work now that we're authenticating: |
| reconnect("foo", "bar"); |
| } |
| |
| static class SecureJmsResourceProvider extends JmsResourceProvider { |
| |
| /** |
| * Creates a connection, authenticating with the specified username and password. |
| * |
| * @see org.apache.activemq.test.JmsResourceProvider#createConnection(javax.jms.ConnectionFactory) |
| */ |
| public Connection createConnection(ConnectionFactory cf, String username, String password) throws JMSException { |
| Connection connection = cf.createConnection(username, password); |
| if (getClientID() != null) { |
| connection.setClientID(getClientID()); |
| } |
| return connection; |
| } |
| } |
| } |