Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java
38867 views
/*1* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 510672126* @summary Check the NotificationAccessController methods are properly called.27* @author Luis-Miguel Alventosa28* @run clean NotificationAccessControllerTest29* @run build NotificationAccessControllerTest30* @run main NotificationAccessControllerTest31*/3233import com.sun.jmx.remote.security.NotificationAccessController;34import java.util.ArrayList;35import java.util.Collections;36import java.util.HashMap;37import java.util.List;38import java.util.Map;39import java.util.concurrent.CopyOnWriteArrayList;40import java.util.concurrent.Semaphore;41import javax.management.MBeanServer;42import javax.management.MBeanServerConnection;43import javax.management.MBeanServerFactory;44import javax.management.Notification;45import javax.management.NotificationBroadcasterSupport;46import javax.management.NotificationListener;47import javax.management.ObjectName;48import javax.management.remote.JMXAuthenticator;49import javax.management.remote.JMXConnector;50import javax.management.remote.JMXConnectorFactory;51import javax.management.remote.JMXConnectorServer;52import javax.management.remote.JMXConnectorServerFactory;53import javax.management.remote.JMXPrincipal;54import javax.management.remote.JMXServiceURL;55import javax.security.auth.Subject;5657public class NotificationAccessControllerTest {5859public class NAC implements NotificationAccessController {60private final boolean throwException;61public NAC(boolean throwException) {62this.throwException = throwException;63}6465@Override66public void addNotificationListener(67String connectionId,68ObjectName name,69Subject subject)70throws SecurityException {71echo("addNotificationListener:");72echo("\tconnectionId: " + connectionId);73echo("\tname: " + name);74echo("\tsubject: " +75(subject == null ? null : subject.getPrincipals()));76if (throwException)77if (name.getCanonicalName().equals("domain:name=1,type=NB")78&&79subject != null80&&81subject.getPrincipals().contains(new JMXPrincipal("role")))82throw new SecurityException();83}8485@Override86public void removeNotificationListener(87String connectionId,88ObjectName name,89Subject subject)90throws SecurityException {91echo("removeNotificationListener:");92echo("\tconnectionId: " + connectionId);93echo("\tname: " + name);94echo("\tsubject: " +95(subject == null ? null : subject.getPrincipals()));96if (throwException)97if (name.getCanonicalName().equals("domain:name=2,type=NB")98&&99subject != null100&&101subject.getPrincipals().contains(new JMXPrincipal("role")))102throw new SecurityException();103}104105@Override106public void fetchNotification(107String connectionId,108ObjectName name,109Notification notification,110Subject subject)111throws SecurityException {112echo("fetchNotification:");113echo("\tconnectionId: " + connectionId);114echo("\tname: " + name);115echo("\tnotification: " + notification);116echo("\tsubject: " +117(subject == null ? null : subject.getPrincipals()));118if (!throwException)119if (name.getCanonicalName().equals("domain:name=2,type=NB")120&&121subject != null122&&123subject.getPrincipals().contains(new JMXPrincipal("role")))124throw new SecurityException();125}126}127128public class CustomJMXAuthenticator implements JMXAuthenticator {129@Override130public Subject authenticate(Object credentials) {131String role = ((String[]) credentials)[0];132echo("\nCreate principal with name = " + role);133return new Subject(true,134Collections.singleton(new JMXPrincipal(role)),135Collections.EMPTY_SET,136Collections.EMPTY_SET);137}138}139140public interface NBMBean {141public void emitNotification(int seqnum, ObjectName name);142}143144public static class NB145extends NotificationBroadcasterSupport146implements NBMBean {147@Override148public void emitNotification(int seqnum, ObjectName name) {149if (name == null) {150sendNotification(new Notification("nb", this, seqnum));151} else {152sendNotification(new Notification("nb", name, seqnum));153}154}155}156157public class Listener implements NotificationListener {158public final List<Notification> notifs = new CopyOnWriteArrayList<>();159160private final Semaphore s;161public Listener(Semaphore s) {162this.s = s;163}164@Override165public void handleNotification(Notification n, Object h) {166echo("handleNotification:");167echo("\tNotification = " + n);168echo("\tNotification.SeqNum = " + n.getSequenceNumber());169echo("\tHandback = " + h);170notifs.add(n);171s.release();172}173}174175/**176* Check received notifications177*/178public int checkNotifs(int size,179List<Notification> received,180List<ObjectName> expected) {181if (received.size() != size) {182echo("Error: expecting " + size + " notifications, got " +183received.size());184return 1;185} else {186for (Notification n : received) {187echo("Received notification: " + n);188if (!n.getType().equals("nb")) {189echo("Notification type must be \"nb\"");190return 1;191}192ObjectName o = (ObjectName) n.getSource();193int index = (int) n.getSequenceNumber();194ObjectName nb = expected.get(index);195if (!o.equals(nb)) {196echo("Notification source must be " + nb);197return 1;198}199}200}201return 0;202}203204/**205* Run test206*/207public int runTest(boolean enableChecks, boolean throwException)208throws Exception {209210echo("\n=-=-= " + (enableChecks ? "Enable" : "Disable") +211" notification access control checks " +212(!enableChecks ? "" : (throwException ? ": add/remove " :213": fetch ")) + "=-=-=");214215JMXConnectorServer server = null;216JMXConnector client = null;217218/*219* (!enableChecks)220* - List must contain three notifs from sources nb1, nb2 and nb3221* (enableChecks && !throwException)222* - List must contain one notif from source nb1223* (enableChecks && throwException)224* - List must contain two notifs from sources nb2 and nb3225*/226final int expected_notifs =227(!enableChecks ? 3 : (throwException ? 2 : 1));228229// Create a new MBeanServer230//231final MBeanServer mbs = MBeanServerFactory.createMBeanServer();232233try {234// Create server environment map235//236final Map<String,Object> env = new HashMap<>();237env.put("jmx.remote.authenticator", new CustomJMXAuthenticator());238if (enableChecks) {239env.put("com.sun.jmx.remote.notification.access.controller",240new NAC(throwException));241}242243// Create the JMXServiceURL244//245final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");246247// Create a JMXConnectorServer248//249server = JMXConnectorServerFactory.newJMXConnectorServer(url,250env,251mbs);252253// Start the JMXConnectorServer254//255server.start();256257// Create server environment map258//259final Map<String,Object> cenv = new HashMap<>();260String[] credentials = new String[] { "role" , "password" };261cenv.put("jmx.remote.credentials", credentials);262263// Create JMXConnector and connect to JMXConnectorServer264//265client = JMXConnectorFactory.connect(server.getAddress(), cenv);266267// Get non-secure MBeanServerConnection268//269final MBeanServerConnection mbsc =270client.getMBeanServerConnection();271272// Create NB MBean273//274ObjectName nb1 = ObjectName.getInstance("domain:type=NB,name=1");275ObjectName nb2 = ObjectName.getInstance("domain:type=NB,name=2");276ObjectName nb3 = ObjectName.getInstance("domain:type=NB,name=3");277mbsc.createMBean(NB.class.getName(), nb1);278mbsc.createMBean(NB.class.getName(), nb2);279mbsc.createMBean(NB.class.getName(), nb3);280281// Add notification listener282//283Semaphore s = new Semaphore(0);284285Listener li = new Listener(s);286try {287mbsc.addNotificationListener(nb1, li, null, null);288if (enableChecks && throwException) {289echo("Didn't get expected exception");290return 1;291}292} catch (SecurityException e) {293if (enableChecks && throwException) {294echo("Got expected exception: " + e);295} else {296echo("Got unexpected exception: " + e);297return 1;298}299}300mbsc.addNotificationListener(nb2, li, null, null);301302System.out.println("\n+++ Expecting to receive " + expected_notifs +303" notification" + (expected_notifs > 1 ? "s" : "") +304" +++");305// Invoke the "sendNotification" method306//307mbsc.invoke(nb1, "emitNotification",308new Object[] {0, null},309new String[] {"int", "javax.management.ObjectName"});310mbsc.invoke(nb2, "emitNotification",311new Object[] {1, null},312new String[] {"int", "javax.management.ObjectName"});313mbsc.invoke(nb2, "emitNotification",314new Object[] {2, nb3},315new String[] {"int", "javax.management.ObjectName"});316317// Wait for notifications to be emitted318//319s.acquire(expected_notifs);320321// Remove notification listener322//323if (!throwException)324mbsc.removeNotificationListener(nb1, li);325try {326mbsc.removeNotificationListener(nb2, li);327if (enableChecks && throwException) {328echo("Didn't get expected exception");329return 1;330}331} catch (SecurityException e) {332if (enableChecks && throwException) {333echo("Got expected exception: " + e);334} else {335echo("Got unexpected exception: " + e);336return 1;337}338}339340int result = 0;341List<ObjectName> sources = new ArrayList();342sources.add(nb1);343sources.add(nb2);344sources.add(nb3);345result = checkNotifs(expected_notifs, li.notifs, sources);346if (result > 0) {347return result;348}349} catch (Exception e) {350echo("Failed to perform operation: " + e);351e.printStackTrace();352return 1;353} finally {354// Close the connection355//356if (client != null)357client.close();358359// Stop the connector server360//361if (server != null)362server.stop();363364// Release the MBeanServer365//366if (mbs != null)367MBeanServerFactory.releaseMBeanServer(mbs);368}369370return 0;371}372373/*374* Print message375*/376private static void echo(String message) {377System.out.println(message);378}379380public static void main(String[] args) throws Exception {381382System.out.println("\nTest notification access control.");383384NotificationAccessControllerTest nact =385new NotificationAccessControllerTest();386387int error = 0;388389error += nact.runTest(false, false);390391error += nact.runTest(true, false);392393error += nact.runTest(true, true);394395if (error > 0) {396final String msg = "\nTest FAILED! Got " + error + " error(s)";397System.out.println(msg);398throw new IllegalArgumentException(msg);399} else {400System.out.println("\nTest PASSED!");401}402}403}404405406