This is an automated email from the ASF dual-hosted git repository.

tabish 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 acf60a8809 ARTEMIS-5092 add security-setting mngmnt via JSON
acf60a8809 is described below

commit acf60a880992f61133559f49500ea8330517543c
Author: Justin Bertram <[email protected]>
AuthorDate: Thu Dec 11 17:03:40 2025 -0600

    ARTEMIS-5092 add security-setting mngmnt via JSON
    
    This commit includes the following changes:
    
     - A few new testing & debugging helper methods.
     - Deprecated existing security-settings management methods
     - New security-settings management method accepting JSON input
     - Simplified RoleInfo by extending Role
     - Added constants for permission types & used them where possible
     - Clarified deprepcation for Role ctors
     - Added support methods for JSON conversion
     - Added tests for JSON conversion support methods, etc.
---
 .../apache/activemq/artemis/utils/JsonLoader.java  |  23 ++
 .../apache/activemq/artemis/utils/RandomUtil.java  |  14 +
 .../apache/activemq/artemis/api/core/JsonUtil.java |  18 ++
 .../api/core/management/ActiveMQServerControl.java |  55 +++-
 .../artemis/api/core/management/RoleInfo.java      | 122 +--------
 .../activemq/artemis/core/security/Role.java       | 146 ++++++-----
 .../activemq/artemis/utils/SecurityFormatter.java  | 284 +++++++++++++++++++--
 .../activemq/artemis/api/core/JsonUtilTest.java    |  19 ++
 .../artemis/util/SecurityFormatterTest.java        | 191 ++++++++++++++
 .../deployers/impl/FileConfigurationParser.java    |  62 ++---
 .../management/impl/ActiveMQServerControlImpl.java |  20 +-
 .../config/PersistedSecuritySetting.java           |  68 +++--
 .../core/server/impl/ActiveMQServerImpl.java       |  13 +-
 .../management/ActiveMQServerControlTest.java      |  54 +++-
 .../ActiveMQServerControlUsingCoreTest.java        |   5 +
 .../tests/unit/core/util/RandomUtilTest.java       |  19 +-
 16 files changed, 854 insertions(+), 259 deletions(-)

diff --git 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/JsonLoader.java
 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/JsonLoader.java
index 6ff1f04129..8ee101c3f6 100644
--- 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/JsonLoader.java
+++ 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/JsonLoader.java
@@ -26,8 +26,13 @@ import 
org.apache.activemq.artemis.json.impl.JsonObjectBuilderImpl;
 import org.apache.activemq.artemis.json.impl.JsonObjectImpl;
 
 import javax.json.JsonReader;
+import javax.json.JsonWriter;
 import javax.json.spi.JsonProvider;
 import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Map;
 
 /**
  * This is to make sure we use the proper classLoader to load JSon libraries. 
This is equivalent to using
@@ -43,6 +48,12 @@ public class JsonLoader {
       }
    }
 
+   public static void writeObject(Map<String, Object> properties, Writer 
writer, JsonObject jsonObject) {
+      try (JsonWriter jsonReader = 
provider.createWriterFactory(properties).createWriter(writer)) {
+         jsonReader.writeObject((((JsonObjectImpl)jsonObject).getRawObject()));
+      }
+   }
+
    public static JsonArray readArray(Reader reader) {
       try (JsonReader jsonReader = provider.createReader(reader)) {
          return new JsonArrayImpl(jsonReader.readArray());
@@ -56,4 +67,16 @@ public class JsonLoader {
    public static JsonObjectBuilder createObjectBuilder() {
       return new JsonObjectBuilderImpl(provider.createObjectBuilder());
    }
+
+   // Please do not remove this method as it's useful for debugging purposes
+   public static String prettyPrint(String json) {
+      String result = json;
+      try (StringReader reader = new StringReader(json);
+           StringWriter writer = new StringWriter()) {
+         
JsonLoader.writeObject(Map.of(javax.json.stream.JsonGenerator.PRETTY_PRINTING, 
true), writer, JsonLoader.readObject(reader));
+         result = writer.toString();
+      } catch (Exception e) {
+      }
+      return result;
+   }
 }
diff --git 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java
 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java
index 8e88389213..b1d7b032fe 100644
--- 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java
+++ 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java
@@ -175,4 +175,18 @@ public class RandomUtil {
       return RandomUtil.random.nextFloat();
    }
 
+   /**
+    * Generates an array of random alpha-numeric words. The words will be of a 
random length between 1 and 10
+    * characters.
+    *
+    * @param wordCount the number of random words to generate
+    * @return an array of randomly generated alpha-numeric words between 1 and 
10 characters long
+    */
+   public static String[] randomWords(int wordCount) {
+      String[] words = new String[wordCount];
+      for (int i = 0; i < wordCount; i++) {
+         words[i] = randomAlphaNumericString((randomPositiveInt() % 10) + 1);
+      }
+      return words;
+   }
 }
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/JsonUtil.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/JsonUtil.java
index cfc0fb20eb..4aad12eeea 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/JsonUtil.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/JsonUtil.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.activemq.artemis.json.JsonArray;
 import org.apache.activemq.artemis.json.JsonArrayBuilder;
@@ -456,4 +457,21 @@ public final class JsonUtil {
          return s;
       }
    }
