Skip to content

Commit 8d1df1f

Browse files
committed
ARTEMIS-6115 Add JMH test for SecurityManagerUtil.authorize
1 parent 9754483 commit 8d1df1f

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.activemq.artemis.tests.performance.jmh;
18+
19+
import org.apache.activemq.artemis.core.security.CheckType;
20+
import org.apache.activemq.artemis.core.security.Role;
21+
import org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal;
22+
import org.apache.activemq.artemis.utils.SecurityManagerUtil;
23+
import org.openjdk.jmh.annotations.Benchmark;
24+
import org.openjdk.jmh.annotations.BenchmarkMode;
25+
import org.openjdk.jmh.annotations.Fork;
26+
import org.openjdk.jmh.annotations.Measurement;
27+
import org.openjdk.jmh.annotations.Mode;
28+
import org.openjdk.jmh.annotations.Param;
29+
import org.openjdk.jmh.annotations.Scope;
30+
import org.openjdk.jmh.annotations.Setup;
31+
import org.openjdk.jmh.annotations.State;
32+
import org.openjdk.jmh.annotations.Warmup;
33+
34+
import javax.security.auth.Subject;
35+
import java.util.ArrayList;
36+
import java.util.HashSet;
37+
import java.util.List;
38+
import java.util.Set;
39+
import java.util.concurrent.ThreadLocalRandom;
40+
41+
@State(Scope.Benchmark)
42+
@Fork(1)
43+
@Warmup(iterations = 4, time = 1)
44+
@Measurement(iterations = 4, time = 1)
45+
@BenchmarkMode(Mode.Throughput)
46+
public class SecurityManagerUtilAuthorizePerfTest {
47+
48+
/* Total number of roles in the resource ACL */
49+
@Param({"8", "1024"})
50+
int roleCount;
51+
52+
/* Number of roles assigned to each subject */
53+
@Param({"8", "64"})
54+
int subjectRoleCount;
55+
56+
private Set<Role> roles;
57+
58+
private Subject adminSubject; // all permissions
59+
private Subject producerSubject; // send + consume
60+
private Subject monitorSubject; // manage + browse
61+
private Subject guestSubject; // no permissions
62+
63+
private Subject[] subjects;
64+
65+
private static final CheckType SEND = CheckType.SEND;
66+
private static final CheckType CONSUME = CheckType.CONSUME;
67+
private static final CheckType MANAGE = CheckType.MANAGE;
68+
private static final CheckType[] CHECK_TYPES = {SEND, CONSUME, MANAGE};
69+
70+
@Setup
71+
public void init() {
72+
List<Role> roleList = new ArrayList<>(roleCount);
73+
74+
for (int i = 0; i < roleCount / 4; i++) {
75+
roleList.add(new Role("role-t0-" + i, true, true, true, true, true, true, true, true, true, true)); // all permissions
76+
roleList.add(new Role("role-t1-" + i, true, true, false, false, false, false, false, false, false, false)); // send + consume
77+
roleList.add(new Role("role-t2-" + i, false, false, false, false, false, false, true, true, false, false)); // manage + browse
78+
roleList.add(new Role("role-t3-" + i, false, false, false, false, false, false, false, false, false, false)); // no permissions
79+
}
80+
81+
roles = new HashSet<>(roleList);
82+
83+
subjects = new Subject[4];
84+
for (int tier = 0; tier < 4; tier++) {
85+
Subject s = new Subject();
86+
for (int i = 0; i < subjectRoleCount; i++) {
87+
s.getPrincipals().add(new RolePrincipal(roleList.get((tier + i * 4) % roleList.size()).getName()));
88+
}
89+
subjects[tier] = s;
90+
}
91+
92+
adminSubject = subjects[0];
93+
producerSubject = subjects[1];
94+
monitorSubject = subjects[2];
95+
guestSubject = subjects[3];
96+
97+
}
98+
99+
@Benchmark
100+
public boolean testAdminSend() {
101+
return SecurityManagerUtil.authorize(adminSubject, roles, SEND, RolePrincipal.class);
102+
}
103+
104+
@Benchmark
105+
public boolean testProducerSend() {
106+
return SecurityManagerUtil.authorize(producerSubject, roles, SEND, RolePrincipal.class);
107+
}
108+
109+
@Benchmark
110+
public boolean testProducerConsume() {
111+
return SecurityManagerUtil.authorize(producerSubject, roles, CONSUME, RolePrincipal.class);
112+
}
113+
114+
@Benchmark
115+
public boolean testMonitorManage() {
116+
return SecurityManagerUtil.authorize(monitorSubject, roles, MANAGE, RolePrincipal.class);
117+
}
118+
119+
/*monitor checking SEND — rolesWithPermission is non-empty (tier-0 and tier-1 have send) but none of monitor's principals match, so the inner loop exhausts. */
120+
@Benchmark
121+
public boolean testMonitorSendDenied() {
122+
return SecurityManagerUtil.authorize(monitorSubject, roles, SEND, RolePrincipal.class);
123+
}
124+
125+
/** guest checking SEND — same denial path, models high-volume anonymous traffic. */
126+
@Benchmark
127+
public boolean testGuestSendDenied() {
128+
return SecurityManagerUtil.authorize(guestSubject, roles, SEND, RolePrincipal.class);
129+
}
130+
131+
@Benchmark
132+
public boolean testMixedRealisticLoad() {
133+
ThreadLocalRandom rng = ThreadLocalRandom.current();
134+
Subject subject = subjects[rng.nextInt(4)];
135+
CheckType check = CHECK_TYPES[rng.nextInt(3)];
136+
return SecurityManagerUtil.authorize(subject, roles, check, RolePrincipal.class);
137+
}
138+
139+
}

0 commit comments

Comments
 (0)