From 6bd30e8fe34066fa02ff253e4f71781cc12c2278 Mon Sep 17 00:00:00 2001 From: Justin Bertram Date: Wed, 14 Jul 2021 14:26:19 -0500 Subject: [PATCH] ARTEMIS-3385 management changes can be reverted by XML update Durable changes made via the management API (e.g. adding security-settings, adding address-settings, adding diverts) can be reverted when reloading the XML at runtime. --- .../core/server/impl/ActiveMQServerImpl.java | 36 ++- .../tests/integration/jms/RedeployTest.java | 231 ++++++++++++++++++ .../reload-address-settings-updated.xml | 59 +++++ .../resources/reload-address-settings.xml | 59 +++++ .../test/resources/reload-diverts-updated.xml | 64 +++++ .../src/test/resources/reload-diverts.xml | 64 +++++ .../reload-security-settings-updated.xml | 62 +++++ .../resources/reload-security-settings.xml | 62 +++++ 8 files changed, 625 insertions(+), 12 deletions(-) create mode 100644 tests/integration-tests/src/test/resources/reload-address-settings-updated.xml create mode 100644 tests/integration-tests/src/test/resources/reload-address-settings.xml create mode 100644 tests/integration-tests/src/test/resources/reload-diverts-updated.xml create mode 100644 tests/integration-tests/src/test/resources/reload-diverts.xml create mode 100644 tests/integration-tests/src/test/resources/reload-security-settings-updated.xml create mode 100644 tests/integration-tests/src/test/resources/reload-security-settings.xml diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java index 0dbd005259..740c3f7b8d 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java @@ -3590,18 +3590,23 @@ public class ActiveMQServerImpl implements ActiveMQServer { * @throws Exception */ private void recoverStoredConfigs() throws Exception { + recoverStoredAddressSettings(); + recoverStoredSecuritySettings(); + } + + private void recoverStoredSecuritySettings() throws Exception { + List roles = storageManager.recoverSecuritySettings(); + for (PersistedSecuritySetting roleItem : roles) { + Set setRoles = SecurityFormatter.createSecurity(roleItem.getSendRoles(), roleItem.getConsumeRoles(), roleItem.getCreateDurableQueueRoles(), roleItem.getDeleteDurableQueueRoles(), roleItem.getCreateNonDurableQueueRoles(), roleItem.getDeleteNonDurableQueueRoles(), roleItem.getManageRoles(), roleItem.getBrowseRoles(), roleItem.getCreateAddressRoles(), roleItem.getDeleteAddressRoles()); + securityRepository.addMatch(roleItem.getAddressMatch().toString(), setRoles); + } + } + + private void recoverStoredAddressSettings() throws Exception { List adsettings = storageManager.recoverAddressSettings(); for (PersistedAddressSetting set : adsettings) { addressSettingsRepository.addMatch(set.getAddressMatch().toString(), set.getSetting()); } - - List roles = storageManager.recoverSecuritySettings(); - - for (PersistedSecuritySetting roleItem : roles) { - Set setRoles = SecurityFormatter.createSecurity(roleItem.getSendRoles(), roleItem.getConsumeRoles(), roleItem.getCreateDurableQueueRoles(), roleItem.getDeleteDurableQueueRoles(), roleItem.getCreateNonDurableQueueRoles(), roleItem.getDeleteNonDurableQueueRoles(), roleItem.getManageRoles(), roleItem.getBrowseRoles(), roleItem.getCreateAddressRoles(), roleItem.getDeleteAddressRoles()); - - securityRepository.addMatch(roleItem.getAddressMatch().toString(), setRoles); - } } @Override @@ -4064,6 +4069,14 @@ public class ActiveMQServerImpl implements ActiveMQServer { } private void deployDiverts() throws Exception { + recoverStoredDiverts(); + //deploy the configured diverts + for (DivertConfiguration config : configuration.getDivertConfigurations()) { + deployDivert(config); + } + } + + private void recoverStoredDiverts() throws Exception { if (storageManager.recoverDivertConfigurations() != null) { for (PersistedDivertConfiguration persistedDivertConfiguration : storageManager.recoverDivertConfigurations()) { @@ -4079,10 +4092,6 @@ public class ActiveMQServerImpl implements ActiveMQServer { } } } - //deploy the configured diverts - for (DivertConfiguration config : configuration.getDivertConfigurations()) { - deployDivert(config); - } } private void deployGroupingHandlerConfiguration(final GroupingHandlerConfiguration config) throws Exception { @@ -4316,9 +4325,11 @@ public class ActiveMQServerImpl implements ActiveMQServer { if (configurationReloadDeployed.compareAndSet(false, true)) { ActiveMQServerLogger.LOGGER.reloadingConfiguration("security"); securityRepository.swap(configuration.getSecurityRoles().entrySet()); + recoverStoredSecuritySettings(); ActiveMQServerLogger.LOGGER.reloadingConfiguration("address settings"); addressSettingsRepository.swap(configuration.getAddressesSettings().entrySet()); + recoverStoredAddressSettings(); ActiveMQServerLogger.LOGGER.reloadingConfiguration("diverts"); final Set divertsToRemove = postOffice.getAllBindings() @@ -4338,6 +4349,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { logger.warn("Divert " + divertName + " could not be removed", e); } } + recoverStoredDiverts(); ActiveMQServerLogger.LOGGER.reloadingConfiguration("addresses"); undeployAddressesAndQueueNotInConfiguration(configuration); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java index c868c8a4b3..2541e1b03e 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java @@ -197,6 +197,237 @@ public class RedeployTest extends ActiveMQTestBase { } } + @Test + public void testRedeploySecuritySettings() throws Exception { + Path brokerXML = getTestDirfile().toPath().resolve("broker.xml"); + URL url1 = RedeployTest.class.getClassLoader().getResource("reload-security-settings.xml"); + URL url2 = RedeployTest.class.getClassLoader().getResource("reload-security-settings-updated.xml"); + Files.copy(url1.openStream(), brokerXML); + + EmbeddedActiveMQ embeddedActiveMQ = new EmbeddedActiveMQ(); + embeddedActiveMQ.setConfigResourcePath(brokerXML.toUri().toString()); + embeddedActiveMQ.start(); + + final ReusableLatch latch = new ReusableLatch(1); + + Runnable tick = new Runnable() { + @Override + public void run() { + latch.countDown(); + } + }; + + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + + try { + latch.await(10, TimeUnit.SECONDS); + + Set roles = embeddedActiveMQ.getActiveMQServer().getSecurityRepository().getMatch("foo"); + boolean found = false; + for (Role role : roles) { + if (role.getName().equals("a")) { + found = true; + } + } + + assertTrue(found); + + Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING); + brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000); + latch.setCount(1); + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + latch.await(10, TimeUnit.SECONDS); + + roles = embeddedActiveMQ.getActiveMQServer().getSecurityRepository().getMatch("foo"); + found = false; + for (Role role : roles) { + if (role.getName().equals("b")) { + found = true; + } + } + + assertTrue(found); + + } finally { + embeddedActiveMQ.stop(); + } + } + + @Test + public void testRedeploySecuritySettingsWithManagementChange() throws Exception { + Path brokerXML = getTestDirfile().toPath().resolve("broker.xml"); + URL url1 = RedeployTest.class.getClassLoader().getResource("reload-security-settings.xml"); + URL url2 = RedeployTest.class.getClassLoader().getResource("reload-security-settings-updated.xml"); + Files.copy(url1.openStream(), brokerXML); + + EmbeddedActiveMQ embeddedActiveMQ = new EmbeddedActiveMQ(); + embeddedActiveMQ.setConfigResourcePath(brokerXML.toUri().toString()); + embeddedActiveMQ.start(); + + final ReusableLatch latch = new ReusableLatch(1); + + Runnable tick = new Runnable() { + @Override + public void run() { + latch.countDown(); + } + }; + + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + + try { + latch.await(10, TimeUnit.SECONDS); + + Set roles = embeddedActiveMQ.getActiveMQServer().getSecurityRepository().getMatch("foo"); + boolean found = false; + for (Role role : roles) { + if (role.getName().equals("a")) { + found = true; + } + } + + assertTrue(found); + + embeddedActiveMQ.getActiveMQServer().getActiveMQServerControl().addSecuritySettings("bar", "c", "c", "c", "c", "c", "c", "c", "c", "c", "c"); + roles = embeddedActiveMQ.getActiveMQServer().getSecurityRepository().getMatch("bar"); + for (Role role : roles) { + if (role.getName().equals("c")) { + found = true; + } + } + + assertTrue(found); + + Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING); + brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000); + latch.setCount(1); + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + latch.await(10, TimeUnit.SECONDS); + + roles = embeddedActiveMQ.getActiveMQServer().getSecurityRepository().getMatch("foo"); + found = false; + for (Role role : roles) { + if (role.getName().equals("b")) { + found = true; + } + } + + assertTrue(found); + + roles = embeddedActiveMQ.getActiveMQServer().getSecurityRepository().getMatch("bar"); + found = false; + for (Role role : roles) { + if (role.getName().equals("c")) { + found = true; + } + } + + assertTrue(found); + + } finally { + embeddedActiveMQ.stop(); + } + } + + @Test + public void testRedeployAddressSettingsWithManagementChange() throws Exception { + Path brokerXML = getTestDirfile().toPath().resolve("broker.xml"); + URL url1 = RedeployTest.class.getClassLoader().getResource("reload-address-settings.xml"); + URL url2 = RedeployTest.class.getClassLoader().getResource("reload-address-settings-updated.xml"); + Files.copy(url1.openStream(), brokerXML); + + EmbeddedActiveMQ embeddedActiveMQ = new EmbeddedActiveMQ(); + embeddedActiveMQ.setConfigResourcePath(brokerXML.toUri().toString()); + embeddedActiveMQ.start(); + + final ReusableLatch latch = new ReusableLatch(1); + + Runnable tick = new Runnable() { + @Override + public void run() { + latch.countDown(); + } + }; + + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + + try { + latch.await(10, TimeUnit.SECONDS); + + AddressSettings addressSettings = embeddedActiveMQ.getActiveMQServer().getAddressSettingsRepository().getMatch("foo"); + assertEquals("a", addressSettings.getDeadLetterAddress().toString()); + + embeddedActiveMQ.getActiveMQServer().getActiveMQServerControl().addAddressSettings("bar", "c", null, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false, null, 0, 0, null, false, false, false, false); + addressSettings = embeddedActiveMQ.getActiveMQServer().getAddressSettingsRepository().getMatch("bar"); + assertEquals("c", addressSettings.getDeadLetterAddress().toString()); + + Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING); + brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000); + latch.setCount(1); + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + latch.await(10, TimeUnit.SECONDS); + + addressSettings = embeddedActiveMQ.getActiveMQServer().getAddressSettingsRepository().getMatch("foo"); + assertEquals("b", addressSettings.getDeadLetterAddress().toString()); + + addressSettings = embeddedActiveMQ.getActiveMQServer().getAddressSettingsRepository().getMatch("bar"); + assertEquals("c", addressSettings.getDeadLetterAddress().toString()); + + } finally { + embeddedActiveMQ.stop(); + } + } + + @Test + public void testRedeployDivertsWithManagementChange() throws Exception { + Path brokerXML = getTestDirfile().toPath().resolve("broker.xml"); + URL url1 = RedeployTest.class.getClassLoader().getResource("reload-diverts.xml"); + URL url2 = RedeployTest.class.getClassLoader().getResource("reload-diverts-updated.xml"); + Files.copy(url1.openStream(), brokerXML); + + EmbeddedActiveMQ embeddedActiveMQ = new EmbeddedActiveMQ(); + embeddedActiveMQ.setConfigResourcePath(brokerXML.toUri().toString()); + embeddedActiveMQ.start(); + + final ReusableLatch latch = new ReusableLatch(1); + + Runnable tick = new Runnable() { + @Override + public void run() { + latch.countDown(); + } + }; + + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + + try { + latch.await(10, TimeUnit.SECONDS); + + DivertBinding divertBinding = (DivertBinding) embeddedActiveMQ.getActiveMQServer().getPostOffice().getBinding(new SimpleString("a")); + assertNotNull(divertBinding); + assertEquals("a", divertBinding.getDivert().getAddress().toString()); + + embeddedActiveMQ.getActiveMQServer().getActiveMQServerControl().createDivert("c", "c", "c", "target", false, null, null); + + Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING); + brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000); + latch.setCount(1); + embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick); + latch.await(10, TimeUnit.SECONDS); + + divertBinding = (DivertBinding) embeddedActiveMQ.getActiveMQServer().getPostOffice().getBinding(new SimpleString("b")); + assertNotNull(divertBinding); + assertEquals("b", divertBinding.getDivert().getAddress().toString()); + + divertBinding = (DivertBinding) embeddedActiveMQ.getActiveMQServer().getPostOffice().getBinding(new SimpleString("c")); + assertNotNull(divertBinding); + assertEquals("c", divertBinding.getDivert().getAddress().toString()); + + } finally { + embeddedActiveMQ.stop(); + } + } + @Test public void testRedeployFilter() throws Exception { Path brokerXML = getTestDirfile().toPath().resolve("broker.xml"); diff --git a/tests/integration-tests/src/test/resources/reload-address-settings-updated.xml b/tests/integration-tests/src/test/resources/reload-address-settings-updated.xml new file mode 100644 index 0000000000..de99e51119 --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-address-settings-updated.xml @@ -0,0 +1,59 @@ + + + + + + + + 0.0.0.0 + + 100 + + true + + false + + + NIO + + ./target/data/paging + + ./target/data/bindings + + ./target/data/journal + + ./target/data/large-messages + + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + + + + b + + + + diff --git a/tests/integration-tests/src/test/resources/reload-address-settings.xml b/tests/integration-tests/src/test/resources/reload-address-settings.xml new file mode 100644 index 0000000000..57c0be76f8 --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-address-settings.xml @@ -0,0 +1,59 @@ + + + + + + + + 0.0.0.0 + + 100 + + true + + false + + + NIO + + ./target/data/paging + + ./target/data/bindings + + ./target/data/journal + + ./target/data/large-messages + + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + + + + a + + + + diff --git a/tests/integration-tests/src/test/resources/reload-diverts-updated.xml b/tests/integration-tests/src/test/resources/reload-diverts-updated.xml new file mode 100644 index 0000000000..4afc44f320 --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-diverts-updated.xml @@ -0,0 +1,64 @@ + + + + + + + + 0.0.0.0 + + 100 + + true + + false + + NIO + + ./target/data/paging + + ./target/data/bindings + + ./target/data/journal + + ./target/data/large-messages + + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + +
+
+
+
+ + + + +
b
+ target +
+
+ + diff --git a/tests/integration-tests/src/test/resources/reload-diverts.xml b/tests/integration-tests/src/test/resources/reload-diverts.xml new file mode 100644 index 0000000000..6b18f62573 --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-diverts.xml @@ -0,0 +1,64 @@ + + + + + + + + 0.0.0.0 + + 100 + + true + + false + + NIO + + ./target/data/paging + + ./target/data/bindings + + ./target/data/journal + + ./target/data/large-messages + + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + +
+
+
+
+ + + + +
a
+ target +
+
+ + diff --git a/tests/integration-tests/src/test/resources/reload-security-settings-updated.xml b/tests/integration-tests/src/test/resources/reload-security-settings-updated.xml new file mode 100644 index 0000000000..47d94b16d3 --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-security-settings-updated.xml @@ -0,0 +1,62 @@ + + + + + + + + 0.0.0.0 + + 100 + + true + + false + + NIO + + ./target/data/paging + + ./target/data/bindings + + ./target/data/journal + + ./target/data/large-messages + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + + + + + + + + + + + + + + diff --git a/tests/integration-tests/src/test/resources/reload-security-settings.xml b/tests/integration-tests/src/test/resources/reload-security-settings.xml new file mode 100644 index 0000000000..095b475e2c --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-security-settings.xml @@ -0,0 +1,62 @@ + + + + + + + + 0.0.0.0 + + 100 + + true + + false + + NIO + + ./target/data/paging + + ./target/data/bindings + + ./target/data/journal + + ./target/data/large-messages + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + + + + + + + + + + + + + +