Skip to content

Commit acf60a8

Browse files
jbertramtabish121
authored andcommitted
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.
1 parent 21e6684 commit acf60a8

File tree

16 files changed

+854
-259
lines changed

16 files changed

+854
-259
lines changed

artemis-commons/src/main/java/org/apache/activemq/artemis/utils/JsonLoader.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@
2626
import org.apache.activemq.artemis.json.impl.JsonObjectImpl;
2727

2828
import javax.json.JsonReader;
29+
import javax.json.JsonWriter;
2930
import javax.json.spi.JsonProvider;
3031
import java.io.Reader;
32+
import java.io.StringReader;
33+
import java.io.StringWriter;
34+
import java.io.Writer;
35+
import java.util.Map;
3136

3237
/**
3338
* This is to make sure we use the proper classLoader to load JSon libraries. This is equivalent to using
@@ -43,6 +48,12 @@ public static JsonObject readObject(Reader reader) {
4348
}
4449
}
4550

51+
public static void writeObject(Map<String, Object> properties, Writer writer, JsonObject jsonObject) {
52+
try (JsonWriter jsonReader = provider.createWriterFactory(properties).createWriter(writer)) {
53+
jsonReader.writeObject((((JsonObjectImpl)jsonObject).getRawObject()));
54+
}
55+
}
56+
4657
public static JsonArray readArray(Reader reader) {
4758
try (JsonReader jsonReader = provider.createReader(reader)) {
4859
return new JsonArrayImpl(jsonReader.readArray());
@@ -56,4 +67,16 @@ public static JsonArrayBuilder createArrayBuilder() {
5667
public static JsonObjectBuilder createObjectBuilder() {
5768
return new JsonObjectBuilderImpl(provider.createObjectBuilder());
5869
}
70+
71+
// Please do not remove this method as it's useful for debugging purposes
72+
public static String prettyPrint(String json) {
73+
String result = json;
74+
try (StringReader reader = new StringReader(json);
75+
StringWriter writer = new StringWriter()) {
76+
JsonLoader.writeObject(Map.of(javax.json.stream.JsonGenerator.PRETTY_PRINTING, true), writer, JsonLoader.readObject(reader));
77+
result = writer.toString();
78+
} catch (Exception e) {
79+
}
80+
return result;
81+
}
5982
}

artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,18 @@ public static float randomFloat() {
175175
return RandomUtil.random.nextFloat();
176176
}
177177

178+
/**
179+
* Generates an array of random alpha-numeric words. The words will be of a random length between 1 and 10
180+
* characters.
181+
*
182+
* @param wordCount the number of random words to generate
183+
* @return an array of randomly generated alpha-numeric words between 1 and 10 characters long
184+
*/
185+
public static String[] randomWords(int wordCount) {
186+
String[] words = new String[wordCount];
187+
for (int i = 0; i < wordCount; i++) {
188+
words[i] = randomAlphaNumericString((randomPositiveInt() % 10) + 1);
189+
}
190+
return words;
191+
}
178192
}

artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/JsonUtil.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.List;
2727
import java.util.Map;
2828
import java.util.Set;
29+
import java.util.stream.Collectors;
2930

3031
import org.apache.activemq.artemis.json.JsonArray;
3132
import org.apache.activemq.artemis.json.JsonArrayBuilder;
@@ -456,4 +457,21 @@ public String toString() {
456457
return s;
457458
}
458459
}
460+
461+
/**
462+
* Converts a JSON array from the specified key in a JsonObject into a comma-separated string. If the key does not
463+
* exist or if its value is not a JSON array, then an empty string is returned.
464+
*
465+
* @param jsonObject the JsonObject from which to retrieve the array
466+
* @param key the key associated with the JSON array in the JsonObject
467+
* @return a comma-separated string representation of the array's elements, or an empty string if the key does not
468+
* exist or the value is not an array
469+
*/
470+
public static String arrayToString(JsonObject jsonObject, String key) {
471+
JsonValue value = jsonObject.get(key);
472+
if (value == null || value.getValueType() != JsonValue.ValueType.ARRAY) {
473+
return "";
474+
}
475+
return jsonObject.getJsonArray(key).stream().map((s) -> ((JsonString) s).getString()).collect(Collectors.joining(", "));
476+
}
459477
}

artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,10 @@ boolean closeConsumerWithID(@Parameter(desc = "The session ID", name = "sessionI
13821382
@Operation(desc = "List the sessions for the given connectionID", impact = MBeanOperationInfo.INFO)
13831383
String[] listSessions(@Parameter(desc = "a connection ID", name = "connectionID") String connectionID) throws Exception;
13841384

1385+
/**
1386+
* @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, String)}
1387+
*/
1388+
@Deprecated(forRemoval = true)
13851389
@Operation(desc = "Add security settings for addresses matching the addressMatch", impact = MBeanOperationInfo.ACTION)
13861390
void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMatch") String addressMatch,
13871391
@Parameter(desc = "a comma-separated list of roles allowed to send messages", name = "send") String sendRoles,
@@ -1392,6 +1396,10 @@ void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMa
13921396
@Parameter(desc = "a comma-separated list of roles allowed to delete non durable queues", name = "deleteNonDurableQueueRoles") String deleteNonDurableQueueRoles,
13931397
@Parameter(desc = "a comma-separated list of roles allowed to send management messages messages", name = "manage") String manageRoles) throws Exception;
13941398

1399+
/**
1400+
* @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, String)}
1401+
*/
1402+
@Deprecated(forRemoval = true)
13951403
@Operation(desc = "Add security settings for addresses matching the addressMatch", impact = MBeanOperationInfo.ACTION)
13961404
void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMatch") String addressMatch,
13971405
@Parameter(desc = "a comma-separated list of roles allowed to send messages", name = "send") String sendRoles,
@@ -1403,6 +1411,10 @@ void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMa
14031411
@Parameter(desc = "a comma-separated list of roles allowed to send management messages messages", name = "manage") String manageRoles,
14041412
@Parameter(desc = "a comma-separated list of roles allowed to browse queues", name = "browse") String browseRoles) throws Exception;
14051413

1414+
/**
1415+
* @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, String)}
1416+
*/
1417+
@Deprecated(forRemoval = true)
14061418
@Operation(desc = "Add security settings for addresses matching the addressMatch", impact = MBeanOperationInfo.ACTION)
14071419
void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMatch") String addressMatch,
14081420
@Parameter(desc = "a comma-separated list of roles allowed to send messages", name = "send") String sendRoles,
@@ -1416,6 +1428,10 @@ void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMa
14161428
@Parameter(desc = "a comma-separated list of roles allowed to create addresses", name = "createAddressRoles") String createAddressRoles,
14171429
@Parameter(desc = "a comma-separated list of roles allowed to delete addresses", name = "deleteAddressRoles") String deleteAddressRoles) throws Exception;
14181430

1431+
/**
1432+
* @deprecated use {@link ActiveMQServerControl#addSecuritySettings(String, String)}
1433+
*/
1434+
@Deprecated(forRemoval = true)
14191435
@Operation(desc = "Add security settings for addresses matching the addressMatch", impact = MBeanOperationInfo.ACTION)
14201436
void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMatch") String addressMatch,
14211437
@Parameter(desc = "a comma-separated list of roles allowed to send messages", name = "send") String sendRoles,
@@ -1431,6 +1447,43 @@ void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMa
14311447
@Parameter(desc = "a comma-separated list of roles allowed to view management resources", name = "view") String viewRoles,
14321448
@Parameter(desc = "a comma-separated list of roles allowed to edit management resources", name = "edit") String editRoles) throws Exception;
14331449

1450+
/**
1451+
* Add security-settings for matching addresses.
1452+
*
1453+
* @param addressMatch The address match pattern to which the security-settings will be applied.
1454+
* @param securitySettingsAsJson The security-settings in JSON format. The JSON consists of key/value pairs where the
1455+
* key is a string representing the permission type, and the value is an array of
1456+
* strings containing the names of the roles which will be granted the corresponding
1457+
* permission, e.g.:
1458+
* <pre>{@code
1459+
* {
1460+
* "send": ["role1", "role2"],
1461+
* "consume": ["role3", "role4"],
1462+
* "createDurableQueue": ["role5", "role6"]
1463+
* }
1464+
* }</pre>
1465+
* These permission types are supported:
1466+
* <ul>
1467+
* <li>send</li>
1468+
* <li>consume</li>
1469+
* <li>createDurableQueue</li>
1470+
* <li>deleteDurableQueue</li>
1471+
* <li>createNonDurableQueue</li>
1472+
* <li>deleteNonDurableQueue</li>
1473+
* <li>manage</li>
1474+
* <li>browse</li>
1475+
* <li>createAddress</li>
1476+
* <li>deleteAddress</li>
1477+
* <li>view</li>
1478+
* <li>edit</li>
1479+
* </ul>
1480+
* This JSON can be constructed using methods from {@link org.apache.activemq.artemis.utils.SecurityFormatter}.
1481+
* @throws Exception If an error occurs while adding the security-settings.
1482+
*/
1483+
@Operation(desc = "Add security-settings for matching addresses", impact = MBeanOperationInfo.ACTION)
1484+
void addSecuritySettings(@Parameter(desc = "an address match", name = "addressMatch") String addressMatch,
1485+
@Parameter(desc = "The configuration of the security-settings as JSON", name = "securitySettingsAsJson") String securitySettingsAsJson) throws Exception;
1486+
14341487
@Operation(desc = "Remove security settings for an address", impact = MBeanOperationInfo.ACTION)
14351488
void removeSecuritySettings(@Parameter(desc = "an address match", name = "addressMatch") String addressMatch) throws Exception;
14361489

