This is an automated email from the ASF dual-hosted git repository.
jbertram pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/artemis.git
The following commit(s) were added to refs/heads/main by this push:
new 91d6985162 ARTEMIS-5795 Set security config using system properties
91d6985162 is described below
commit 91d69851623b2f7fcb6997057404d4c28c3d036d
Author: Domenico Francesco Bruscino <[email protected]>
AuthorDate: Fri Dec 5 08:39:53 2025 +0100
ARTEMIS-5795 Set security config using system properties
---
.../artemis/cli/factory/BrokerFactory.java | 50 ++-
.../artemis/cli/factory/BrokerFactoryTest.java | 421 +++++++++++++++++++++
.../cli/factory/TestBrokerFactoryHandler.java | 87 +++++
.../org/apache/activemq/artemis/broker/test | 17 +
.../api/config/ActiveMQDefaultConfiguration.java | 18 +
.../apache/activemq/artemis/dto/PropertyDTO.java | 8 +
docs/user-manual/security.adoc | 54 ++-
7 files changed, 653 insertions(+), 2 deletions(-)
diff --git
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/BrokerFactory.java
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/BrokerFactory.java
index 5a1a28c48c..181207239e 100644
---
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/BrokerFactory.java
+++
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/BrokerFactory.java
@@ -18,10 +18,18 @@ package org.apache.activemq.artemis.cli.factory;
import java.io.IOException;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Properties;
+import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.cli.ConfigurationException;
import org.apache.activemq.artemis.core.server.ActivateCallback;
import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.dto.JaasSecurityDTO;
+import org.apache.activemq.artemis.dto.PropertyDTO;
+import org.apache.activemq.artemis.dto.SecurityManagerDTO;
import org.apache.activemq.artemis.dto.ServerDTO;
import org.apache.activemq.artemis.integration.Broker;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
@@ -29,6 +37,11 @@ import org.apache.activemq.artemis.utils.FactoryFinder;
public class BrokerFactory {
+ private static final String SECURITY_JAAS_DOMAIN_PROP_NAME = "domain";
+ private static final String SECURITY_JAAS_CERTIFICATE_DOMAIN_PROP_NAME =
"certificateDomain";
+ private static final String SECURITY_MANAGER_CLASS_NAME_PROP_NAME =
"className";
+ private static final String SECURITY_MANAGER_PROPERTIES_PREFIX =
"properties.";
+
private static BrokerDTO createBrokerConfiguration(URI configURI,
String artemisHome,
String artemisInstance,
@@ -44,7 +57,42 @@ public class BrokerFactory {
} catch (IOException ioe) {
throw new ConfigurationException("Invalid configuration URI, can't
find configuration scheme: " + configURI.getScheme());
}
- return factory.createBroker(configURI, artemisHome, artemisInstance,
artemisURIInstance);
+ BrokerDTO broker = factory.createBroker(configURI, artemisHome,
artemisInstance, artemisURIInstance);
+
+ populateSecurityWithSystemProperties(broker);
+
+ return broker;
+ }
+
+ private static void populateSecurityWithSystemProperties(BrokerDTO broker) {
+ Properties systemProperties = System.getProperties();
+ String systemSecurityJaasPropertyPrefix =
ActiveMQDefaultConfiguration.getDefaultSystemSecurityJaasPropertyPrefix();
+ String systemSecurityManagerPropertyPrefix =
ActiveMQDefaultConfiguration.getDefaultSystemSecurityManagerPropertyPrefix();
+
+ if (systemProperties.containsKey(systemSecurityJaasPropertyPrefix +
SECURITY_JAAS_DOMAIN_PROP_NAME)) {
+ broker.security = broker.security instanceof JaasSecurityDTO ?
+ (JaasSecurityDTO) broker.security : new JaasSecurityDTO();
+ } else if
(systemProperties.containsKey(systemSecurityManagerPropertyPrefix +
SECURITY_MANAGER_CLASS_NAME_PROP_NAME)) {
+ broker.security = broker.security instanceof SecurityManagerDTO ?
+ (SecurityManagerDTO) broker.security : new SecurityManagerDTO();
+ }
+
+ if (broker.security instanceof JaasSecurityDTO security) {
+ security.domain = Optional.ofNullable((String)systemProperties.get(
+ systemSecurityJaasPropertyPrefix +
SECURITY_JAAS_DOMAIN_PROP_NAME)).orElse(security.domain);
+ security.certificateDomain =
Optional.ofNullable((String)systemProperties.get(
+ systemSecurityJaasPropertyPrefix +
SECURITY_JAAS_CERTIFICATE_DOMAIN_PROP_NAME)).orElse(security.certificateDomain);
+ } else if (broker.security instanceof SecurityManagerDTO security) {
+ security.className = Optional.ofNullable((String)systemProperties.get(
+ systemSecurityManagerPropertyPrefix +
SECURITY_MANAGER_CLASS_NAME_PROP_NAME)).orElse(security.className);
+ security.properties = Objects.requireNonNullElse(security.properties,
new ArrayList<>());
+ systemProperties.forEach((key, value) -> {
+ if (((String)key).startsWith(systemSecurityManagerPropertyPrefix +
SECURITY_MANAGER_PROPERTIES_PREFIX)) {
+ security.properties.add(new PropertyDTO(((String)key).substring(
+ systemSecurityManagerPropertyPrefix.length() +
SECURITY_MANAGER_PROPERTIES_PREFIX.length()), (String)value));
+ }
+ });
+ }
}
public static BrokerDTO createBrokerConfiguration(String configuration,
diff --git
a/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/factory/BrokerFactoryTest.java
b/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/factory/BrokerFactoryTest.java
new file mode 100644
index 0000000000..70de3643a1
--- /dev/null
+++
b/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/factory/BrokerFactoryTest.java
@@ -0,0 +1,421 @@
+/*
+ * 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.artemis.cli.factory;
+
+import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
+import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.dto.JaasSecurityDTO;
+import org.apache.activemq.artemis.dto.PropertyDTO;
+import org.apache.activemq.artemis.dto.SecurityDTO;
+import org.apache.activemq.artemis.dto.SecurityManagerDTO;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class BrokerFactoryTest {
+
+ private static final String testBrokerConfiguration = "test://config";
+
+ private final String securityJaasPropertyPrefix =
ActiveMQDefaultConfiguration.getDefaultSystemSecurityJaasPropertyPrefix();
+ private final String securityManagerPropertyPrefix =
ActiveMQDefaultConfiguration.getDefaultSystemSecurityManagerPropertyPrefix();
+ private final List<String> systemPropertiesToClear = new ArrayList<>();
+
+ @BeforeEach
+ public void setUp() {
+ TestBrokerFactoryHandler.clear();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ TestBrokerFactoryHandler.clear();
+ for (String property : systemPropertiesToClear) {
+ System.clearProperty(property);
+ }
+ systemPropertiesToClear.clear();
+ }
+
+ private void setSystemProperty(String key, String value) {
+ System.setProperty(key, value);
+ systemPropertiesToClear.add(key);
+ }
+
+ @Test
+ public void testCreateBrokerConfiguration() throws Exception {
+ final String testArtemisHome = "test-home";
+ final String testArtemisInstance = "test-instance";
+ final URI testArtemisURIInstance = URI.create(testArtemisInstance);
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO createdBroker = BrokerFactory.createBrokerConfiguration(
+ testBrokerConfiguration, testArtemisHome, testArtemisInstance,
testArtemisURIInstance);
+
+ assertNotNull(createdBroker);
+ assertEquals(testBrokerConfiguration,
TestBrokerFactoryHandler.getBrokerURI().toString());
+ assertEquals(testArtemisHome, TestBrokerFactoryHandler.getArtemisHome());
+ assertEquals(testArtemisInstance,
TestBrokerFactoryHandler.getArtemisInstance());
+ assertEquals(testArtemisURIInstance,
TestBrokerFactoryHandler.getArtemisURIInstance());
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithJaasDomainFromSystemProperties() throws
Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "domain", "testDomain");
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "testDomain", null);
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithJaasCertificateDomainFromSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "certificateDomain",
"testCertificateDomain");
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ assertNull(createdBroker.security);
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithJaasDomainAndCertificateDomainFromSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "domain", "testDomain");
+ setSystemProperty(securityJaasPropertyPrefix + "certificateDomain",
"testCertificateDomain");
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO broker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(broker);
+ testJaasSecurity(broker.security, "testDomain", "testCertificateDomain");
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewJaasDomainFromExistingJaasSecurityAndSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "domain",
"newTestDomain");
+
+ JaasSecurityDTO security = new JaasSecurityDTO();
+ security.domain = "testDomain";
+ security.certificateDomain = "testCertificateDomain";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "newTestDomain",
"testCertificateDomain");
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewJaasCertificateDomainFromExistingJaasSecurityAndSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "certificateDomain",
"newTestCertificateDomain");
+
+ JaasSecurityDTO security = new JaasSecurityDTO();
+ security.domain = "testDomain";
+ security.certificateDomain = "testCertificateDomain";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "testDomain",
"newTestCertificateDomain");
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewJaasDomainFromExistingSecurityManagerAndSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "domain",
"newTestDomain");
+
+ SecurityManagerDTO security = new SecurityManagerDTO();
+ security.className = "testClass";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "newTestDomain", null);
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewJaasCertificateDomainFromExistingSecurityManagerAndSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "certificateDomain",
"newTestCertificateDomain");
+
+ SecurityManagerDTO security = new SecurityManagerDTO();
+ security.className = "testClass";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "testClass",
Collections.emptyList());
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewJaasDomainAndCertificateDomainFromExistingJaasSecurityAndSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "domain",
"newTestDomain");
+ setSystemProperty(securityJaasPropertyPrefix + "certificateDomain",
"newTestCertificateDomain");
+
+ JaasSecurityDTO security = new JaasSecurityDTO();
+ security.domain = "testDomain";
+ security.certificateDomain = "testCertificateDomain";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "newTestDomain",
"newTestCertificateDomain");
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewJaasDomainAndCertificateDomainFromExistingSecurityManagerAndSystemProperties()
throws Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "domain",
"newTestDomain");
+ setSystemProperty(securityJaasPropertyPrefix + "certificateDomain",
"newTestCertificateDomain");
+
+ SecurityManagerDTO security = new SecurityManagerDTO();
+ security.className = "testClassName";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "newTestDomain",
"newTestCertificateDomain");
+ }
+
+ private void testJaasSecurity(SecurityDTO security, String expectedDomain,
String expectedCertificateDomain) throws Exception {
+ assertNotNull(security);
+ assertInstanceOf(JaasSecurityDTO.class, security);
+ JaasSecurityDTO jaasSecurity = (JaasSecurityDTO) security;
+ assertEquals(expectedDomain, jaasSecurity.domain);
+ assertEquals(expectedCertificateDomain, jaasSecurity.certificateDomain);
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithSecurityManagerClassNameFromSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "className",
"testClassName");
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "testClassName",
Collections.emptyList());
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithSecurityManagerPropertiesFromSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey1",
"testValue1");
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey2",
"testValue2");
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ assertNull(createdBroker.security);
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithSecurityManagerClassNameAndPropertiesFromSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "className",
"testClassName");
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey1",
"testValue1");
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey2",
"testValue2");
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "testClassName", List.of(
+ new PropertyDTO("testKey1", "testValue1"), new
PropertyDTO("testKey2", "testValue2")));
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewSecurityManagerClassNameFromExistingSecurityManagerAndSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "className",
"newTestClassName");
+
+ SecurityManagerDTO security = new SecurityManagerDTO();
+ security.className = "testClassName";
+ security.properties = new ArrayList<>(List.of(
+ new PropertyDTO("testKey1", "testValue1"),
+ new PropertyDTO("testKey2", "testValue2")));
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "newTestClassName", List.of(
+ new PropertyDTO("testKey1", "testValue1"), new
PropertyDTO("testKey2", "testValue2")));
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewSecurityManagerPropertiesFromExistingSecurityManagerAndSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey1",
"newTestValue1");
+ setSystemProperty(securityManagerPropertyPrefix +
"properties.newTestKey2", "newTestValue2");
+
+ SecurityManagerDTO security = new SecurityManagerDTO();
+ security.className = "testClassName";
+ security.properties = new ArrayList<>(List.of(
+ new PropertyDTO("testKey1", "testValue1"),
+ new PropertyDTO("testKey2", "testValue2")));
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "testClassName", List.of(
+ new PropertyDTO("testKey1", "testValue1"), new
PropertyDTO("testKey2", "testValue2"),
+ new PropertyDTO("testKey1", "newTestValue1"), new
PropertyDTO("newTestKey2", "newTestValue2")));
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewSecurityManagerClassNameAndPropertiesFromExistingSecurityManagerAndSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "className",
"newTestClassName");
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey1",
"newTestValue1");
+ setSystemProperty(securityManagerPropertyPrefix +
"properties.newTestKey2", "newTestValue2");
+
+ SecurityManagerDTO security = new SecurityManagerDTO();
+ security.className = "testClassName";
+ security.properties = new ArrayList<>(List.of(
+ new PropertyDTO("testKey1", "testValue1"),
+ new PropertyDTO("testKey2", "testValue2")));
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "newTestClassName", List.of(
+ new PropertyDTO("testKey1", "testValue1"), new
PropertyDTO("testKey2", "testValue2"),
+ new PropertyDTO("testKey1", "newTestValue1"), new
PropertyDTO("newTestKey2", "newTestValue2")));
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewSecurityManagerClassNameFromExistingJaasSecurityAndSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "className",
"newTestClassName");
+
+ JaasSecurityDTO security = new JaasSecurityDTO();
+ security.domain = "testDomain";
+ security.certificateDomain = "testCertificateDomain";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "newTestClassName",
Collections.emptyList());
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewSecurityManagerPropertiesFromExistingJaasSecurityAndSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey1",
"newTestValue1");
+ setSystemProperty(securityManagerPropertyPrefix +
"properties.newTestKey2", "newTestValue2");
+
+ JaasSecurityDTO security = new JaasSecurityDTO();
+ security.domain = "testDomain";
+ security.certificateDomain = "testCertificateDomain";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "testDomain",
"testCertificateDomain");
+ }
+
+ @Test
+ public void
testCreateBrokerConfigurationWithNewSecurityManagerClassNameAndPropertiesFromExistingJaasSecurityAndSystemProperties()
throws Exception {
+ setSystemProperty(securityManagerPropertyPrefix + "className",
"newTestClassName");
+ setSystemProperty(securityManagerPropertyPrefix + "properties.testKey1",
"newTestValue1");
+ setSystemProperty(securityManagerPropertyPrefix +
"properties.newTestKey2", "newTestValue2");
+
+ JaasSecurityDTO security = new JaasSecurityDTO();
+ security.domain = "testDomain";
+ security.certificateDomain = "testCertificateDomain";
+ BrokerDTO broker = new BrokerDTO();
+ broker.security = security;
+ TestBrokerFactoryHandler.setBroker(broker);
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testSecurityManager(createdBroker.security, "newTestClassName", List.of(
+ new PropertyDTO("testKey1", "newTestValue1"), new
PropertyDTO("newTestKey2", "newTestValue2")));
+ }
+
+ private void testSecurityManager(SecurityDTO security, String
expectedClassName, List<PropertyDTO> expectedProperties) throws Exception {
+ assertNotNull(security);
+ assertInstanceOf(SecurityManagerDTO.class, security);
+ SecurityManagerDTO securityManager = (SecurityManagerDTO)security;
+ assertEquals(expectedClassName, securityManager.className);
+
+ if (expectedProperties != null) {
+ assertEquals(expectedProperties.size(),
securityManager.properties.size());
+ assertTrue(expectedProperties.stream().allMatch(expectedProperty ->
+ securityManager.properties.stream().anyMatch(property ->
+ Objects.equals(expectedProperty.key, property.key) &&
+ Objects.equals(expectedProperty.value, property.value))));
+ } else {
+ assertNull(securityManager.properties);
+ }
+ }
+
+ @Test
+ public void testJaasSecurityTakesPrecedenceOverSecurityManager() throws
Exception {
+ setSystemProperty(securityJaasPropertyPrefix + "domain", "testDomain");
+ setSystemProperty(securityManagerPropertyPrefix + "className",
"testClassName");
+
+ TestBrokerFactoryHandler.setBroker(new BrokerDTO());
+
+ BrokerDTO createdBroker =
BrokerFactory.createBrokerConfiguration("test://config", null, null, null);
+
+ assertNotNull(createdBroker);
+ testJaasSecurity(createdBroker.security, "testDomain", null);
+ }
+}
diff --git
a/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/factory/TestBrokerFactoryHandler.java
b/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/factory/TestBrokerFactoryHandler.java
new file mode 100644
index 0000000000..7bae00bc59
--- /dev/null
+++
b/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/factory/TestBrokerFactoryHandler.java
@@ -0,0 +1,87 @@
+/*
+ * 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.artemis.cli.factory;
+
+import org.apache.activemq.artemis.dto.BrokerDTO;
+
+import java.net.URI;
+
+public class TestBrokerFactoryHandler implements BrokerFactoryHandler {
+
+ private static URI brokerURI;
+ private static String artemisHome;
+ private static String artemisInstance;
+ private static URI artemisURIInstance;
+ private static BrokerDTO broker;
+
+ public static URI getBrokerURI() {
+ return brokerURI;
+ }
+
+ public static void setBrokerURI(URI brokerURI) {
+ TestBrokerFactoryHandler.brokerURI = brokerURI;
+ }
+
+ public static String getArtemisHome() {
+ return artemisHome;
+ }
+
+ public static void setArtemisHome(String artemisHome) {
+ TestBrokerFactoryHandler.artemisHome = artemisHome;
+ }
+
+ public static String getArtemisInstance() {
+ return artemisInstance;
+ }
+
+ public static void setArtemisInstance(String artemisInstance) {
+ TestBrokerFactoryHandler.artemisInstance = artemisInstance;
+ }
+
+ public static URI getArtemisURIInstance() {
+ return artemisURIInstance;
+ }
+
+ public static void setArtemisURIInstance(URI artemisURIInstance) {
+ TestBrokerFactoryHandler.artemisURIInstance = artemisURIInstance;
+ }
+
+ public static BrokerDTO getBroker() {
+ return broker;
+ }
+
+ public static void setBroker(BrokerDTO broker) {
+ TestBrokerFactoryHandler.broker = broker;
+ }
+
+ public static void clear() {
+ brokerURI = null;
+ artemisHome = null;
+ artemisInstance = null;
+ artemisURIInstance = null;
+ broker = null;
+ }
+
+ @Override
+ public BrokerDTO createBroker(URI brokerURI, String artemisHome, String
artemisInstance, URI artemisURIInstance) throws Exception {
+ TestBrokerFactoryHandler.brokerURI = brokerURI;
+ TestBrokerFactoryHandler.artemisHome = artemisHome;
+ TestBrokerFactoryHandler.artemisInstance = artemisInstance;
+ TestBrokerFactoryHandler.artemisURIInstance = artemisURIInstance;
+ return broker;
+ }
+}
diff --git
a/artemis-cli/src/test/resources/META-INF/services/org/apache/activemq/artemis/broker/test
b/artemis-cli/src/test/resources/META-INF/services/org/apache/activemq/artemis/broker/test
new file mode 100644
index 0000000000..4259e4bb64
--- /dev/null
+++
b/artemis-cli/src/test/resources/META-INF/services/org/apache/activemq/artemis/broker/test
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.activemq.artemis.cli.factory.TestBrokerFactoryHandler
diff --git
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
index c7f7af4ec5..3d31bb5cb9 100644
---
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
+++
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
@@ -571,6 +571,12 @@ public final class ActiveMQDefaultConfiguration {
public static final String DEFAULT_SYSTEM_WEB_PROPERTY_PREFIX =
"webconfig.";
+ public static final String DEFAULT_SYSTEM_SECURITY_PROPERTY_PREFIX =
"securityconfig.";
+
+ public static final String DEFAULT_SYSTEM_SECURITY_JAAS_PROPERTY_PREFIX =
"jaas.";
+
+ public static final String DEFAULT_SYSTEM_SECURITY_MANAGER_PROPERTY_PREFIX
= "manager.";
+
public static final String BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME =
"broker.properties";
public static final String BROKER_PROPERTIES_KEY_SURROUND = "\"";
@@ -1726,6 +1732,18 @@ public final class ActiveMQDefaultConfiguration {
return DEFAULT_SYSTEM_WEB_PROPERTY_PREFIX;
}
+ public static String getDefaultSystemSecurityPropertyPrefix() {
+ return DEFAULT_SYSTEM_SECURITY_PROPERTY_PREFIX;
+ }
+
+ public static String getDefaultSystemSecurityJaasPropertyPrefix() {
+ return getDefaultSystemSecurityPropertyPrefix() +
DEFAULT_SYSTEM_SECURITY_JAAS_PROPERTY_PREFIX;
+ }
+
+ public static String getDefaultSystemSecurityManagerPropertyPrefix() {
+ return getDefaultSystemSecurityPropertyPrefix() +
DEFAULT_SYSTEM_SECURITY_MANAGER_PROPERTY_PREFIX;
+ }
+
public static String getDefaultBrokerPropertiesKeySurround() {
return BROKER_PROPERTIES_KEY_SURROUND;
}
diff --git
a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/PropertyDTO.java
b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/PropertyDTO.java
index c1015a830d..9fe37f35a5 100644
--- a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/PropertyDTO.java
+++ b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/PropertyDTO.java
@@ -30,4 +30,12 @@ public class PropertyDTO {
@XmlAttribute
public String value;
+
+ public PropertyDTO() {
+ }
+
+ public PropertyDTO(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
}
diff --git a/docs/user-manual/security.adoc b/docs/user-manual/security.adoc
index b08eb271d7..e42a3123c1 100644
--- a/docs/user-manual/security.adoc
+++ b/docs/user-manual/security.adoc
@@ -20,6 +20,55 @@ Security is enabled by default. To disable security
completely set the `security
</configuration>
----
+== Boot-time Security Configuration via System Properties
+
+Security configuration can be provided at boot time via system properties,
which will override any security settings defined in `bootstrap.xml`.
+This is useful for containerized deployments or scenarios where configuration
needs to be injected without modifying configuration files.
+
+=== JAAS Security via System Properties
+
+To configure JAAS security at boot time, use the following system properties:
+
+securityconfig.jaas.domain::
+The name of the JAAS login configuration entry to use for authentication.
+This is equivalent to the `domain` attribute of the `<jaas-security>` element
in `bootstrap.xml`.
+
+securityconfig.jaas.certificateDomain::
+The name of the JAAS login configuration entry to use for certificate-based
authentication.
+This is equivalent to the `certificate-domain` attribute of the
`<jaas-security>` element in `bootstrap.xml`.
+
+For example, to start the broker with JAAS security configured via system
properties:
+
+[,sh]
+----
+./artemis run -Dsecurityconfig.jaas.domain=MyDomain
-Dsecurityconfig.jaas.certificateDomain=MyCertDomain
+----
+
+=== Custom Security Manager via System Properties
+
+To configure a custom security manager at boot time, use the following system
properties:
+
+securityconfig.manager.className::
+The fully qualified class name of the security manager implementation.
+This is equivalent to the `class-name` attribute of the `<security-manager>`
element in `bootstrap.xml`.
+
+securityconfig.manager.properties.<key>::
+Properties to pass to the security manager.
+Each property key after the `properties.` prefix will be passed as a
configuration property to the security manager.
+
+For example, to start the broker with the basic security manager configured
via system properties:
+
+[,sh]
+----
+./artemis run \
+
-Dsecurityconfig.manager.className=org.apache.activemq.artemis.spi.core.security.ActiveMQBasicSecurityManager
\
+ -Dsecurityconfig.manager.properties.bootstrapUser=admin \
+ -Dsecurityconfig.manager.properties.bootstrapPassword=admin \
+ -Dsecurityconfig.manager.properties.bootstrapRole=amq
+----
+
+NOTE: When security configuration is provided via system properties, it takes
precedence over any security configuration in `bootstrap.xml`.
+
== Caching Security Operations
For performance reasons both *authentication and authorization is cached*
independently.
@@ -404,6 +453,7 @@ All user & role data is stored in the broker's bindings
journal which means any
When using the Java Authentication and Authorization Service (JAAS) much of
the configuration depends on which login module is used.
However, there are a few commonalities for every case.
The first place to look is in `bootstrap.xml`.
+Alternatively, JAAS security can be configured at boot time via system
properties as described in <<jaas-security-via-system-properties>>.
Here is an example using the `PropertiesLogin` JAAS login module which reads
user, password, and role information from properties files:
[,xml]
@@ -1583,7 +1633,9 @@ For details about masking passwords in broker.xml please
see the xref:masking-pa
The underpinnings of the broker's security implementation can be changed if so
desired.
The broker uses a component called a "security manager" to implement the
actual authentication and authorization checks.
-By default, the broker uses
`org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager` to
provide JAAS integration, but users can provide their own implementation of
`org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5` and
configure it in `bootstrap.xml` using the `security-manager` element, e.g.:
+By default, the broker uses
`org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager` to
provide JAAS integration, but users can provide their own implementation of
`org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5` and
configure it in `bootstrap.xml` using the `security-manager` element.
+Alternatively, a custom security manager can be configured at boot time via
system properties as described in
<<custom-security-manager-via-system-properties>>.
+Here is an example of configuring a custom security manager in `bootstrap.xml`:
[,xml]
----
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]