1 /* |
1 /* |
2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
35 import java.util.ArrayList; |
35 import java.util.ArrayList; |
36 import java.util.Collections; |
36 import java.util.Collections; |
37 import java.util.HashMap; |
37 import java.util.HashMap; |
38 import java.util.List; |
38 import java.util.List; |
39 import java.util.Map; |
39 import java.util.Map; |
|
40 import java.util.concurrent.CopyOnWriteArrayList; |
|
41 import java.util.concurrent.Semaphore; |
40 import javax.management.MBeanServer; |
42 import javax.management.MBeanServer; |
41 import javax.management.MBeanServerConnection; |
43 import javax.management.MBeanServerConnection; |
42 import javax.management.MBeanServerFactory; |
44 import javax.management.MBeanServerFactory; |
43 import javax.management.Notification; |
45 import javax.management.Notification; |
44 import javax.management.NotificationBroadcasterSupport; |
46 import javax.management.NotificationBroadcasterSupport; |
54 import javax.security.auth.Subject; |
56 import javax.security.auth.Subject; |
55 |
57 |
56 public class NotificationAccessControllerTest { |
58 public class NotificationAccessControllerTest { |
57 |
59 |
58 public class NAC implements NotificationAccessController { |
60 public class NAC implements NotificationAccessController { |
59 private boolean throwException; |
61 private final boolean throwException; |
60 public NAC(boolean throwException) { |
62 public NAC(boolean throwException) { |
61 this.throwException = throwException; |
63 this.throwException = throwException; |
62 } |
64 } |
|
65 |
|
66 @Override |
63 public void addNotificationListener( |
67 public void addNotificationListener( |
64 String connectionId, |
68 String connectionId, |
65 ObjectName name, |
69 ObjectName name, |
66 Subject subject) |
70 Subject subject) |
67 throws SecurityException { |
71 throws SecurityException { |
71 echo("\tsubject: " + |
75 echo("\tsubject: " + |
72 (subject == null ? null : subject.getPrincipals())); |
76 (subject == null ? null : subject.getPrincipals())); |
73 if (throwException) |
77 if (throwException) |
74 if (name.getCanonicalName().equals("domain:name=1,type=NB") |
78 if (name.getCanonicalName().equals("domain:name=1,type=NB") |
75 && |
79 && |
|
80 subject != null |
|
81 && |
76 subject.getPrincipals().contains(new JMXPrincipal("role"))) |
82 subject.getPrincipals().contains(new JMXPrincipal("role"))) |
77 throw new SecurityException(); |
83 throw new SecurityException(); |
78 } |
84 } |
|
85 |
|
86 @Override |
79 public void removeNotificationListener( |
87 public void removeNotificationListener( |
80 String connectionId, |
88 String connectionId, |
81 ObjectName name, |
89 ObjectName name, |
82 Subject subject) |
90 Subject subject) |
83 throws SecurityException { |
91 throws SecurityException { |
87 echo("\tsubject: " + |
95 echo("\tsubject: " + |
88 (subject == null ? null : subject.getPrincipals())); |
96 (subject == null ? null : subject.getPrincipals())); |
89 if (throwException) |
97 if (throwException) |
90 if (name.getCanonicalName().equals("domain:name=2,type=NB") |
98 if (name.getCanonicalName().equals("domain:name=2,type=NB") |
91 && |
99 && |
|
100 subject != null |
|
101 && |
92 subject.getPrincipals().contains(new JMXPrincipal("role"))) |
102 subject.getPrincipals().contains(new JMXPrincipal("role"))) |
93 throw new SecurityException(); |
103 throw new SecurityException(); |
94 } |
104 } |
|
105 |
|
106 @Override |
95 public void fetchNotification( |
107 public void fetchNotification( |
96 String connectionId, |
108 String connectionId, |
97 ObjectName name, |
109 ObjectName name, |
98 Notification notification, |
110 Notification notification, |
99 Subject subject) |
111 Subject subject) |
103 echo("\tname: " + name); |
115 echo("\tname: " + name); |
104 echo("\tnotification: " + notification); |
116 echo("\tnotification: " + notification); |
105 echo("\tsubject: " + |
117 echo("\tsubject: " + |
106 (subject == null ? null : subject.getPrincipals())); |
118 (subject == null ? null : subject.getPrincipals())); |
107 if (!throwException) |
119 if (!throwException) |
108 if (name.getCanonicalName().equals("domain:name=2,type=NB") && |
120 if (name.getCanonicalName().equals("domain:name=2,type=NB") |
|
121 && |
|
122 subject != null |
|
123 && |
109 subject.getPrincipals().contains(new JMXPrincipal("role"))) |
124 subject.getPrincipals().contains(new JMXPrincipal("role"))) |
110 throw new SecurityException(); |
125 throw new SecurityException(); |
111 } |
126 } |
112 } |
127 } |
113 |
128 |
114 public class CustomJMXAuthenticator implements JMXAuthenticator { |
129 public class CustomJMXAuthenticator implements JMXAuthenticator { |
|
130 @Override |
115 public Subject authenticate(Object credentials) { |
131 public Subject authenticate(Object credentials) { |
116 String role = ((String[]) credentials)[0]; |
132 String role = ((String[]) credentials)[0]; |
117 echo("\nCreate principal with name = " + role); |
133 echo("\nCreate principal with name = " + role); |
118 return new Subject(true, |
134 return new Subject(true, |
119 Collections.singleton(new JMXPrincipal(role)), |
135 Collections.singleton(new JMXPrincipal(role)), |
127 } |
143 } |
128 |
144 |
129 public static class NB |
145 public static class NB |
130 extends NotificationBroadcasterSupport |
146 extends NotificationBroadcasterSupport |
131 implements NBMBean { |
147 implements NBMBean { |
|
148 @Override |
132 public void emitNotification(int seqnum, ObjectName name) { |
149 public void emitNotification(int seqnum, ObjectName name) { |
133 if (name == null) { |
150 if (name == null) { |
134 sendNotification(new Notification("nb", this, seqnum)); |
151 sendNotification(new Notification("nb", this, seqnum)); |
135 } else { |
152 } else { |
136 sendNotification(new Notification("nb", name, seqnum)); |
153 sendNotification(new Notification("nb", name, seqnum)); |
137 } |
154 } |
138 } |
155 } |
139 } |
156 } |
140 |
157 |
141 public class Listener implements NotificationListener { |
158 public class Listener implements NotificationListener { |
142 public List<Notification> notifs = new ArrayList<Notification>(); |
159 public final List<Notification> notifs = new CopyOnWriteArrayList<>(); |
|
160 |
|
161 private final Semaphore s; |
|
162 public Listener(Semaphore s) { |
|
163 this.s = s; |
|
164 } |
|
165 @Override |
143 public void handleNotification(Notification n, Object h) { |
166 public void handleNotification(Notification n, Object h) { |
144 echo("handleNotification:"); |
167 echo("handleNotification:"); |
145 echo("\tNotification = " + n); |
168 echo("\tNotification = " + n); |
146 echo("\tNotification.SeqNum = " + n.getSequenceNumber()); |
169 echo("\tNotification.SeqNum = " + n.getSequenceNumber()); |
147 echo("\tHandback = " + h); |
170 echo("\tHandback = " + h); |
148 notifs.add(n); |
171 notifs.add(n); |
|
172 s.release(); |
149 } |
173 } |
150 } |
174 } |
151 |
175 |
152 /** |
176 /** |
153 * Check received notifications |
177 * Check received notifications |
190 ": fetch ")) + "=-=-="); |
214 ": fetch ")) + "=-=-="); |
191 |
215 |
192 JMXConnectorServer server = null; |
216 JMXConnectorServer server = null; |
193 JMXConnector client = null; |
217 JMXConnector client = null; |
194 |
218 |
|
219 /* |
|
220 * (!enableChecks) |
|
221 * - List must contain three notifs from sources nb1, nb2 and nb3 |
|
222 * (enableChecks && !throwException) |
|
223 * - List must contain one notif from source nb1 |
|
224 * (enableChecks && throwException) |
|
225 * - List must contain two notifs from sources nb2 and nb3 |
|
226 */ |
|
227 final int expected_notifs = |
|
228 (!enableChecks ? 3 : (throwException ? 2 : 1)); |
|
229 |
195 // Create a new MBeanServer |
230 // Create a new MBeanServer |
196 // |
231 // |
197 final MBeanServer mbs = MBeanServerFactory.createMBeanServer(); |
232 final MBeanServer mbs = MBeanServerFactory.createMBeanServer(); |
198 |
233 |
199 try { |
234 try { |
200 // Create server environment map |
235 // Create server environment map |
201 // |
236 // |
202 final Map<String,Object> env = new HashMap<String,Object>(); |
237 final Map<String,Object> env = new HashMap<>(); |
203 env.put("jmx.remote.authenticator", new CustomJMXAuthenticator()); |
238 env.put("jmx.remote.authenticator", new CustomJMXAuthenticator()); |
204 if (enableChecks) { |
239 if (enableChecks) { |
205 env.put("com.sun.jmx.remote.notification.access.controller", |
240 env.put("com.sun.jmx.remote.notification.access.controller", |
206 new NAC(throwException)); |
241 new NAC(throwException)); |
207 } |
242 } |
220 // |
255 // |
221 server.start(); |
256 server.start(); |
222 |
257 |
223 // Create server environment map |
258 // Create server environment map |
224 // |
259 // |
225 final Map<String,Object> cenv = new HashMap<String,Object>(); |
260 final Map<String,Object> cenv = new HashMap<>(); |
226 String[] credentials = new String[] { "role" , "password" }; |
261 String[] credentials = new String[] { "role" , "password" }; |
227 cenv.put("jmx.remote.credentials", credentials); |
262 cenv.put("jmx.remote.credentials", credentials); |
228 |
263 |
229 // Create JMXConnector and connect to JMXConnectorServer |
264 // Create JMXConnector and connect to JMXConnectorServer |
230 // |
265 // |
244 mbsc.createMBean(NB.class.getName(), nb2); |
279 mbsc.createMBean(NB.class.getName(), nb2); |
245 mbsc.createMBean(NB.class.getName(), nb3); |
280 mbsc.createMBean(NB.class.getName(), nb3); |
246 |
281 |
247 // Add notification listener |
282 // Add notification listener |
248 // |
283 // |
249 Listener li = new Listener(); |
284 Semaphore s = new Semaphore(0); |
|
285 |
|
286 Listener li = new Listener(s); |
250 try { |
287 try { |
251 mbsc.addNotificationListener(nb1, li, null, null); |
288 mbsc.addNotificationListener(nb1, li, null, null); |
252 if (enableChecks && throwException) { |
289 if (enableChecks && throwException) { |
253 echo("Didn't get expected exception"); |
290 echo("Didn't get expected exception"); |
254 return 1; |
291 return 1; |
261 return 1; |
298 return 1; |
262 } |
299 } |
263 } |
300 } |
264 mbsc.addNotificationListener(nb2, li, null, null); |
301 mbsc.addNotificationListener(nb2, li, null, null); |
265 |
302 |
|
303 System.out.println("\n+++ Expecting to receive " + expected_notifs + |
|
304 " notification" + (expected_notifs > 1 ? "s" : "") + |
|
305 " +++"); |
266 // Invoke the "sendNotification" method |
306 // Invoke the "sendNotification" method |
267 // |
307 // |
268 mbsc.invoke(nb1, "emitNotification", |
308 mbsc.invoke(nb1, "emitNotification", |
269 new Object[] {0, null}, |
309 new Object[] {0, null}, |
270 new String[] {"int", "javax.management.ObjectName"}); |
310 new String[] {"int", "javax.management.ObjectName"}); |
275 new Object[] {2, nb3}, |
315 new Object[] {2, nb3}, |
276 new String[] {"int", "javax.management.ObjectName"}); |
316 new String[] {"int", "javax.management.ObjectName"}); |
277 |
317 |
278 // Wait for notifications to be emitted |
318 // Wait for notifications to be emitted |
279 // |
319 // |
280 Thread.sleep(2000); |
320 s.acquire(expected_notifs); |
281 |
321 |
282 // Remove notification listener |
322 // Remove notification listener |
283 // |
323 // |
284 if (!throwException) |
324 if (!throwException) |
285 mbsc.removeNotificationListener(nb1, li); |
325 mbsc.removeNotificationListener(nb1, li); |
301 int result = 0; |
341 int result = 0; |
302 List<ObjectName> sources = new ArrayList(); |
342 List<ObjectName> sources = new ArrayList(); |
303 sources.add(nb1); |
343 sources.add(nb1); |
304 sources.add(nb2); |
344 sources.add(nb2); |
305 sources.add(nb3); |
345 sources.add(nb3); |
306 if (!enableChecks) { |
346 result = checkNotifs(expected_notifs, li.notifs, sources); |
307 // List must contain three notifs from sources nb1, nb2 and nb3 |
|
308 // |
|
309 result = checkNotifs(3, li.notifs, sources); |
|
310 } |
|
311 if (enableChecks && !throwException) { |
|
312 // List must contain one notif from source nb1 |
|
313 // |
|
314 result = checkNotifs(1, li.notifs, sources); |
|
315 } |
|
316 if (enableChecks && throwException) { |
|
317 // List must contain two notifs from sources nb2 and nb3 |
|
318 // |
|
319 result = checkNotifs(2, li.notifs, sources); |
|
320 } |
|
321 if (result > 0) { |
347 if (result > 0) { |
322 return result; |
348 return result; |
323 } |
349 } |
324 } catch (Exception e) { |
350 } catch (Exception e) { |
325 echo("Failed to perform operation: " + e); |
351 echo("Failed to perform operation: " + e); |