@@ -1685,7 +1738,7 @@ void addAddressSettings(@Parameter(desc = "an address match", name = "addressMat
16851738
* adds a new address setting for a specific address
16861739
*/
16871740
@Operation(desc = "Add address settings for addresses matching the addressMatch", impact = MBeanOperationInfo.ACTION)
1688-
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;
1741+
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;
16891742

16901743
@Operation(desc = "Remove address settings", impact = MBeanOperationInfo.ACTION)
16911744
void removeAddressSettings(@Parameter(desc = "an address match", name = "addressMatch") String addressMatch) throws Exception;

artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/RoleInfo.java

Lines changed: 13 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,15 @@
1616
*/
1717
package org.apache.activemq.artemis.api.core.management;
1818

19+
import org.apache.activemq.artemis.api.core.JsonUtil;
20+
import org.apache.activemq.artemis.core.security.Role;
1921
import org.apache.activemq.artemis.json.JsonArray;
2022
import org.apache.activemq.artemis.json.JsonObject;
2123

22-
import org.apache.activemq.artemis.api.core.JsonUtil;
23-
2424
/**
2525
* Helper class to create Java Objects from the JSON serialization returned by {@link AddressControl#getRolesAsJSON()}.
2626
*/
27-
public final class RoleInfo {
28-
29-
private final String name;
30-
31-
private final boolean send;
32-
33-
private final boolean consume;
34-
35-
private final boolean createDurableQueue;
36-
37-
private final boolean deleteDurableQueue;
38-
39-
private final boolean createNonDurableQueue;
40-
41-
private final boolean deleteNonDurableQueue;
42-
43-
private final boolean manage;
44-
45-
private final boolean browse;
46-
47-
private final boolean createAddress;
48-
49-
private final boolean deleteAddress;
27+
public final class RoleInfo extends Role {
5028

5129
/**
5230
* {@return an array of RoleInfo corresponding to the JSON serialization returned by {@link
@@ -59,16 +37,16 @@ public static RoleInfo[] from(final String jsonString) throws Exception {
5937
JsonObject r = array.getJsonObject(i);
6038
RoleInfo role = new RoleInfo(
6139
r.getString("name"),
62-
r.getBoolean("send"),
63-
r.getBoolean("consume"),
64-
r.getBoolean("createDurableQueue"),
65-
r.getBoolean("deleteDurableQueue"),
66-
r.getBoolean("createNonDurableQueue"),
67-
r.getBoolean("deleteNonDurableQueue"),
68-
r.getBoolean("manage"),
69-
r.getBoolean("browse"),
70-
r.getBoolean("createAddress"),
71-
r.getBoolean("deleteAddress"));
40+
r.getBoolean(SEND_PERMISSION),
41+
r.getBoolean(CONSUME_PERMISSION),
42+
r.getBoolean(CREATE_DURABLE_QUEUE_PERMISSION),
43+
r.getBoolean(DELETE_DURABLE_QUEUE_PERMISSION),
44+
r.getBoolean(CREATE_NONDURABLE_QUEUE_PERMISSION),
45+
r.getBoolean(DELETE_NONDURABLE_QUEUE_PERMISSION),
46+
r.getBoolean(MANAGE_PERMISSION),
47+
r.getBoolean(BROWSE_PERMISSION),
48+
r.getBoolean(CREATE_ADDRESS_PERMISSION),
49+
r.getBoolean(DELETE_ADDRESS_PERMISSION));
7250
roles[i] = role;
7351
}
7452
return roles;
@@ -97,78 +75,4 @@ private RoleInfo(final String name,
9775
this.createAddress = createAddress;
9876
this.deleteAddress = deleteAddress;
9977
}
100-
101-
public String getName() {
102-
return name;
103-
}
104-
105-
/**
106-
* {@return whether this role can send messages to the address}
107-
*/
108-
public boolean isSend() {
109-
return send;
110-
}
111-
112-
/**
113-
* {@return whether this role can consume messages from queues bound to the address}
114-
*/
115-
public boolean isConsume() {
116-
return consume;
117-
}
118-
119-
/**
120-
* {@return whether this role can create durable queues bound to the address}
121-
*/
122-
public boolean isCreateDurableQueue() {
123-
return createDurableQueue;
124-
}
125-
126-
/**
127-
* {@return whether this role can delete durable queues bound to the address}
128-
*/
129-
public boolean isDeleteDurableQueue() {
130-
return deleteDurableQueue;
131-
}
132-
133-
/**
134-
* {@return whether this role can create non-durable queues bound to the address}
135-
*/
136-
public boolean isCreateNonDurableQueue() {
137-
return createNonDurableQueue;
138-
}
139-
140-
/**
141-
* {@return whether this role can delete non-durable queues bound to the address}
142-
*/
143-
public boolean isDeleteNonDurableQueue() {
144-
return deleteNonDurableQueue;
145-
}
146-
147-
/**
148-
* {@return whether this role can send management messages to the address}
149-
*/
150-
public boolean isManage() {
151-
return manage;
152-
}
153-
154-
/**
155-
* {@return whether this role can browse queues bound to the address}
156-
*/
157-
public boolean isBrowse() {
158-
return browse;
159-
}
160-
161-
/**
162-
* {@return whether this role can create addresses}
163-
*/
164-
public boolean isCreateAddress() {
165-
return createAddress;
166-
}
167-
168-
/**
169-
* {@return whether this role can delete addresses}
170-
*/
171-
public boolean isDeleteAddress() {
172-
return deleteAddress;
173-
}
17478
}

0 commit comments

Comments
 (0)