|
1 /* |
|
2 * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
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 |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 */ |
|
23 |
|
24 /* |
|
25 * |
|
26 * @test JMXNamespaceSecurityTest.java |
|
27 * @summary General JMXNamespaceSecurityTest test. |
|
28 * @author Daniel Fuchs |
|
29 * @run clean JMXNamespaceViewTest JMXNamespaceSecurityTest Wombat WombatMBean |
|
30 * LazyDomainTest |
|
31 * @run build JMXNamespaceSecurityTest JMXNamespaceViewTest Wombat WombatMBean |
|
32 * LazyDomainTest |
|
33 * @run main/othervm JMXNamespaceSecurityTest namespace.policy |
|
34 */ |
|
35 import java.io.File; |
|
36 import java.io.IOException; |
|
37 import java.util.HashMap; |
|
38 import java.util.List; |
|
39 import java.util.Map; |
|
40 import java.util.logging.Logger; |
|
41 import java.lang.management.ManagementFactory; |
|
42 import java.util.ArrayList; |
|
43 import java.util.HashSet; |
|
44 import java.util.Set; |
|
45 import java.util.TreeSet; |
|
46 import javax.management.MBeanServer; |
|
47 import javax.management.MBeanServerFactory; |
|
48 import javax.management.ObjectName; |
|
49 import javax.management.namespace.JMXDomain; |
|
50 import javax.management.namespace.JMXNamespace; |
|
51 import javax.management.namespace.JMXNamespaces; |
|
52 import javax.management.remote.JMXConnectorServer; |
|
53 |
|
54 /** |
|
55 * |
|
56 * @author Sun Microsystems, Inc. |
|
57 */ |
|
58 public class JMXNamespaceSecurityTest extends JMXNamespaceViewTest { |
|
59 |
|
60 /** |
|
61 * A logger for this class. |
|
62 **/ |
|
63 private static final Logger LOG = |
|
64 Logger.getLogger(JMXNamespaceSecurityTest.class.getName()); |
|
65 |
|
66 public static class NamedMBeanServerCreator |
|
67 extends JMXNamespaceViewTest.MBeanServerConfigCreator { |
|
68 public MBeanServer createMBeanServerFor(NamespaceConfig config) { |
|
69 return MBeanServerFactory. |
|
70 createNamedMBeanServer(config.name,config.name); |
|
71 } |
|
72 } |
|
73 /** |
|
74 * Creates a config for a hierarchy of namespaces, mixing local namespaces |
|
75 * and remote namespaces using the given protocol. |
|
76 * @param protocol The protocol that should be used for remote namespaces. |
|
77 * @return A namespace config hierarchy. |
|
78 * @throws java.lang.Exception |
|
79 */ |
|
80 public static NamespaceConfig[] makeConfig(String protocol) |
|
81 throws Exception { |
|
82 final NamespaceConfig[] config = { |
|
83 // Top level namespace "top1" (local) |
|
84 config("top1",wombats("wchief","w1","w2","w3"), |
|
85 // top1//local1 |
|
86 config("local1",wombats("wchief","ww1","ww2")), |
|
87 // top1//local2 |
|
88 config("local2",wombats("wchief","ww4","ww5","ww6"), |
|
89 // top1//local2//local3 |
|
90 config("local3",wombats("wchief","www1","www2")), |
|
91 // top1//local2//rmi1 |
|
92 config("rmi1",url(protocol),wombats("wchief","www3","www4","www5"))), |
|
93 // top1//rmi2 |
|
94 config("rmi2",url(protocol),wombats("wchief","ww7","ww8","ww9"), |
|
95 // top1//rmi2//local4 |
|
96 config("local4",wombats("wchief","www6","www7")), |
|
97 // top1//rmi2//rmi3 |
|
98 config("rmi3",url(protocol),wombats("wchief","www3","www4","www5"), |
|
99 // top1//rmi2//rmi3//local5 |
|
100 config("local5",wombats("wchief","wwww1"))))), |
|
101 // Top level namespace "top2" (local) |
|
102 config("top2",wombats("wchief","w21","w22","w23"), |
|
103 // top2//local21 |
|
104 config("local21",wombats("wchief","ww21","ww22")), |
|
105 // top2//rmi22 |
|
106 config("rmi22",url(protocol),wombats("wchief","ww27","ww28","ww29"), |
|
107 // top2//rmi22//local24 |
|
108 config("local24",wombats("wchief","www26","www27")), |
|
109 // top2//rmi22//rmi23 |
|
110 config("rmi23",url(protocol),wombats("wchief","www23","www24","www25"), |
|
111 // top2//rmi22//rmi23//local25 |
|
112 config("local25",wombats("wchief","wwww21"))))), |
|
113 // Top level namespace "top3" (remote) |
|
114 config("top3",url(protocol),wombats("wchief","w31","w32","w33"), |
|
115 // top3//local31 |
|
116 config("local31",wombats("wchief","ww31","ww32")), |
|
117 // top3//rmi32 |
|
118 config("rmi32",url(protocol),wombats("wchief","ww37","ww38","ww39"), |
|
119 // top3//rmi32//local34 |
|
120 config("local34",wombats("wchief","www36","www37")), |
|
121 // top3//rmi32//rmi33 |
|
122 config("rmi33",url(protocol),wombats("wchief","www33","www34","www35"), |
|
123 // top3//rmi32//local35 |
|
124 config("local35",wombats("wchief","wwww31"))))), |
|
125 }; |
|
126 return config; |
|
127 } |
|
128 |
|
129 public static void test(MBeanServer server, NamespaceConfig[] namespaces) |
|
130 throws Exception { |
|
131 System.out.println("Launching test..."); |
|
132 List<JMXConnectorServer> cslist = load(server, |
|
133 new NamedMBeanServerCreator(), namespaces); |
|
134 Map<String,NamespaceConfig> inputMap = |
|
135 new HashMap<String,NamespaceConfig>(); |
|
136 |
|
137 for (NamespaceConfig cfg : namespaces) { |
|
138 fillMap(inputMap,"",cfg); |
|
139 } |
|
140 final MBeanServer platform = ManagementFactory.getPlatformMBeanServer(); |
|
141 //if (System.getProperty("jmx.wait")!=null) { |
|
142 /* |
|
143 // if we wanted to lazy load the platform MBeanServer: |
|
144 final LazyDomainTest.MBeanServerLoader loader = |
|
145 new LazyDomainTest.MBeanServerLoader() { |
|
146 public MBeanServer loadMBeanServer() { |
|
147 return ManagementFactory.getPlatformMBeanServer(); |
|
148 } |
|
149 }; |
|
150 final LazyDomainTest.MBeanServerProxy proxy = |
|
151 new LazyDomainTest.MBeanServerProxy(loader); |
|
152 final LazyDomainTest.LazyDomain domain = |
|
153 new LazyDomainTest.LazyDomain(proxy); |
|
154 server.registerMBean(domain, |
|
155 JMXDomain.getDomainObjectName("java.lang")); |
|
156 */ |
|
157 // Mount java.lang MBeans into our private server so that |
|
158 // visualvm can connect. |
|
159 server.registerMBean( |
|
160 new JMXDomain(platform), |
|
161 JMXDomain.getDomainObjectName("java.lang")); |
|
162 //} |
|
163 if (System.getProperty("jmx.wait")!=null) { |
|
164 platform.registerMBean(new JMXNamespace(server), |
|
165 JMXNamespaces.getNamespaceObjectName("test")); |
|
166 } |
|
167 |
|
168 System.setSecurityManager(new SecurityManager()); |
|
169 |
|
170 // Some sanity checks... The policy file should allow access |
|
171 // to java.lang MBeans. |
|
172 final ObjectName platnames = new ObjectName("java.lang:*"); |
|
173 for (ObjectName o : platform.queryNames(platnames,null)) { |
|
174 server.getMBeanInfo(o); |
|
175 } |
|
176 final Set<ObjectName> lang = |
|
177 new HashSet<ObjectName>(server.queryNames(platnames, null)); |
|
178 lang.remove(JMXDomain.getDomainObjectName("java.lang")); |
|
179 if (!lang.equals(platform. |
|
180 queryNames(platnames, null))) |
|
181 throw new Exception("Wrong list of platform names: "+lang); |
|
182 System.out.println("Got all java.lang MBeans: "+lang); |
|
183 |
|
184 // The policy file should allow to see all namespaces. |
|
185 // check this... |
|
186 final List<ObjectName> patterns = new ArrayList<ObjectName>(); |
|
187 final Set<String> paths = new TreeSet<String>(); |
|
188 final Set<String> uuids = new HashSet<String>(); |
|
189 patterns.add(new ObjectName("*//:*")); |
|
190 while (patterns.size()>0) { |
|
191 System.out.println("server.queryNames("+patterns.get(0)+",null)"); |
|
192 Set<ObjectName> names = server.queryNames(patterns.remove(0),null); |
|
193 System.out.println("found: "+names); |
|
194 |
|
195 for (ObjectName no : names) { |
|
196 final String uuid = (String) server.getAttribute(no, "UUID"); |
|
197 if (uuids.contains(uuid)) { |
|
198 System.out.print("namespace "+no+", uuid="+uuid+ |
|
199 " already parsed. Skipping"); |
|
200 continue; |
|
201 } |
|
202 uuids.add(uuid); |
|
203 patterns.add(new ObjectName(no.getDomain()+"*//:*")); |
|
204 System.out.println("added pattern: "+ |
|
205 new ObjectName(no.getDomain()+"*//:*")); |
|
206 if (no.getDomain().endsWith(ClientContext.NAMESPACE+ |
|
207 JMXNamespaces.NAMESPACE_SEPARATOR)) continue; |
|
208 paths.add(no.getDomain().substring(0, |
|
209 no.getDomain().length()- |
|
210 JMXNamespaces.NAMESPACE_SEPARATOR.length())); |
|
211 } |
|
212 } |
|
213 final TreeSet<String> expected = new TreeSet<String>(inputMap.keySet()); |
|
214 if (!expected.equals(paths)) { |
|
215 throw new Exception("wrong set of namespaces, expected "+ |
|
216 expected+", got "+paths); |
|
217 } |
|
218 |
|
219 System.out.println("Got all namespaces: "+paths); |
|
220 |
|
221 // Check that we can see all wombats. |
|
222 // |
|
223 ObjectName wchief = |
|
224 new ObjectName("top1//rmi2//wombat:name=wchief,type=Wombat"); |
|
225 String caption = (String) server.getAttribute(wchief,"Caption"); |
|
226 System.out.println("wchief says "+caption); |
|
227 Object mood = server.getAttribute(wchief,"Mood"); |
|
228 System.out.println("wchief's mood on a scale of 100 is "+mood); |
|
229 |
|
230 ObjectName wchief2 = |
|
231 new ObjectName("top1//wombat:name=wchief,type=Wombat"); |
|
232 String caption2 = (String) server.getAttribute(wchief2,"Caption"); |
|
233 System.out.println("wchief2 says "+caption2); |
|
234 try { |
|
235 Object mood2 = server.getAttribute(wchief2,"Mood"); |
|
236 System.out.println("wchief2's mood on a scale of 100 is "+mood2); |
|
237 throw new Exception("Expected security exception for "+ |
|
238 "getAttribute("+wchief2+", \"Mood\""); |
|
239 } catch (SecurityException x) { |
|
240 System.out.println("wchief2's mood is unavailable: "+x); |
|
241 } |
|
242 try { |
|
243 exportAndWaitIfNeeded(server); |
|
244 } finally { |
|
245 closeAll(cslist); |
|
246 } |
|
247 |
|
248 } |
|
249 /** Creates a new instance of JMXNamespaceTest */ |
|
250 public JMXNamespaceSecurityTest() { |
|
251 } |
|
252 |
|
253 public static void main(String[] args) throws Exception { |
|
254 String osName = System.getProperty("os.name"); |
|
255 System.out.println("os.name = " + osName); |
|
256 if (!osName.equals("SunOS")) { |
|
257 System.out.println("This test runs on Solaris only."); |
|
258 System.out.println("Bye! Bye!"); |
|
259 return; |
|
260 } |
|
261 final String policy = System.getProperty("test.src") + |
|
262 File.separator + args[0]; |
|
263 System.out.println("PolicyFile = " + policy); |
|
264 System.setProperty("java.security.policy", policy); |
|
265 if (!new File(System.getProperty("java.security.policy")).canRead()) |
|
266 throw new IOException("no such file: "+ |
|
267 System.getProperty("java.security.policy")); |
|
268 test(MBeanServerFactory.createNamedMBeanServer("root","root"), |
|
269 makeConfig("rmi")); |
|
270 } |
|
271 |
|
272 } |