Path: blob/master/test/jdk/javax/management/security/AuthorizationTest.java
41149 views
/*1* Copyright (c) 2003, 2018, 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 805886526* @summary Checks various authentication behavior from remote jmx client27* @author Olivier Lagneau28* @modules java.management.rmi29* @library /test/lib30* @compile Simple.java31* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials32* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException33* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException34* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials35* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedGetException36* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException37* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException38* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials39* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException40* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException41* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username4 -Dpassword=password4 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedGetException -expectedSetException42* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException43*/4445import java.io.File;46import java.util.Map ;47import java.util.HashMap ;48import java.util.List;49import java.util.ArrayList;50import java.util.Arrays;5152import java.lang.management.ManagementFactory;5354import javax.management.MBeanServer;55import javax.management.MBeanServerFactory ;56import javax.management.MBeanServerConnection;57import javax.management.remote.JMXConnector;58import javax.management.remote.JMXConnectorFactory;59import javax.management.remote.JMXConnectorServer;60import javax.management.remote.JMXConnectorServerFactory;61import javax.management.remote.JMXServiceURL;6263import javax.management.Attribute ;64import javax.management.ObjectName ;6566import jdk.test.lib.JDKToolFinder;67import jdk.test.lib.process.ProcessTools;6869public class AuthorizationTest {7071static final String SERVER_CLASS_NAME = "AuthorizationTest";72static final String CLIENT_CLASS_NAME = "AuthorizationTest$ClientSide";73static final String CLIENT_CLASS_MAIN = CLIENT_CLASS_NAME;7475static final String USERNAME_PROPERTY = "username";76static final String PASSWORD_PROPERTY = "password";7778private JMXConnectorServer cs;7980/*81* First Debug properties and arguments are collect in expected82* map (argName, value) format, then calls original test's run method.83*/84public static void main(String args[]) throws Exception {8586System.out.println("=================================================");8788// Parses parameters89Utils.parseDebugProperties();9091// Supported parameters list format is :92// "MainClass [-server <param-spec> ...] [-client <param-spec> ...]93// with <param-spec> either "-parami valuei" or "-parami"94HashMap<String, Object> serverMap = new HashMap<>() ;95int clientArgsIndex =96Utils.parseServerParameters(args, SERVER_CLASS_NAME, serverMap);9798// Extract and records client params99String[] clientParams = null;100if (clientArgsIndex < args.length) {101int clientParamsSize = args.length - clientArgsIndex;102clientParams = new String[clientParamsSize];103System.arraycopy(args, clientArgsIndex, clientParams, 0, clientParamsSize);104} else {105clientParams = new String[0];106}107108// Run test109AuthorizationTest test = new AuthorizationTest();110test.run(serverMap, clientParams);111112}113114/*115* Create the MBeansServer side of the test and returns its address116*/117private JMXServiceURL createServerSide(Map<String, Object> serverMap)118throws Exception {119final int NINETY_SECONDS = 90;120121System.out.println("AuthorizationTest::createServerSide: Start") ;122123MBeanServer mbs = MBeanServerFactory.newMBeanServer();124JMXServiceURL url = new JMXServiceURL("rmi", null, 0);125126// Creates connection environment from server side params127HashMap<String, Object> env = new HashMap<>();128String value = null;129130if ((value = (String)serverMap.get("-mapType")) != null) {131if (value.contains("x.access.file")) {132String accessFileStr = System.getProperty("test.src") +133File.separator + "access.properties";134env.put("jmx.remote.x.access.file", accessFileStr);135System.out.println("Added " + accessFileStr + " file as jmx.remote.x.access.file");136}137if (value.contains("x.password.file")) {138String passwordFileStr = System.getProperty("test.src") +139File.separator + "password.properties";140env.put("jmx.remote.x.password.file", passwordFileStr);141System.out.println("Added " + passwordFileStr + " file as jmx.remote.x.password.file");142}143}144145if (serverMap.containsKey("-populate")) {146String populateClassName = "Simple";147ObjectName on =148new ObjectName("defaultDomain:class=Simple");149150Utils.debug(Utils.DEBUG_STANDARD, "create and register Simple MBean") ;151mbs.createMBean(populateClassName, on);152}153154cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);155cs.start();156157Utils.waitReady(cs, NINETY_SECONDS);158159JMXServiceURL addr = cs.getAddress();160161System.out.println("AuthorizationTest::createServerSide: Done.") ;162163return addr;164}165166/*167* Creating command-line for running subprocess JVM:168*169* JVM command line is like:170* {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main171*172* {defaultopts} are the default java options set by the framework.173*174*/175private List<String> buildCommandLine(String args[]) {176List<String> opts = new ArrayList<>();177opts.add(JDKToolFinder.getJDKTool("java"));178opts.addAll(Arrays.asList(jdk.test.lib.Utils.getTestJavaOpts()));179180String usernameValue = System.getProperty(USERNAME_PROPERTY);181if (usernameValue != null) {182opts.add("-D" + USERNAME_PROPERTY + "=" + usernameValue);183}184String passwordValue = System.getProperty(PASSWORD_PROPERTY);185if (passwordValue != null) {186opts.add("-D" + PASSWORD_PROPERTY + "=" + passwordValue);187}188189opts.add("-cp");190opts.add(System.getProperty("test.class.path", "test.class.path"));191opts.add(CLIENT_CLASS_MAIN);192opts.addAll(Arrays.asList(args));193return opts;194}195196/**197* Runs AuthorizationTest$ClientSide with the passed options and redirects198* subprocess standard I/O to the current (parent) process. This provides a199* trace of what happens in the subprocess while it is runnning (and before200* it terminates).201*202* @param serviceUrlStr string representing the JMX service Url to connect to.203*/204private int runClientSide(String args[], String serviceUrlStr) throws Exception {205206// Building command-line207List<String> opts = buildCommandLine(args);208opts.add("-serviceUrl");209opts.add(serviceUrlStr);210211// Launch separate JVM subprocess212int exitCode = 0;213String[] optsArray = opts.toArray(new String[0]);214ProcessBuilder pb = new ProcessBuilder(optsArray);215Process p = ProcessTools.startProcess("AuthorizationTest$ClientSide", pb);216217// Handling end of subprocess218try {219exitCode = p.waitFor();220if (exitCode != 0) {221System.out.println(222"Subprocess unexpected exit value of [" + exitCode +223"]. Expected 0.\n");224}225} catch (InterruptedException e) {226System.out.println("Parent process interrupted with exception : \n " + e + " :" );227228// Parent thread unknown state, killing subprocess.229p.destroyForcibly();230231throw new RuntimeException(232"Parent process interrupted with exception : \n " + e + " :" );233234} finally {235if (p.isAlive()) {236p.destroyForcibly();237}238return exitCode;239}240241}242243public void run(Map<String, Object> serverArgs, String clientArgs[]) {244245System.out.println("AuthorizationTest::run: Start") ;246int errorCount = 0;247248try {249// Initialise the server side250JMXServiceURL urlToUse = createServerSide(serverArgs);251252// Run client side253errorCount = runClientSide(clientArgs, urlToUse.toString());254255if ( errorCount == 0 ) {256System.out.println("AuthorizationTest::run: Done without any error") ;257} else {258System.out.println("AuthorizationTest::run: Done with "259+ errorCount260+ " error(s)") ;261throw new RuntimeException("errorCount = " + errorCount);262}263264cs.stop();265266} catch(Exception e) {267throw new RuntimeException(e);268}269270}271272private static class ClientSide {273274private JMXConnector cc = null;275private MBeanServerConnection mbsc = null;276277public static void main(String args[]) throws Exception {278279// Parses parameters280Utils.parseDebugProperties();281282// Supported parameters list format is : "MainClass [-client <param-spec> ...]283// with <param-spec> either "-parami valuei" or "-parami"284HashMap<String, Object> clientMap = new HashMap<>() ;285Utils.parseClientParameters(args, CLIENT_CLASS_NAME, clientMap);286287// Run test288ClientSide test = new ClientSide();289test.run(clientMap);290291}292293public void run(Map<String, Object> args) {294295int errorCount = 0 ;296297try {298boolean expectedCreateException =299(args.containsKey("-expectedCreateException")) ? true : false ;300boolean expectedGetException =301(args.containsKey("-expectedGetException")) ? true : false ;302boolean expectedSetException =303(args.containsKey("-expectedSetException")) ? true : false ;304boolean expectedInvokeException =305(args.containsKey("-expectedInvokeException")) ? true : false ;306// JSR262 (see bug 6440374)307// There is no special JSR262 protocol operation for connect.308// The first request sent initiate the connection.309// In the JSR262 current implementation, getDefaultDomain is sent to310// the server in order to get the server part of the connection ID.311// => the connection may fail if no access permission on get requests.312boolean expectedConnectException =313(args.containsKey("-expectedConnectException")) ? true : false ;314// Before connection,315// remove the element of the Map with null values (not supported by RMI)316// See bug 4982668317args.remove("-expectedCreateException");318args.remove("-expectedGetException");319args.remove("-expectedSetException");320args.remove("-expectedInvokeException");321args.remove("-expectedConnectException");322323324// Here do connect to the JMX Server325String username = System.getProperty("username");326Utils.debug(Utils.DEBUG_STANDARD,327"ClientSide::run: CONNECT on behalf of \"" + username + "\"");328doConnect(args, expectedConnectException);329330// If the connection did not fail, perform some requests.331// At this stage the mbeanserver connection is up and running332if (mbsc != null) {333ObjectName on = new ObjectName("defaultDomain:class=Simple");334335// Create request336Utils.debug(Utils.DEBUG_STANDARD,337"ClientSide::run: CREATE on behalf of \"" +338username + "\"");339errorCount += doCreateRequest(mbsc,340new ObjectName("defaultDomain:class=Simple,user=" + username),341expectedCreateException);342343// Get request344Utils.debug(Utils.DEBUG_STANDARD,345"ClientSide::run: GET on behalf of \"" +346username + "\"");347errorCount += doGetRequest(mbsc, on, expectedGetException);348349// Set request350Utils.debug(Utils.DEBUG_STANDARD,351"ClientSide::run: SET on behalf of \"" +352username + "\"");353errorCount += doSetRequest(mbsc, on, expectedSetException);354355// Invoke request356Utils.debug(Utils.DEBUG_STANDARD,357"ClientSide::run: INVOKE on behalf of \"" +358username + "\"");359errorCount += doInvokeRequest(mbsc, on, expectedInvokeException);360}361362} catch(Exception e) {363Utils.printThrowable(e, true) ;364errorCount++;365} finally {366// Terminate the JMX Client367try {368cc.close();369} catch (Exception e) {370Utils.printThrowable(e, true) ;371errorCount++;372}373}374375System.out.println("ClientSide::run: Done") ;376377// Handle result378if (errorCount == 0) {379System.out.println("ClientSide::run: (OK) authorization test succeeded.");380} else {381String message = "AuthorizationTest$ClientSide::run: (ERROR) " +382" authorization test failed with " +383errorCount + " error(s)";384System.out.println(message);385throw new RuntimeException(message);386}387}388389protected void doConnect(Map<String, Object> args,390boolean expectedException) {391392String msgTag = "ClientSide::doConnect";393boolean throwRuntimeException = false;394String message = "";395396try {397Utils.debug(Utils.DEBUG_STANDARD,398"ClientSide::doConnect: Connect the client");399400// Collect connection environment401HashMap<String, Object> env = new HashMap<>();402403Object value = args.get("-mapType");404if (value != null) {405String username = System.getProperty("username");406String password = System.getProperty("password");407Utils.debug(Utils.DEBUG_STANDARD,408msgTag + "add \"jmx.remote.credentials\" = \"" +409username + "\", \"" + password + "\"");410env.put("jmx.remote.credentials",411new String[] { username , password });412}413414// Get a connection to remote mbean server415JMXServiceURL addr = new JMXServiceURL((String)args.get("-serviceUrl"));416cc = JMXConnectorFactory.connect(addr,env);417mbsc = cc.getMBeanServerConnection();418419if (expectedException) {420message = "ClientSide::doConnect: (ERROR) " +421"Connect did not fail with expected SecurityException";422System.out.println(message);423throwRuntimeException = true;424} else {425System.out.println("ClientSide::doConnect: (OK) Connect succeed");426}427} catch(Exception e) {428Utils.printThrowable(e, true);429if (expectedException) {430if (e instanceof java.lang.SecurityException) {431System.out.println("ClientSide::doConnect: (OK) " +432"Connect failed with expected SecurityException");433} else {434message = "ClientSide::doConnect: (ERROR) " +435"Create failed with " + e.getClass() +436" instead of expected SecurityException";437System.out.println(message);438throwRuntimeException = true;439}440} else {441message = "ClientSide::doConnect: (ERROR) " +442"Connect failed";443System.out.println(message);444throwRuntimeException = true;445}446}447448// If the connection failed, or if the connection succeeded but should not,449// no need to go further => throw RuntimeException and exit the test450if (throwRuntimeException) {451throw new RuntimeException(message);452}453}454455protected int doCreateRequest(MBeanServerConnection mbsc,456ObjectName on,457boolean expectedException) {458int errorCount = 0;459460try {461Utils.debug(Utils.DEBUG_STANDARD,462"ClientSide::doCreateRequest: Create and register the MBean") ;463464mbsc.createMBean("Simple", on) ;465466if (expectedException) {467System.out.println("ClientSide::doCreateRequest: " +468"(ERROR) Create did not fail with expected SecurityException");469errorCount++;470} else {471System.out.println("ClientSide::doCreateRequest: (OK) Create succeed") ;472}473} catch(Exception e) {474Utils.printThrowable(e, true) ;475if (expectedException) {476if (e instanceof java.lang.SecurityException) {477System.out.println("ClientSide::doCreateRequest: " +478"(OK) Create failed with expected SecurityException") ;479} else {480System.out.println("ClientSide::doCreateRequest: " +481"(ERROR) Create failed with " +482e.getClass() + " instead of expected SecurityException");483errorCount++;484}485} else {486System.out.println("ClientSide::doCreateRequest: " +487"(ERROR) Create failed");488errorCount++;489}490}491return errorCount;492}493494protected int doGetRequest(MBeanServerConnection mbsc,495ObjectName on,496boolean expectedException) {497int errorCount = 0;498499try {500Utils.debug(Utils.DEBUG_STANDARD,501"ClientSide::doGetRequest: Get attributes of the MBean") ;502503mbsc.getAttribute(on, "Attribute");504505if (expectedException) {506System.out.println("ClientSide::doGetRequest: " +507"(ERROR) Get did not fail with expected SecurityException");508errorCount++;509} else {510System.out.println("ClientSide::doGetRequest: (OK) Get succeed") ;511}512} catch(Exception e) {513Utils.printThrowable(e, true) ;514if (expectedException) {515if (e instanceof java.lang.SecurityException) {516System.out.println("ClientSide::doGetRequest: " +517"(OK) Get failed with expected SecurityException") ;518} else {519System.out.println("ClientSide::doGetRequest: " +520"(ERROR) Get failed with " +521e.getClass() + " instead of expected SecurityException");522errorCount++;523}524} else {525System.out.println("ClientSide::doGetRequest: (ERROR) Get failed");526errorCount++;527}528}529530return errorCount;531}532533protected int doSetRequest(MBeanServerConnection mbsc,534ObjectName on,535boolean expectedException) {536int errorCount = 0;537538try {539Utils.debug(Utils.DEBUG_STANDARD,540"ClientSide::doSetRequest: Set attributes of the MBean") ;541542Attribute attribute = new Attribute("Attribute", "My value") ;543mbsc.setAttribute(on, attribute) ;544545if (expectedException) {546System.out.println("ClientSide::doSetRequest: " +547"(ERROR) Set did not fail with expected SecurityException");548errorCount++;549} else {550System.out.println("ClientSide::doSetRequest: (OK) Set succeed") ;551}552} catch(Exception e) {553Utils.printThrowable(e, true) ;554if (expectedException) {555if (e instanceof java.lang.SecurityException) {556System.out.println("ClientSide::doSetRequest: " +557"(OK) Set failed with expected SecurityException") ;558} else {559System.out.println("ClientSide::doSetRequest: " +560"(ERROR) Set failed with " +561e.getClass() + " instead of expected SecurityException");562errorCount++;563}564} else {565System.out.println("ClientSide::doSetRequest: (ERROR) Set failed");566errorCount++;567}568}569return errorCount;570}571572protected int doInvokeRequest(MBeanServerConnection mbsc,573ObjectName on,574boolean expectedException) {575int errorCount = 0;576577try {578Utils.debug(Utils.DEBUG_STANDARD,579"ClientSide::doInvokeRequest: Invoke operations on the MBean") ;580581mbsc.invoke(on, "operation", null, null) ;582583if (expectedException) {584System.out.println("ClientSide::doInvokeRequest: " +585"(ERROR) Invoke did not fail with expected SecurityException");586errorCount++;587} else {588System.out.println("ClientSide::doInvokeRequest: (OK) Invoke succeed") ;589}590} catch(Exception e) {591Utils.printThrowable(e, true) ;592if (expectedException) {593if (e instanceof java.lang.SecurityException) {594System.out.println("ClientSide::doInvokeRequest: " +595"(OK) Invoke failed with expected SecurityException") ;596} else {597System.out.println("ClientSide::doInvokeRequest: " +598" (ERROR) Invoke failed with " +599e.getClass() + " instead of expected SecurityException");600errorCount++;601}602} else {603System.out.println("ClientSide::doInvokeRequest: " +604"(ERROR) Invoke failed");605errorCount++;606}607}608return errorCount;609}610611}612}613614615