+
+   /**
+    * Converts a JSON array from the specified key in a JsonObject into a 
comma-separated string. If the key does not
+    * exist or if its value is not a JSON array, then an empty string is 
returned.
+    *
+    * @param jsonObject the JsonObject from which to retrieve the array
+    * @param key        the key associated with the JSON array in the 
JsonObject
+    * @return a comma-separated string representation of the array's elements, 
or an empty string if the key does not
+    * exist or the value is not an array
+    */
+   public static String arrayToString(JsonObject jsonObject, String key) {
+      JsonValue value = jsonObject.get(key);
+      if (value == null || value.getValueType() != JsonValue.ValueType.ARRAY) {
+         return "";
+      }
+      return jsonObject.getJsonArray(key).stream().map((s) -> ((JsonString) 
s).getString()).collect(Collectors.joining(", "));
+   }
 }
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java
index c744e7aea4..4169cf7898 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java
@@ -1382,6 +1382,10 @@ public interface ActiveMQServerControl {
    @Operation(desc = "List the sessions for the given connectionID", impact = 
MBeanOperationInfo.INFO)
    String[] listSessions(@Parameter(desc = "a connection ID", name = 
"connectionID") String connectionID) throws Exception;
 
+   /**
+    * @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, 
String)}
+    */
+   @Deprecated(forRemoval = true)
    @Operation(desc = "Add security settings for addresses matching the 
addressMatch", impact = MBeanOperationInfo.ACTION)
    void addSecuritySettings(@Parameter(desc = "an address match", name = 
"addressMatch") String addressMatch,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to send messages", name = "send") String sendRoles,
@@ -1392,6 +1396,10 @@ public interface ActiveMQServerControl {
                             @Parameter(desc = "a comma-separated list of roles 
allowed to delete non durable queues", name = "deleteNonDurableQueueRoles") 
String deleteNonDurableQueueRoles,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to send management messages messages", name = "manage") String 
manageRoles) throws Exception;
 
+   /**
+    * @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, 
String)}
+    */
+   @Deprecated(forRemoval = true)
    @Operation(desc = "Add security settings for addresses matching the 
addressMatch", impact = MBeanOperationInfo.ACTION)
    void addSecuritySettings(@Parameter(desc = "an address match", name = 
"addressMatch") String addressMatch,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to send messages", name = "send") String sendRoles,
@@ -1403,6 +1411,10 @@ public interface ActiveMQServerControl {
                             @Parameter(desc = "a comma-separated list of roles 
allowed to send management messages messages", name = "manage") String 
manageRoles,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to browse queues", name = "browse") String browseRoles) throws 
Exception;
 
+   /**
+    * @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, 
String)}
+    */
+   @Deprecated(forRemoval = true)
    @Operation(desc = "Add security settings for addresses matching the 
addressMatch", impact = MBeanOperationInfo.ACTION)
    void addSecuritySettings(@Parameter(desc = "an address match", name = 
"addressMatch") String addressMatch,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to send messages", name = "send") String sendRoles,
@@ -1416,6 +1428,10 @@ public interface ActiveMQServerControl {
                             @Parameter(desc = "a comma-separated list of roles 
allowed to create addresses", name = "createAddressRoles") String 
createAddressRoles,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to delete addresses", name = "deleteAddressRoles") String 
deleteAddressRoles) throws Exception;
 
+   /**
+    * @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, 
String)}
+    */
+   @Deprecated(forRemoval = true)
    @Operation(desc = "Add security settings for addresses matching the 
addressMatch", impact = MBeanOperationInfo.ACTION)
    void addSecuritySettings(@Parameter(desc = "an address match", name = 
"addressMatch") String addressMatch,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to send messages", name = "send") String sendRoles,
@@ -1431,6 +1447,43 @@ public interface ActiveMQServerControl {
                             @Parameter(desc = "a comma-separated list of roles 
allowed to view management resources", name = "view") String viewRoles,
                             @Parameter(desc = "a comma-separated list of roles 
allowed to edit management resources", name = "edit") String editRoles) throws 
Exception;
 
+   /**
+    * Add security-settings for matching addresses.
+    *
+    * @param addressMatch           The address match pattern to which the 
security-settings will be applied.
+    * @param securitySettingsAsJson The security-settings in JSON format. The 
JSON consists of key/value pairs where the
+    *                               key is a string representing the 
permission type, and the value is an array of
+    *                               strings containing the names of the roles 
which will be granted the corresponding
+    *                               permission, e.g.:
+    *                               <pre>{@code
+    *                               {
+    *                                 "send": ["role1", "role2"],
+    *                                 "consume": ["role3", "role4"],
+    *                                 "createDurableQueue": ["role5", "role6"]
+    *                               }
+    *                               }</pre>
+    *                               These permission types are supported:
+    *                               <ul>
+    *                               <li>send</li>
+    *                               <li>consume</li>
+    *                               <li>createDurableQueue</li>
+    *                               <li>deleteDurableQueue</li>
+    *                               <li>createNonDurableQueue</li>
+    *                               <li>deleteNonDurableQueue</li>
+    *                               <li>manage</li>
+    *                               <li>browse</li>
+    *                               <li>createAddress</li>
+    *                               <li>deleteAddress</li>
+    *                               <li>view</li>
+    *                               <li>edit</li>
+    *                               </ul>
+    *                               This JSON can be constructed using methods 
from {@link org.apache.activemq.artemis.utils.SecurityFormatter}.
+    * @throws Exception If an error occurs while adding the security-settings.
+    */
+   @Operation(desc = "Add security-settings for matching addresses", impact = 
MBeanOperationInfo.ACTION)
+   void addSecuritySettings(@Parameter(desc = "an address match", name = 
"addressMatch") String addressMatch,
+                            @Parameter(desc = "The configuration of the 
security-settings as JSON", name = "securitySettingsAsJson")  String 
securitySettingsAsJson) throws Exception;
+
    @Operation(desc = "Remove security settings for an address", impact = 
MBeanOperationInfo.ACTION)
    void removeSecuritySettings(@Parameter(desc = "an address match", name = 
"addressMatch") String addressMatch) throws Exception;
 
@@ -1685,7 +1738,7 @@ public interface ActiveMQServerControl {
     * adds a new address setting for a specific address
     */
    @Operation(desc = "Add address settings for addresses matching the 
addressMatch", impact = MBeanOperationInfo.ACTION)
-   String addAddressSettings(@Parameter(desc = "an address match", name = 
"addressMatch") String address, @Parameter(desc = "The configuration of the 
address settings as JSON", name = "addressSettingsConfigurationAsJson")  String 
addressSettingsConfigurationAsJson) throws Exception;
+   String addAddressSettings(@Parameter(desc = "an address match", name = 
"addressMatch") String address, @Parameter(desc = "The configuration of the 
address settings as JSON", name = "addressSettingsConfigurationAsJson") String 
addressSettingsConfigurationAsJson) throws Exception;
 
    @Operation(desc = "Remove address settings", impact = 
MBeanOperationInfo.ACTION)
    void removeAddressSettings(@Parameter(desc = "an address match", name = 
"addressMatch") String addressMatch) throws Exception;
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/RoleInfo.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/RoleInfo.java
index ec89d552ee..24204e4c8e 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/RoleInfo.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/RoleInfo.java
@@ -16,37 +16,15 @@
  */
 package org.apache.activemq.artemis.api.core.management;
 
+import org.apache.activemq.artemis.api.core.JsonUtil;
+import org.apache.activemq.artemis.core.security.Role;
 import org.apache.activemq.artemis.json.JsonArray;
 import org.apache.activemq.artemis.json.JsonObject;
 
-import org.apache.activemq.artemis.api.core.JsonUtil;
-
 /**
  * Helper class to create Java Objects from the JSON serialization returned by 
{@link AddressControl#getRolesAsJSON()}.
  */
-public final class RoleInfo {
-
-   private final String name;
-
-   private final boolean send;
-
-   private final boolean consume;
-
-   private final boolean createDurableQueue;
-
-   private final boolean deleteDurableQueue;
-
-   private final boolean createNonDurableQueue;
-
-   private final boolean deleteNonDurableQueue;
-
-   private final boolean manage;
-
-   private final boolean browse;
-
-   private final boolean createAddress;
-
-   private final boolean deleteAddress;
+public final class RoleInfo extends Role {
 
    /**
     * {@return an array of RoleInfo corresponding to the JSON serialization 
returned by {@link
@@ -59,16 +37,16 @@ public final class RoleInfo {
          JsonObject r = array.getJsonObject(i);
          RoleInfo role = new RoleInfo(
                  r.getString("name"),
-                 r.getBoolean("send"),
-                 r.getBoolean("consume"),
-                 r.getBoolean("createDurableQueue"),
-                 r.getBoolean("deleteDurableQueue"),
-                 r.getBoolean("createNonDurableQueue"),
-                 r.getBoolean("deleteNonDurableQueue"),
-                 r.getBoolean("manage"),
-                 r.getBoolean("browse"),
-                 r.getBoolean("createAddress"),
-                 r.getBoolean("deleteAddress"));
+                 r.getBoolean(SEND_PERMISSION),
+                 r.getBoolean(CONSUME_PERMISSION),
+                 r.getBoolean(CREATE_DURABLE_QUEUE_PERMISSION),
+                 r.getBoolean(DELETE_DURABLE_QUEUE_PERMISSION),
+                 r.getBoolean(CREATE_NONDURABLE_QUEUE_PERMISSION),
+                 r.getBoolean(DELETE_NONDURABLE_QUEUE_PERMISSION),
+                 r.getBoolean(MANAGE_PERMISSION),
+                 r.getBoolean(BROWSE_PERMISSION),
+                 r.getBoolean(CREATE_ADDRESS_PERMISSION),
+                 r.getBoolean(DELETE_ADDRESS_PERMISSION));
          roles[i] = role;
       }
       return roles;
@@ -97,78 +75,4 @@ public final class RoleInfo {
       this.createAddress = createAddress;
       this.deleteAddress = deleteAddress;
    }
-
-   public String getName() {
-      return name;
-   }
-
-   /**
-    * {@return whether this role can send messages to the address}
-    */
-   public boolean isSend() {
-      return send;
-   }
-
-   /**
-    * {@return whether this role can consume messages from queues bound to the 
address}
-    */
-   public boolean isConsume() {
-      return consume;
-   }
-
-   /**
-    * {@return whether this role can create durable queues bound to the 
address}
-    */
-   public boolean isCreateDurableQueue() {
-      return createDurableQueue;
-   }
-
-   /**
-    * {@return whether this role can delete durable queues bound to the 
address}
-    */
-   public boolean isDeleteDurableQueue() {
-      return deleteDurableQueue;
-   }
-
-   /**
-    * {@return whether this role can create non-durable queues bound to the 
address}
-    */
-   public boolean isCreateNonDurableQueue() {
-      return createNonDurableQueue;
-   }
-
-   /**
-    * {@return whether this role can delete non-durable queues bound to the 
address}
-    */
-   public boolean isDeleteNonDurableQueue() {
-      return deleteNonDurableQueue;
-   }
-
-   /**
-    * {@return whether this role can send management messages to the address}
-    */
-   public boolean isManage() {
-      return manage;
-   }
-
-   /**
-    * {@return whether this role can browse queues bound to the address}
-    */
-   public boolean isBrowse() {
-      return browse;
-   }
-
-   /**
-    * {@return whether this role can create addresses}
-    */
-   public boolean isCreateAddress() {
-      return createAddress;
-   }
-
-   /**
-    * {@return whether this role can delete addresses}
-    */
-   public boolean isDeleteAddress() {
-      return deleteAddress;
-   }
 }
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/security/Role.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/security/Role.java
index 395e0cc507..89e2df372a 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/security/Role.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/security/Role.java
@@ -27,37 +27,63 @@ import org.apache.activemq.artemis.utils.JsonLoader;
  */
 public class Role implements Serializable {
 
+   public static final String SEND_PERMISSION = "send";
+   public static final String CONSUME_PERMISSION = "consume";
+   public static final String CREATE_DURABLE_QUEUE_PERMISSION = 
"createDurableQueue";
+   public static final String DELETE_DURABLE_QUEUE_PERMISSION = 
"deleteDurableQueue";
+   public static final String CREATE_NONDURABLE_QUEUE_PERMISSION = 
"createNonDurableQueue";
+   public static final String DELETE_NONDURABLE_QUEUE_PERMISSION = 
"deleteNonDurableQueue";
+   public static final String MANAGE_PERMISSION = "manage";
+   public static final String BROWSE_PERMISSION = "browse";
+   public static final String CREATE_ADDRESS_PERMISSION = "createAddress";
+   public static final String DELETE_ADDRESS_PERMISSION = "deleteAddress";
+   public static final String VIEW_PERMISSION = "view";
+   public static final String EDIT_PERMISSION = "edit";
+
    private static final long serialVersionUID = 3560097227776448872L;
 
-   private String name;
+   protected String name;
 
-   private boolean send;
+   protected boolean send;
 
-   private boolean consume;
+   protected boolean consume;
 
-   private boolean createAddress;
+   protected boolean createAddress;
 
-   private boolean deleteAddress;
+   protected boolean deleteAddress;
 
-   private boolean createDurableQueue;
+   protected boolean createDurableQueue;
 
-   private boolean deleteDurableQueue;
+   protected boolean deleteDurableQueue;
 
-   private boolean createNonDurableQueue;
+   protected boolean createNonDurableQueue;
 
-   private boolean deleteNonDurableQueue;
+   protected boolean deleteNonDurableQueue;
 
-   private boolean manage;
+   protected boolean manage;
 
-   private boolean browse;
+   protected boolean browse;
 
-   private boolean view;
+   protected boolean view;
 
-   private boolean edit;
+   protected boolean edit;
 
    public JsonObject toJson() {
-      return JsonLoader.createObjectBuilder().add("name", name).add("send", 
send).add("consume", consume).add("createDurableQueue", 
createDurableQueue).add("deleteDurableQueue", 
deleteDurableQueue).add("createNonDurableQueue", 
createNonDurableQueue).add("deleteNonDurableQueue", 
deleteNonDurableQueue).add("manage", manage)
-         .add("browse", browse).add("createAddress", 
createAddress).add("deleteAddress", deleteAddress).add("view", 
view).add("edit", edit).build();
+      return JsonLoader.createObjectBuilder()
+         .add("name", name)
+         .add(SEND_PERMISSION, send)
+         .add(CONSUME_PERMISSION, consume)
+         .add(CREATE_DURABLE_QUEUE_PERMISSION, createDurableQueue)
+         .add(DELETE_DURABLE_QUEUE_PERMISSION, deleteDurableQueue)
+         .add(CREATE_NONDURABLE_QUEUE_PERMISSION, createNonDurableQueue)
+         .add(DELETE_NONDURABLE_QUEUE_PERMISSION, deleteNonDurableQueue)
+         .add(MANAGE_PERMISSION, manage)
+         .add(BROWSE_PERMISSION, browse)
+         .add(CREATE_ADDRESS_PERMISSION, createAddress)
+         .add(DELETE_ADDRESS_PERMISSION, deleteAddress)
+         .add(VIEW_PERMISSION, view)
+         .add(EDIT_PERMISSION, edit)
+         .build();
    }
 
    public Role() {
@@ -65,9 +91,9 @@ public class Role implements Serializable {
    }
 
    /**
-    * @deprecated Use {@link #Role(String, boolean, boolean, boolean, boolean, 
boolean, boolean, boolean, boolean)}
+    * @deprecated Use {@link #Role(String, boolean, boolean, boolean, boolean, 
boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean)}
     */
-   @Deprecated
+   @Deprecated(forRemoval = true)
    public Role(final String name,
                final boolean send,
                final boolean consume,
@@ -81,7 +107,10 @@ public class Role implements Serializable {
       this(name, send, consume, createDurableQueue, deleteDurableQueue, 
createNonDurableQueue, deleteNonDurableQueue, manage, consume);
    }
 
-   @Deprecated
+   /**
+    * @deprecated Use {@link #Role(String, boolean, boolean, boolean, boolean, 
boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean)}
+    */
+   @Deprecated(forRemoval = true)
    public Role(final String name,
                final boolean send,
                final boolean consume,
@@ -96,7 +125,10 @@ public class Role implements Serializable {
       this(name, send, consume, createDurableQueue, deleteDurableQueue, 
createNonDurableQueue, deleteNonDurableQueue, manage, browse, 
createDurableQueue || createNonDurableQueue, deleteDurableQueue || 
deleteNonDurableQueue, false, false);
    }
 
-   @Deprecated
+   /**
+    * @deprecated Use {@link #Role(String, boolean, boolean, boolean, boolean, 
boolean, boolean, boolean, boolean, boolean, boolean, boolean, boolean)}
+    */
+   @Deprecated(forRemoval = true)
    public Role(final String name,
                final boolean send,
                final boolean consume,
@@ -183,6 +215,14 @@ public class Role implements Serializable {
       return browse;
    }
 
+   public boolean isEdit() {
+      return edit;
+   }
+
+   public boolean isView() {
+      return view;
+   }
+
    public void setName(String name) {
       this.name = name;
    }
@@ -227,45 +267,53 @@ public class Role implements Serializable {
       this.browse = browse;
    }
 
+   public void setEdit(boolean edit) {
+      this.edit = edit;
+   }
+
+   public void setView(boolean view) {
+      this.view = view;
+   }
+
    @Override
    public String toString() {
       StringBuilder stringReturn = new StringBuilder("Role {name=" + name + "; 
allows=[");
 
       if (send) {
-         stringReturn.append(" send ");
+         stringReturn.append(" " + SEND_PERMISSION + " ");
       }
       if (consume) {
-         stringReturn.append(" consume ");
-      }
-      if (createAddress) {
-         stringReturn.append(" createAddress ");
-      }
-      if (deleteAddress) {
-         stringReturn.append(" deleteAddress ");
+         stringReturn.append(" " + CONSUME_PERMISSION + " ");
       }
       if (createDurableQueue) {
-         stringReturn.append(" createDurableQueue ");
+         stringReturn.append(" " + CREATE_DURABLE_QUEUE_PERMISSION + " ");
       }
       if (deleteDurableQueue) {
-         stringReturn.append(" deleteDurableQueue ");
+         stringReturn.append(" " + DELETE_DURABLE_QUEUE_PERMISSION + " ");
       }
       if (createNonDurableQueue) {
-         stringReturn.append(" createNonDurableQueue ");
+         stringReturn.append(" " + CREATE_NONDURABLE_QUEUE_PERMISSION + " ");
       }
       if (deleteNonDurableQueue) {
-         stringReturn.append(" deleteNonDurableQueue ");
+         stringReturn.append(" " + DELETE_NONDURABLE_QUEUE_PERMISSION + " ");
       }
       if (manage) {
-         stringReturn.append(" manage ");
+         stringReturn.append(" " + MANAGE_PERMISSION + " ");
       }
       if (browse) {
-         stringReturn.append(" browse ");
+         stringReturn.append(" " + BROWSE_PERMISSION + " ");
+      }
+      if (createAddress) {
+         stringReturn.append(" " + CREATE_ADDRESS_PERMISSION + " ");
+      }
+      if (deleteAddress) {
+         stringReturn.append(" " + DELETE_ADDRESS_PERMISSION + " ");
       }
       if (view) {
-         stringReturn.append(" view ");
+         stringReturn.append(" " + VIEW_PERMISSION + " ");
       }
       if (edit) {
-         stringReturn.append(" edit ");
+         stringReturn.append(" " + EDIT_PERMISSION + " ");
       }
       stringReturn.append("]}");
 
@@ -284,52 +332,36 @@ public class Role implements Serializable {
       return Objects.equals(name, other.name) &&
              send == other.send &&
              consume == other.consume &&
-             createAddress == other.createAddress &&
-             deleteAddress == other.deleteAddress &&
              createDurableQueue == other.createDurableQueue &&
              createNonDurableQueue == other.createNonDurableQueue &&
              deleteDurableQueue == other.deleteDurableQueue &&
              deleteNonDurableQueue == other.deleteNonDurableQueue &&
              manage == other.manage &&
              browse == other.browse &&
+             createAddress == other.createAddress &&
+             deleteAddress == other.deleteAddress &&
              view == other.view &&
              edit == other.edit;
    }
 
    @Override
    public int hashCode() {
-      return Objects.hash(name, send, consume, createAddress, deleteAddress, 
createDurableQueue, deleteDurableQueue,
-                          createNonDurableQueue, deleteNonDurableQueue, 
manage, browse, view, edit);
+      return Objects.hash(name, send, consume, createDurableQueue, 
deleteDurableQueue, createNonDurableQueue,
+                          deleteNonDurableQueue, manage, browse, 
createAddress, deleteAddress, view, edit);
    }
 
    public void merge(Role other) {
       send = send || other.send;
       consume = consume || other.consume;
-      createAddress = createAddress || other.createAddress;
-      deleteAddress = deleteAddress || other.deleteAddress;
       createDurableQueue = createDurableQueue || other.createDurableQueue;
       deleteDurableQueue = deleteDurableQueue || other.deleteDurableQueue;
       createNonDurableQueue = createNonDurableQueue || 
other.createNonDurableQueue;
       deleteNonDurableQueue = deleteNonDurableQueue || 
other.deleteNonDurableQueue;
       manage = manage || other.manage;
       browse = browse || other.browse;
+      createAddress = createAddress || other.createAddress;
+      deleteAddress = deleteAddress || other.deleteAddress;
       view = view || other.view;
       edit = edit || other.edit;
    }
-
-   public boolean isEdit() {
-      return edit;
-   }
-
-   public void setEdit(boolean edit) {
-      this.edit = edit;
-   }
-
-   public boolean isView() {
-      return view;
-   }
-
-   public void setView(boolean view) {
-      this.view = view;
-   }
 }
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/SecurityFormatter.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/SecurityFormatter.java
index 9dfd54c3c5..373d44c233 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/SecurityFormatter.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/SecurityFormatter.java
@@ -22,10 +22,231 @@ import java.util.List;
 import java.util.Set;
 import java.util.StringTokenizer;
 
+import org.apache.activemq.artemis.api.core.JsonUtil;
+import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl;
 import org.apache.activemq.artemis.core.security.Role;
+import org.apache.activemq.artemis.json.JsonArrayBuilder;
+import org.apache.activemq.artemis.json.JsonObject;
+import org.apache.activemq.artemis.json.JsonObjectBuilder;
+import org.apache.activemq.artemis.json.JsonString;
 
+import static org.apache.activemq.artemis.core.security.Role.BROWSE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CONSUME_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_NONDURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_NONDURABLE_QUEUE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.EDIT_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.MANAGE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.SEND_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.VIEW_PERMISSION;
+
+/**
+ * A utility class mainly for converting back and forth between JSON and a 
{@code Set} of {@link Role} objects.
+ * <p>
+ * This is necessary because while security-settings are configured via XML 
and JSON as well as stored in the journal as
+ * a list of role names keyed by permission type, they are handled by the 
broker in a {@code HierarchicalRepository} as
+ * a {@code Set} of {@link Role} objects where each {@link Role} object 
contains the role name and a boolean for each
+ * permission type. Therefore, we need methods to convert between the two 
representations.
+ */
 public class SecurityFormatter {
 
+   /**
+    * Converts a {@code Set} of {@link Role} objects into a JSON string 
representation.
+    *
+    * @param roles the {@code Set} of {@link Role} objects to be converted 
into JSON.
+    * @return JSON representing the permission types and their associated role 
names. See
+    * {@link ActiveMQServerControl#addSecuritySettings(String, String)} for 
details about the JSON structure.
+    */
+   public static String toJSON(Set<Role> roles) {
+      JsonObjectBuilder builder = JsonLoader.createObjectBuilder();
+      JsonArrayBuilder sendRoles = JsonLoader.createArrayBuilder();
+      JsonArrayBuilder consumeRoles = JsonLoader.createArrayBuilder();
+      JsonArrayBuilder createDurableQueueRoles = 
JsonLoader.createArrayBuilder();
+      JsonArrayBuilder deleteDurableQueueRoles = 
JsonLoader.createArrayBuilder();
+      JsonArrayBuilder createNonDurableQueueRoles = 
JsonLoader.createArrayBuilder();
+      JsonArrayBuilder deleteNonDurableQueueRoles = 
JsonLoader.createArrayBuilder();
+      JsonArrayBuilder manageRoles = JsonLoader.createArrayBuilder();
+      JsonArrayBuilder browseRoles = JsonLoader.createArrayBuilder();
+      JsonArrayBuilder createAddressRoles = JsonLoader.createArrayBuilder();
+      JsonArrayBuilder deleteAddressRoles = JsonLoader.createArrayBuilder();
+      JsonArrayBuilder viewRoles = JsonLoader.createArrayBuilder();
+      JsonArrayBuilder editRoles = JsonLoader.createArrayBuilder();
+
+      for (Role role : roles) {
+         if (role.isSend()) {
+            sendRoles.add(role.getName());
+         }
+         if (role.isConsume()) {
+            consumeRoles.add(role.getName());
+         }
+         if (role.isCreateDurableQueue()) {
+            createDurableQueueRoles.add(role.getName());
+         }
+         if (role.isDeleteDurableQueue()) {
+            deleteDurableQueueRoles.add(role.getName());
+         }
+         if (role.isCreateNonDurableQueue()) {
+            createNonDurableQueueRoles.add(role.getName());
+         }
+         if (role.isDeleteNonDurableQueue()) {
+            deleteNonDurableQueueRoles.add(role.getName());
+         }
+         if (role.isManage()) {
+            manageRoles.add(role.getName());
+         }
+         if (role.isBrowse()) {
+            browseRoles.add(role.getName());
+         }
+         if (role.isCreateAddress()) {
+            createAddressRoles.add(role.getName());
+         }
+         if (role.isDeleteAddress()) {
+            deleteAddressRoles.add(role.getName());
+         }
+         if (role.isView()) {
+            viewRoles.add(role.getName());
+         }
+         if (role.isEdit()) {
+            editRoles.add(role.getName());
+         }
+      }
+      return builder
+         .add(SEND_PERMISSION, sendRoles)
+         .add(CONSUME_PERMISSION, consumeRoles)
+         .add(CREATE_DURABLE_QUEUE_PERMISSION, createDurableQueueRoles)
+         .add(DELETE_DURABLE_QUEUE_PERMISSION, deleteDurableQueueRoles)
+         .add(CREATE_NONDURABLE_QUEUE_PERMISSION, createNonDurableQueueRoles)
+         .add(DELETE_NONDURABLE_QUEUE_PERMISSION, deleteNonDurableQueueRoles)
+         .add(MANAGE_PERMISSION, manageRoles)
+         .add(BROWSE_PERMISSION, browseRoles)
+         .add(CREATE_ADDRESS_PERMISSION, createAddressRoles)
+         .add(DELETE_ADDRESS_PERMISSION, deleteAddressRoles)
+         .add(VIEW_PERMISSION, viewRoles)
+         .add(EDIT_PERMISSION, editRoles)
+         .build().toString();
+   }
+
+   /**
+    * Converts the specified role permissions into a JSON string 
representation. Each permission category maps to an
+    * array of role names.
+    *
+    * @param sendRoles                  a comma-separated string of role names 
allowed to send messages
+    * @param consumeRoles               a comma-separated string of role names 
allowed to consume messages
+    * @param createDurableQueueRoles    a comma-separated string of role names 
allowed to create durable queues
+    * @param deleteDurableQueueRoles    a comma-separated string of role names 
allowed to delete durable queues
+    * @param createNonDurableQueueRoles a comma-separated string of role names 
allowed to create non-durable queues
+    * @param deleteNonDurableQueueRoles a comma-separated string of role names 
allowed to delete non-durable queues
+    * @param manageRoles                a comma-separated string of role names 
allowed to manage resources
+    * @param browseRoles                a comma-separated string of role names 
allowed to browse messages
+    * @param createAddressRoles         a comma-separated string of role names 
allowed to create addresses
+    * @param deleteAddressRoles         a comma-separated string of role names 
allowed to delete addresses
+    * @param viewRoles                  a comma-separated string of role names 
allowed to view resources
+    * @param editRoles                  a comma-separated string of role names 
allowed to edit resources
+    * @return JSON representing the permission types and their associated role 
names. See
+    * {@link ActiveMQServerControl#addSecuritySettings(String, String)} for 
details about the JSON structure.
+    */
+   public static String toJSON(final String sendRoles,
+                               final String consumeRoles,
+                               final String createDurableQueueRoles,
+                               final String deleteDurableQueueRoles,
+                               final String createNonDurableQueueRoles,
+                               final String deleteNonDurableQueueRoles,
+                               final String manageRoles,
+                               final String browseRoles,
+                               final String createAddressRoles,
+                               final String deleteAddressRoles,
+                               final String viewRoles,
+                               final String editRoles) {
+      return JsonLoader.createObjectBuilder()
+         .add(SEND_PERMISSION, JsonUtil.toJsonArray(toListOfRoles(sendRoles)))
+         .add(CONSUME_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(consumeRoles)))
+         .add(CREATE_DURABLE_QUEUE_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(createDurableQueueRoles)))
+         .add(DELETE_DURABLE_QUEUE_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(deleteDurableQueueRoles)))
+         .add(CREATE_NONDURABLE_QUEUE_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(createNonDurableQueueRoles)))
+         .add(DELETE_NONDURABLE_QUEUE_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(deleteNonDurableQueueRoles)))
+         .add(MANAGE_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(manageRoles)))
+         .add(BROWSE_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(browseRoles)))
+         .add(CREATE_ADDRESS_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(createAddressRoles)))
+         .add(DELETE_ADDRESS_PERMISSION, 
JsonUtil.toJsonArray(toListOfRoles(deleteAddressRoles)))
+         .add(VIEW_PERMISSION, JsonUtil.toJsonArray(toListOfRoles(viewRoles)))
+         .add(EDIT_PERMISSION, JsonUtil.toJsonArray(toListOfRoles(editRoles)))
+         .build().toString();
+   }
+
+   /**
+    * Parses a JSON String to create a {@code Set} of {@link Role} objects, 
where each role is assigned specific
+    * permissions based on the data provided in the JSON structure.
+    *
+    * @param json JSON representing the permission types and their associated 
role names. See
+    *             {@link ActiveMQServerControl#addSecuritySettings(String, 
String)} for details about the JSON
+    *             structure.
+    * @return a {@code Set} of {@link Role} objects with permissions assigned 
according to the parsed JSON.
+    */
+   public static Set<Role> fromJSON(JsonObject json) {
+      List<String> sendRoles = getListOfRoles(json, SEND_PERMISSION);
+      List<String> consumeRoles = getListOfRoles(json, CONSUME_PERMISSION);
+      List<String> createDurableQueueRoles = getListOfRoles(json, 
CREATE_DURABLE_QUEUE_PERMISSION);
+      List<String> deleteDurableQueueRoles = getListOfRoles(json, 
DELETE_DURABLE_QUEUE_PERMISSION);
+      List<String> createNonDurableQueueRoles = getListOfRoles(json, 
CREATE_NONDURABLE_QUEUE_PERMISSION);
+      List<String> deleteNonDurableQueueRoles = getListOfRoles(json, 
DELETE_NONDURABLE_QUEUE_PERMISSION);
+      List<String> manageRoles = getListOfRoles(json, MANAGE_PERMISSION);
+      List<String> browseRoles = getListOfRoles(json, BROWSE_PERMISSION);
+      List<String> createAddressRoles = getListOfRoles(json, 
CREATE_ADDRESS_PERMISSION);
+      List<String> deleteAddressRoles = getListOfRoles(json, 
DELETE_ADDRESS_PERMISSION);
+      List<String> viewRoles = getListOfRoles(json, VIEW_PERMISSION);
+      List<String> editRoles = getListOfRoles(json, EDIT_PERMISSION);
+
+      Set<String> allRoles = new HashSet<>();
+      allRoles.addAll(sendRoles);
+      allRoles.addAll(consumeRoles);
+      allRoles.addAll(createDurableQueueRoles);
+      allRoles.addAll(deleteDurableQueueRoles);
+      allRoles.addAll(createNonDurableQueueRoles);
+      allRoles.addAll(deleteNonDurableQueueRoles);
+      allRoles.addAll(manageRoles);
+      allRoles.addAll(browseRoles);
+      allRoles.addAll(createAddressRoles);
+      allRoles.addAll(deleteAddressRoles);
+      allRoles.addAll(viewRoles);
+      allRoles.addAll(editRoles);
+
+      Set<Role> roles = new HashSet<>(allRoles.size());
+      for (String role : allRoles) {
+         roles.add(new Role(role,
+                            sendRoles.contains(role),
+                            consumeRoles.contains(role),
+                            createDurableQueueRoles.contains(role),
+                            deleteDurableQueueRoles.contains(role),
+                            createNonDurableQueueRoles.contains(role),
+                            deleteNonDurableQueueRoles.contains(role),
+                            manageRoles.contains(role),
+                            browseRoles.contains(role),
+                            createAddressRoles.contains(role),
+                            deleteAddressRoles.contains(role),
+                            viewRoles.contains(role),
+                            editRoles.contains(role)));
+      }
+      return roles;
+   }
+
+   /**
+    * Creates a {@code Set} of {@link Role} objects with specific permissions 
based on the provided input role names.
+    *
+    * @param sendRoles                  a comma-separated string of role names 
allowed to send messages
+    * @param consumeRoles               a comma-separated string of role names 
allowed to consume messages
+    * @param createDurableQueueRoles    a comma-separated string of role names 
allowed to create durable queues
+    * @param deleteDurableQueueRoles    a comma-separated string of role names 
allowed to delete durable queues
+    * @param createNonDurableQueueRoles a comma-separated string of roles 
allowed to create non-durable queues
+    * @param deleteNonDurableQueueRoles a comma-separated string of role names 
allowed to delete non-durable queues
+    * @param manageRoles                a comma-separated string of role names 
with manage-level access permissions
+    * @param browseRoles                a comma-separated string of role names 
allowed to browse messages
+    * @param createAddressRoles         a comma-separated string of role names 
allowed to create addresses
+    * @param deleteAddressRoles         a comma-separated string of role names 
allowed to delete addresses
+    * @return a {@code Set} of {@link Role} objects representing the 
permissions assigned to each role
+    */
    public static Set<Role> createSecurity(String sendRoles,
                                           String consumeRoles,
                                           String createDurableQueueRoles,
@@ -36,16 +257,16 @@ public class SecurityFormatter {
                                           String browseRoles,
                                           String createAddressRoles,
                                           String deleteAddressRoles) {
-      List<String> createDurableQueue = toList(createDurableQueueRoles);
-      List<String> deleteDurableQueue = toList(deleteDurableQueueRoles);
-      List<String> createNonDurableQueue = toList(createNonDurableQueueRoles);
-      List<String> deleteNonDurableQueue = toList(deleteNonDurableQueueRoles);
-      List<String> send = toList(sendRoles);
-      List<String> consume = toList(consumeRoles);
-      List<String> manage = toList(manageRoles);
-      List<String> browse = toList(browseRoles);
-      List<String> createAddress = toList(createAddressRoles);
-      List<String> deleteAddress = toList(deleteAddressRoles);
+      List<String> createDurableQueue = toListOfRoles(createDurableQueueRoles);
+      List<String> deleteDurableQueue = toListOfRoles(deleteDurableQueueRoles);
+      List<String> createNonDurableQueue = 
toListOfRoles(createNonDurableQueueRoles);
+      List<String> deleteNonDurableQueue = 
toListOfRoles(deleteNonDurableQueueRoles);
+      List<String> send = toListOfRoles(sendRoles);
+      List<String> consume = toListOfRoles(consumeRoles);
+      List<String> manage = toListOfRoles(manageRoles);
+      List<String> browse = toListOfRoles(browseRoles);
+      List<String> createAddress = toListOfRoles(createAddressRoles);
+      List<String> deleteAddress = toListOfRoles(deleteAddressRoles);
 
       Set<String> allRoles = new HashSet<>();
       allRoles.addAll(createDurableQueue);
@@ -61,16 +282,49 @@ public class SecurityFormatter {
 
       Set<Role> roles = new HashSet<>(allRoles.size());
       for (String role : allRoles) {
-         roles.add(new Role(role, send.contains(role), consume.contains(role), 
createDurableQueue.contains(role), deleteDurableQueue.contains(role), 
createNonDurableQueue.contains(role), deleteNonDurableQueue.contains(role), 
manageRoles.contains(role), browse.contains(role), 
createAddressRoles.contains(role), deleteAddressRoles.contains(role), false, 
false));
+         roles.add(new Role(role,
+                            send.contains(role),
+                            consume.contains(role),
+                            createDurableQueue.contains(role),
+                            deleteDurableQueue.contains(role),
+                            createNonDurableQueue.contains(role),
+                            deleteNonDurableQueue.contains(role),
+                            manageRoles.contains(role),
+                            browse.contains(role),
+                            createAddressRoles.contains(role),
+                            deleteAddressRoles.contains(role),
+                            false,
+                            false));
       }
       return roles;
    }
 
-   @SuppressWarnings("unchecked")
-   private static List<String> toList(final String commaSeparatedString) {
-      if (commaSeparatedString == null || 
commaSeparatedString.trim().isEmpty()) {
+   /**
+    * Retrieves a list of role names from security-settings JSON based on the 
specified permission type.
+    *
+    * @param jsonObject     the {@code JsonObject} containing various 
permission types each mapped to an array of role
+    *                       names.
+    * @param permissionType the specific permission type key to retrieve the 
corresponding list of role names from the
+    *                       JSON object.
+    * @return a {@code List} of strings representing the role names associated 
with the given permission type in the
+    * security-settings JSON.
+    */
+   public static List<String> getListOfRoles(JsonObject jsonObject, String 
permissionType) {
+      return jsonObject.getJsonArray(permissionType) == null ? 
Collections.emptyList() : 
jsonObject.getJsonArray(permissionType).getValuesAs((JsonString v) -> 
v.getString());
+   }
+
+   /**
+    * Converts a comma-separated string of role names into a list of Strings. 
If the input string is null or empty, an
+    * empty list is returned.
+    *
+    * @param commaSeparatedRoles the input string containing role names 
separated by commas
+    * @return a list of Strings populated with the values from the input 
string, or an empty list if the input is null
+    * or empty
+    */
+   public static List<String> toListOfRoles(final String commaSeparatedRoles) {
+      if (commaSeparatedRoles == null || commaSeparatedRoles.trim().isEmpty()) 
{
          return Collections.emptyList();
       }
-      return List.class.cast(Collections.list(new 
StringTokenizer(commaSeparatedString, ", ")));
+      return List.class.cast(Collections.list(new 
StringTokenizer(commaSeparatedRoles, ", ")));
    }
 }
diff --git 
a/artemis-core-client/src/test/java/org/apache/activemq/artemis/api/core/JsonUtilTest.java
 
b/artemis-core-client/src/test/java/org/apache/activemq/artemis/api/core/JsonUtilTest.java
index 52c92eed8c..7c521f4744 100644
--- 
a/artemis-core-client/src/test/java/org/apache/activemq/artemis/api/core/JsonUtilTest.java
+++ 
b/artemis-core-client/src/test/java/org/apache/activemq/artemis/api/core/JsonUtilTest.java
@@ -231,4 +231,23 @@ public class JsonUtilTest {
       assertTrue(inserted.containsKey("c"));
       assertEquals(target, inserted.getJsonObject("c"));
    }
+
+   @Test
+   public void testArrayToString() {
+      final String keyName = "test";
+
+      // test wrong type (i.e. not an array)
+      
assertTrue(JsonUtil.arrayToString(JsonLoader.createObjectBuilder().add(keyName, 
0L).build(), keyName).isEmpty());
+
+      // test empty array
+      
assertTrue(JsonUtil.arrayToString(JsonLoader.createObjectBuilder().build(), 
keyName).isEmpty());
+
+      // test array with 2 elements
+      assertEquals("a, b", 
JsonUtil.arrayToString(JsonLoader.createObjectBuilder()
+                                                     .add(keyName, 
JsonLoader.createArrayBuilder()
+                                                        .add("a")
+                                                        .add("b")
+                                                        .build())
+                                                     .build(), keyName));
+   }
 }
diff --git 
a/artemis-core-client/src/test/java/org/apache/activemq/artemis/util/SecurityFormatterTest.java
 
b/artemis-core-client/src/test/java/org/apache/activemq/artemis/util/SecurityFormatterTest.java
new file mode 100644
index 0000000000..bd7b35ab89
--- /dev/null
+++ 
b/artemis-core-client/src/test/java/org/apache/activemq/artemis/util/SecurityFormatterTest.java
@@ -0,0 +1,191 @@
+/*
+ * 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.util;
+
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.activemq.artemis.api.core.JsonUtil;
+import org.apache.activemq.artemis.core.security.Role;
+import org.apache.activemq.artemis.json.JsonObject;
+import org.apache.activemq.artemis.utils.JsonLoader;
+import org.apache.activemq.artemis.utils.SecurityFormatter;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.activemq.artemis.core.security.Role.BROWSE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CONSUME_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_NONDURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_NONDURABLE_QUEUE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.EDIT_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.MANAGE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.SEND_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.VIEW_PERMISSION;
+import static 
org.apache.activemq.artemis.utils.RandomUtil.randomAlphaNumericString;
+import static org.apache.activemq.artemis.utils.RandomUtil.randomBoolean;
+import static org.apache.activemq.artemis.utils.RandomUtil.randomPositiveInt;
+import static org.apache.activemq.artemis.utils.RandomUtil.randomWords;
+import static org.apache.activemq.artemis.utils.SecurityFormatter.fromJSON;
+import static 
org.apache.activemq.artemis.utils.SecurityFormatter.getListOfRoles;
+import static org.apache.activemq.artemis.utils.SecurityFormatter.toJSON;
+import static 
org.apache.activemq.artemis.utils.SecurityFormatter.toListOfRoles;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class SecurityFormatterTest {
+
+   @Test
+   public void testToJsonFromSet() {
+      Set<Role> originalRoles = new HashSet<>();
+
+      // create several test roles
+      for (int i = 0; i < 10; i++) {
+         boolean[] booleans = new boolean[12];
+         boolean atLeastOneTrue = false;
+
+         // generate a set of permissions that has at least one true value
+         while (!atLeastOneTrue) {
+            for (int j = 0; j < booleans.length; j++) {
+               booleans[j] = randomBoolean();
+               if (booleans[j]) {
+                  atLeastOneTrue = true;
+               }
+            }
+         }
+         originalRoles.add(new Role("role-" + randomAlphaNumericString(6),
+                                    booleans[0],
+                                    booleans[1],
+                                    booleans[2],
+                                    booleans[3],
+                                    booleans[4],
+                                    booleans[5],
+                                    booleans[6],
+                                    booleans[7],
+                                    booleans[8],
+                                    booleans[9],
+                                    booleans[10],
+                                    booleans[11]));
+      }
+
+      assertEquals(originalRoles, 
fromJSON(JsonUtil.readJsonObject(toJSON(originalRoles))));
+   }
+
+   @Test
+   public void testToJsonFromStrings() {
+      String[] roles = new String[12];
+      for (int i = 0; i < roles.length; i++) {
+         roles[i] = String.join(", ", randomWords(randomPositiveInt() % 5 + 
1));
+      }
+
+      String json = toJSON(roles[0],
+                           roles[1],
+                           roles[2],
+                           roles[3],
+                           roles[4],
+                           roles[5],
+                           roles[6],
+                           roles[7],
+                           roles[8],
+                           roles[9],
+                           roles[10],
+                           roles[11]);
+
+      JsonObject o = JsonLoader.readObject(new StringReader(json));
+      assertEquals(toListOfRoles(roles[0]), getListOfRoles(o, 
SEND_PERMISSION));
+      assertEquals(toListOfRoles(roles[1]), getListOfRoles(o, 
CONSUME_PERMISSION));
+      assertEquals(toListOfRoles(roles[2]), getListOfRoles(o, 
CREATE_DURABLE_QUEUE_PERMISSION));
+      assertEquals(toListOfRoles(roles[3]), getListOfRoles(o, 
DELETE_DURABLE_QUEUE_PERMISSION));
+      assertEquals(toListOfRoles(roles[4]), getListOfRoles(o, 
CREATE_NONDURABLE_QUEUE_PERMISSION));
+      assertEquals(toListOfRoles(roles[5]), getListOfRoles(o, 
DELETE_NONDURABLE_QUEUE_PERMISSION));
+      assertEquals(toListOfRoles(roles[6]), getListOfRoles(o, 
MANAGE_PERMISSION));
+      assertEquals(toListOfRoles(roles[7]), getListOfRoles(o, 
BROWSE_PERMISSION));
+      assertEquals(toListOfRoles(roles[8]), getListOfRoles(o, 
CREATE_ADDRESS_PERMISSION));
+      assertEquals(toListOfRoles(roles[9]), getListOfRoles(o, 
DELETE_ADDRESS_PERMISSION));
+      assertEquals(toListOfRoles(roles[10]), getListOfRoles(o, 
VIEW_PERMISSION));
+      assertEquals(toListOfRoles(roles[11]), getListOfRoles(o, 
EDIT_PERMISSION));
+   }
+
+   @Test
+   public void testToJsonVarious() {
+      final String emptyJson = """
+                      
{"send":[],"consume":[],"createDurableQueue":[],"deleteDurableQueue":[],"createNonDurableQueue":[],"deleteNonDurableQueue":[],"manage":[],"browse":[],"createAddress":[],"deleteAddress":[],"view":[],"edit":[]}""";
+      assertEquals(emptyJson,
+                   toJSON("",
+                          "",
+                          "",
+                          "",
+                          "",
+                          "",
+                          "",
+                          "",
+                          "",
+                          "",
+                          "",
+                          ""));
+      assertEquals(emptyJson,
+                   toJSON(null,
+                          null,
+                          null,
+                          null,
+                          null,
+                          null,
+                          null,
+                          null,
+                          null,
+                          null,
+                          null,
+                          null));
+   }
+
+   @Test
+   public void testGetListOfRoles() {
+      String json = """
+       {
+         "send": ["a"],
+         "consume": ["b", "c"],
+         "createDurableQueue": ["d", "e", "f"],
+         "deleteDurableQueue": []
+       }""";
+      JsonObject o = JsonLoader.readObject(new StringReader(json));
+      assertEquals(List.of("a"), SecurityFormatter.getListOfRoles(o, 
SEND_PERMISSION));
+      assertEquals(List.of("b", "c"), SecurityFormatter.getListOfRoles(o, 
CONSUME_PERMISSION));
+      assertEquals(List.of("d", "e", "f"), SecurityFormatter.getListOfRoles(o, 
CREATE_DURABLE_QUEUE_PERMISSION));
+      assertEquals(Collections.emptyList(), 
SecurityFormatter.getListOfRoles(o, DELETE_DURABLE_QUEUE_PERMISSION));
+
+      // test something that doesn't exist
+      assertEquals(Collections.emptyList(), 
SecurityFormatter.getListOfRoles(o, randomAlphaNumericString(4)));
+   }
+
+   @Test
+   public void testToListOfRoles() {
+      assertEquals(Collections.emptyList(), toListOfRoles(""));
+      assertEquals(Collections.emptyList(), toListOfRoles(null));
+
+      assertEquals(List.of("a"), toListOfRoles("a"));
+      assertEquals(List.of("a"), toListOfRoles(" a"));
+      assertEquals(List.of("a"), toListOfRoles("a "));
+      assertEquals(List.of("a"), toListOfRoles(" a "));
+      assertEquals(List.of("a", "b"), toListOfRoles("a,b"));
+      assertEquals(List.of("a", "b"), toListOfRoles("a, b"));
+      assertEquals(List.of("a", "b"), toListOfRoles(" a,  b "));
+   }
+}
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
index ebb479b0c9..f6ad71f36d 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
@@ -151,6 +151,18 @@ import static 
org.apache.activemq.artemis.core.config.impl.Validators.POSITIVE_P
 import static 
org.apache.activemq.artemis.core.config.impl.Validators.ROUTING_TYPE;
 import static 
org.apache.activemq.artemis.core.config.impl.Validators.SLOW_CONSUMER_POLICY_TYPE;
 import static 
org.apache.activemq.artemis.core.config.impl.Validators.SLOW_CONSUMER_THRESHOLD_MEASUREMENT_UNIT;
+import static org.apache.activemq.artemis.core.security.Role.BROWSE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CONSUME_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_NONDURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_NONDURABLE_QUEUE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.EDIT_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.MANAGE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.SEND_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.VIEW_PERMISSION;
 
 /**
  * Parses an XML document according to the {@literal 
artemis-configuration.xsd} schema.
@@ -186,35 +198,13 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
 
    private static final String ROLE_TO_ATTR_NAME = "to";
 
-   static final String CREATEDURABLEQUEUE_NAME = "createDurableQueue";
-
-   private static final String DELETEDURABLEQUEUE_NAME = "deleteDurableQueue";
-
-   private static final String CREATE_NON_DURABLE_QUEUE_NAME = 
"createNonDurableQueue";
-
-   private static final String DELETE_NON_DURABLE_QUEUE_NAME = 
"deleteNonDurableQueue";
-
    // We keep supporting these attribute names for compatibility
+   @Deprecated(forRemoval = true)
    private static final String CREATETEMPQUEUE_NAME = "createTempQueue";
 
+   @Deprecated(forRemoval = true)
    private static final String DELETETEMPQUEUE_NAME = "deleteTempQueue";
 
-   private static final String SEND_NAME = "send";
-
-   private static final String CONSUME_NAME = "consume";
-
-   private static final String MANAGE_NAME = "manage";
-
-   private static final String BROWSE_NAME = "browse";
-
-   private static final String CREATEADDRESS_NAME = "createAddress";
-
-   private static final String DELETEADDRESS_NAME = "deleteAddress";
-
-   private static final String VIEW_NAME = "view";
-
-   private static final String EDIT_NAME = "edit";
-
    // Address parsing
 
    private static final String DEAD_LETTER_ADDRESS_NODE_NAME = 
"dead-letter-address";
@@ -1185,33 +1175,33 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
             String[] mappedRoles = getMappedRoleNames(roles, roleMappings);
 
             for (String role : mappedRoles) {
-               if (SEND_NAME.equals(type)) {
+               if (SEND_PERMISSION.equals(type)) {
                   send.add(role.trim());
-               } else if (CONSUME_NAME.equals(type)) {
+               } else if (CONSUME_PERMISSION.equals(type)) {
                   consume.add(role.trim());
-               } else if (CREATEDURABLEQUEUE_NAME.equals(type)) {
+               } else if (CREATE_DURABLE_QUEUE_PERMISSION.equals(type)) {
                   createDurableQueue.add(role.trim());
-               } else if (DELETEDURABLEQUEUE_NAME.equals(type)) {
+               } else if (DELETE_DURABLE_QUEUE_PERMISSION.equals(type)) {
                   deleteDurableQueue.add(role.trim());
-               } else if (CREATE_NON_DURABLE_QUEUE_NAME.equals(type)) {
+               } else if (CREATE_NONDURABLE_QUEUE_PERMISSION.equals(type)) {
                   createNonDurableQueue.add(role.trim());
-               } else if (DELETE_NON_DURABLE_QUEUE_NAME.equals(type)) {
+               } else if (DELETE_NONDURABLE_QUEUE_PERMISSION.equals(type)) {
                   deleteNonDurableQueue.add(role.trim());
                } else if (CREATETEMPQUEUE_NAME.equals(type)) {
                   createNonDurableQueue.add(role.trim());
                } else if (DELETETEMPQUEUE_NAME.equals(type)) {
                   deleteNonDurableQueue.add(role.trim());
-               } else if (MANAGE_NAME.equals(type)) {
+               } else if (MANAGE_PERMISSION.equals(type)) {
                   manageRoles.add(role.trim());
-               } else if (BROWSE_NAME.equals(type)) {
+               } else if (BROWSE_PERMISSION.equals(type)) {
                   browseRoles.add(role.trim());
-               } else if (CREATEADDRESS_NAME.equals(type)) {
+               } else if (CREATE_ADDRESS_PERMISSION.equals(type)) {
                   createAddressRoles.add(role.trim());
-               } else if (DELETEADDRESS_NAME.equals(type)) {
+               } else if (DELETE_ADDRESS_PERMISSION.equals(type)) {
                   deleteAddressRoles.add(role.trim());
-               } else if (VIEW_NAME.equals(type)) {
+               } else if (VIEW_PERMISSION.equals(type)) {
                   viewRoles.add(role.trim());
-               } else if (EDIT_NAME.equals(type)) {
+               } else if (EDIT_PERMISSION.equals(type)) {
                   editRoles.add(role.trim());
                } else {
                   
ActiveMQServerLogger.LOGGER.rolePermissionConfigurationError(type);
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
index c5cde06c83..d7072f355c 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
@@ -2970,22 +2970,22 @@ public class ActiveMQServerControlImpl extends 
AbstractControl implements Active
                                    final String deleteAddressRoles,
                                    final String viewRoles,
                                    final String editRoles) throws Exception {
+      addSecuritySettings(addressMatch, SecurityFormatter.toJSON(sendRoles, 
consumeRoles, createDurableQueueRoles, deleteDurableQueueRoles, 
createNonDurableQueueRoles, deleteNonDurableQueueRoles, manageRoles, 
browseRoles, createAddressRoles, deleteAddressRoles, viewRoles, editRoles));
+   }
+
+   @Override
+   public void addSecuritySettings(final String addressMatch,
+                                   final String securitySettingsAsJson) throws 
Exception {
       if (AuditLogger.isBaseLoggingEnabled()) {
-         AuditLogger.addSecuritySettings(this.server, addressMatch, sendRoles, 
consumeRoles, createDurableQueueRoles,
-                  deleteDurableQueueRoles, createNonDurableQueueRoles, 
deleteNonDurableQueueRoles, manageRoles,
-                  browseRoles, createAddressRoles, deleteAddressRoles, 
viewRoles, editRoles);
+         AuditLogger.addSecuritySettings(this.server, addressMatch, 
securitySettingsAsJson);
       }
       checkStarted();
 
       clearIO();
       try {
-         Set<Role> roles = SecurityFormatter.createSecurity(sendRoles, 
consumeRoles, createDurableQueueRoles, deleteDurableQueueRoles, 
createNonDurableQueueRoles, deleteNonDurableQueueRoles, manageRoles, 
browseRoles, createAddressRoles, deleteAddressRoles);
-
-         server.getSecurityRepository().addMatch(addressMatch, roles);
-
-         PersistedSecuritySetting persistedRoles = new 
PersistedSecuritySetting(addressMatch, sendRoles, consumeRoles, 
createDurableQueueRoles, deleteDurableQueueRoles, createNonDurableQueueRoles, 
deleteNonDurableQueueRoles, manageRoles, browseRoles, createAddressRoles, 
deleteAddressRoles, viewRoles, editRoles);
-
-         storageManager.storeSecuritySetting(persistedRoles);
+         JsonObject o = JsonUtil.readJsonObject(securitySettingsAsJson);
+         server.getSecurityRepository().addMatch(addressMatch, 
SecurityFormatter.fromJSON(o));
+         storageManager.storeSecuritySetting(new 
PersistedSecuritySetting(addressMatch, o));
       } finally {
          blockOnIO();
       }
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/config/PersistedSecuritySetting.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/config/PersistedSecuritySetting.java
index d179239ee2..2a679db0f3 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/config/PersistedSecuritySetting.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/config/PersistedSecuritySetting.java
@@ -19,9 +19,23 @@ package org.apache.activemq.artemis.core.persistence.config;
 import java.util.Objects;
 
 import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
+import org.apache.activemq.artemis.api.core.JsonUtil;
 import org.apache.activemq.artemis.api.core.SimpleString;
 import org.apache.activemq.artemis.core.journal.EncodingSupport;
-
+import org.apache.activemq.artemis.json.JsonObject;
+
+import static org.apache.activemq.artemis.core.security.Role.BROWSE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CONSUME_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.CREATE_NONDURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_ADDRESS_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_DURABLE_QUEUE_PERMISSION;
+import static 
org.apache.activemq.artemis.core.security.Role.DELETE_NONDURABLE_QUEUE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.EDIT_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.MANAGE_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.SEND_PERMISSION;
+import static org.apache.activemq.artemis.core.security.Role.VIEW_PERMISSION;
 import static org.apache.activemq.artemis.utils.DataConstants.SIZE_INT;
 import static org.apache.activemq.artemis.utils.DataConstants.SIZE_NULL;
 
@@ -88,6 +102,22 @@ public class PersistedSecuritySetting implements 
EncodingSupport {
       this.editRoles = SimpleString.of(editRoles);
    }
 
+   public PersistedSecuritySetting(final String addressMatch, JsonObject o) {
+      this(addressMatch,
+           JsonUtil.arrayToString(o, SEND_PERMISSION),
+           JsonUtil.arrayToString(o, CONSUME_PERMISSION),
+           JsonUtil.arrayToString(o, CREATE_DURABLE_QUEUE_PERMISSION),
+           JsonUtil.arrayToString(o, DELETE_DURABLE_QUEUE_PERMISSION),
+           JsonUtil.arrayToString(o, CREATE_NONDURABLE_QUEUE_PERMISSION),
+           JsonUtil.arrayToString(o, DELETE_NONDURABLE_QUEUE_PERMISSION),
+           JsonUtil.arrayToString(o, MANAGE_PERMISSION),
+           JsonUtil.arrayToString(o, BROWSE_PERMISSION),
+           JsonUtil.arrayToString(o, CREATE_ADDRESS_PERMISSION),
+           JsonUtil.arrayToString(o, DELETE_ADDRESS_PERMISSION),
+           JsonUtil.arrayToString(o, VIEW_PERMISSION),
+           JsonUtil.arrayToString(o, EDIT_PERMISSION));
+   }
+
 
    public long getStoreId() {
       return storeId;
@@ -243,30 +273,18 @@ public class PersistedSecuritySetting implements 
EncodingSupport {
    @Override
    public String toString() {
       return "PersistedSecuritySetting [storeId=" + storeId +
-         ", addressMatch=" +
-         addressMatch +
-         ", sendRoles=" +
-         sendRoles +
-         ", consumeRoles=" +
-         consumeRoles +
-         ", createDurableQueueRoles=" +
-         createDurableQueueRoles +
-         ", deleteDurableQueueRoles=" +
-         deleteDurableQueueRoles +
-         ", createNonDurableQueueRoles=" +
-         createNonDurableQueueRoles +
-         ", deleteNonDurableQueueRoles=" +
-         deleteNonDurableQueueRoles +
-         ", manageRoles=" +
-         manageRoles +
-         ", browseRoles=" +
-         browseRoles +
-         ", createAddressRoles=" +
-         createAddressRoles +
-         ", deleteAddressRoles=" +
-         deleteAddressRoles +
-         ", viewRoles=" +
-         viewRoles +
+         ", addressMatch=" + addressMatch +
+         ", sendRoles=" + sendRoles +
+         ", consumeRoles=" + consumeRoles +
+         ", createDurableQueueRoles=" + createDurableQueueRoles +
+         ", deleteDurableQueueRoles=" + deleteDurableQueueRoles +
+         ", createNonDurableQueueRoles=" + createNonDurableQueueRoles +
+         ", deleteNonDurableQueueRoles=" + deleteNonDurableQueueRoles +
+         ", manageRoles=" + manageRoles +
+         ", browseRoles=" + browseRoles +
+         ", createAddressRoles=" + createAddressRoles +
+         ", deleteAddressRoles=" + deleteAddressRoles +
+         ", viewRoles=" + viewRoles +
          ", editRoles=" + editRoles +
          "]";
    }
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 cbea15b803..98feca733d 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
@@ -3891,8 +3891,17 @@ public class ActiveMQServerImpl implements 
ActiveMQServer {
    private void recoverStoredSecuritySettings() throws Exception {
       List<PersistedSecuritySetting> roles = 
storageManager.recoverSecuritySettings();
       for (PersistedSecuritySetting roleItem : roles) {
-         Set<Role> 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);
+         securityRepository.addMatch(roleItem.getAddressMatch().toString(),
+                                     
SecurityFormatter.createSecurity(roleItem.getSendRoles(),
+                                                                      
roleItem.getConsumeRoles(),
+                                                                      
roleItem.getCreateDurableQueueRoles(),
+                                                                      
roleItem.getDeleteDurableQueueRoles(),
+                                                                      
roleItem.getCreateNonDurableQueueRoles(),
+                                                                      
roleItem.getDeleteNonDurableQueueRoles(),
+                                                                      
roleItem.getManageRoles(),
+                                                                      
roleItem.getBrowseRoles(),
+                                                                      
roleItem.getCreateAddressRoles(),
+                                                                      
roleItem.getDeleteAddressRoles()));
       }
    }
 
diff --git 
a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java
 
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java
index 439fd45e5a..5d046a3692 100644
--- 
a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java
+++ 
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java
@@ -135,6 +135,7 @@ import 
org.apache.activemq.artemis.tests.unit.core.config.impl.fakes.FakeConnect
 import org.apache.activemq.artemis.tests.util.CFUtil;
 import org.apache.activemq.artemis.tests.util.Wait;
 import org.apache.activemq.artemis.utils.RandomUtil;
+import org.apache.activemq.artemis.utils.SecurityFormatter;
 import org.apache.activemq.artemis.utils.UUIDGenerator;
 import org.apache.qpid.jms.JmsConnectionFactory;
 import org.junit.jupiter.api.BeforeEach;
@@ -1174,12 +1175,63 @@ public class ActiveMQServerControlTest extends 
ManagementTestBase {
 
    @TestTemplate
    public void testSecuritySettings() throws Exception {
+      testSecuritySettings(false);
+   }
+
+
+   @TestTemplate
+   public void testSecuritySettingsJson() throws Exception {
+      testSecuritySettings(true);
+   }
+
+   private void testSecuritySettings(boolean json) throws Exception {
       ActiveMQServerControl serverControl = createManagementControl();
       String addressMatch = "test.#";
       String exactAddress = "test.whatever";
 
       assertEquals(2, serverControl.getRoles(addressMatch).length);
-      serverControl.addSecuritySettings(addressMatch, "foo", "foo, bar", null, 
"bar", "foo, bar", "", "", "bar", "foo", "foo", "", "");
+      final String sendRoles = "foo";
+      final String consumeRoles = "foo, bar";
+      final String createDurableQueueRoles = null;
+      final String deleteDurableQueueRoles = "bar";
+      final String createNonDurableQueueRoles = "foo, bar";
+      final String deleteNonDurableQueueRoles = "";
+      final String manageRoles = "";
+      final String browseRoles = "bar";
+      final String createAddressRoles = "foo";
+      final String deleteAddressRoles = "foo";
+      final String viewRoles = "";
+      final String editRoles = "";
+
+      if (json) {
+         serverControl.addSecuritySettings(addressMatch,
+                                           SecurityFormatter.toJSON(sendRoles,
+                                                                    
consumeRoles,
+                                                                    
createDurableQueueRoles,
+                                                                    
deleteDurableQueueRoles,
+                                                                    
createNonDurableQueueRoles,
+                                                                    
deleteNonDurableQueueRoles,
+                                                                    
manageRoles,
+                                                                    
browseRoles,
+                                                                    
createAddressRoles,
+                                                                    
deleteAddressRoles,
+                                                                    viewRoles,
+                                                                    
editRoles));
+      } else {
+         serverControl.addSecuritySettings(addressMatch,
+                                           sendRoles,
+                                           consumeRoles,
+                                           createDurableQueueRoles,
+                                           deleteDurableQueueRoles,
+                                           createNonDurableQueueRoles,
+                                           deleteNonDurableQueueRoles,
+                                           manageRoles,
+                                           browseRoles,
+                                           createAddressRoles,
+                                           deleteAddressRoles,
+                                           viewRoles,
+                                           editRoles);
+      }
 
       // Restart the server. Those settings should be persisted
 
diff --git 
a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java
 
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java
index b37cab4b33..eaefaad994 100644
--- 
a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java
+++ 
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java
@@ -1010,6 +1010,11 @@ public class ActiveMQServerControlUsingCoreTest extends 
ActiveMQServerControlTes
             proxy.invokeOperation("addSecuritySettings", addressMatch, 
sendRoles, consumeRoles, createDurableQueueRoles, deleteDurableQueueRoles, 
createNonDurableQueueRoles, deleteNonDurableQueueRoles, manageRoles, 
browseRoles, createAddress, deleteAddress, viewRoles, editRoles);
          }
 
+         @Override
+         public void addSecuritySettings(String addressMatch, String 
securitySettingsAsJson) throws Exception {
+            proxy.invokeOperation("addSecuritySettings", addressMatch, 
securitySettingsAsJson);
+         }
+
          @Override
          public void removeSecuritySettings(String addressMatch) throws 
Exception {
             proxy.invokeOperation("removeSecuritySettings", addressMatch);
diff --git 
a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/util/RandomUtilTest.java
 
b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/util/RandomUtilTest.java
index 6ebc2407af..8d6e1b8d76 100644
--- 
a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/util/RandomUtilTest.java
+++ 
b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/util/RandomUtilTest.java
@@ -16,12 +16,12 @@
  */
 package org.apache.activemq.artemis.tests.unit.core.util;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
 import org.apache.activemq.artemis.utils.RandomUtil;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 public class RandomUtilTest {
 
 
@@ -38,4 +38,17 @@ public class RandomUtilTest {
       assertEquals(10, i);
 
    }
+
+   @Test
+   public void testRandomWords() {
+      for (int i = 0; i < 1000; i++) {
+         int wordCount = RandomUtil.randomPositiveInt() % 100 + 10;
+         String[] words = RandomUtil.randomWords(wordCount);
+         assertEquals(wordCount, words.length);
+         for (String word : words) {
+            assertTrue(word.length() > 0);
+            assertTrue(word.length() <= 10);
+         }
+      }
+   }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to