1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.nio.file.Files; 25 import java.nio.file.Path; 26 import java.nio.file.Paths; 27 import java.util.ArrayList; 28 import java.util.LinkedHashMap; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Arrays; 32 import java.io.IOException; 33 import java.lang.module.ModuleDescriptor; 34 import jdk.testlibrary.ProcessTools; 35 import jdk.testlibrary.OutputAnalyzer; 36 import org.testng.annotations.BeforeTest; 37 38 /** 39 * @test 40 * @bug 8130360 41 * @library /jdk/jigsaw/lib 42 * @library /lib/testlibrary 43 * @library /java/security/modules 44 * @modules java.base/jdk.internal.module 45 * @build CompilerUtils JarUtils 46 * @summary Test custom security provider module with all possible modular 47 * condition. The test includes different combination of security 48 * client/provider modules interaction with or without service 49 * description. 50 * @run testng SecurityProviderModularTest 51 */ 52 public class SecurityProviderModularTest extends ModularTest { 53 54 private static final Path S_SRC = SRC.resolve("TestSecurityProvider.java"); 55 private static final String S_PKG = "provider"; 56 private static final String S_JAR_NAME = S_PKG + JAR_EXTN; 57 private static final String S_WITH_DESCR_JAR_NAME = S_PKG + DESCRIPTOR 58 + JAR_EXTN; 59 private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN; 60 private static final String MS_WITH_DESCR_JAR_NAME = MODULAR + S_PKG 61 + DESCRIPTOR + JAR_EXTN; 62 63 private static final Path C_SRC = SRC.resolve( 64 "TestSecurityProviderClient.java"); 65 private static final String C_PKG = "client"; 66 private static final String C_JAR_NAME = C_PKG + JAR_EXTN; 67 private static final String MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME = MODULAR 68 + C_PKG + AUTO + JAR_EXTN; 69 private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN; 70 71 private static final Path BUILD_DIR = Paths.get(".").resolve("build"); 72 private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin"); 73 private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG); 74 private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve( 75 S_PKG + DESCRIPTOR); 76 private static final Path C_BUILD_DIR = COMPILE_DIR.resolve(C_PKG); 77 private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase"); 78 private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts"); 79 80 private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG); 81 private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME); 82 private static final Path S_WITH_DESCRIPTOR_JAR = S_ARTIFACTS_DIR.resolve( 83 S_WITH_DESCR_JAR_NAME); 84 private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve( 85 MS_JAR_NAME); 86 private static final Path MS_WITH_DESCR_JAR = S_ARTIFACTS_DIR.resolve( 87 MS_WITH_DESCR_JAR_NAME); 88 89 private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG); 90 private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME); 91 private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME); 92 private static final Path MC_DEPENDS_ON_AUTO_SERVICE_JAR = C_ARTIFACTS_DIR 93 .resolve(MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME); 94 95 private static final String MAIN = C_PKG + ".TestSecurityProviderClient"; 96 private static final String S_INTERFACE = "java.security.Provider"; 97 private static final String S_IMPL = S_PKG + ".TestSecurityProvider"; 98 private static final List<String> M_REQUIRED = Arrays.asList("java.base"); 99 private static final Path META_DESCR_PATH = Paths.get("META-INF") 100 .resolve("services").resolve(S_INTERFACE); 101 private static final Path S_META_DESCR_FPATH = S_WITH_META_DESCR_BUILD_DIR 102 .resolve(META_DESCR_PATH); 103 104 private static final boolean WITH_S_DESCR = true; 105 private static final boolean WITHOUT_S_DESCR = false; 106 private static final String CLASS_NOT_FOUND_MSG = "NoClassDefFoundError:" 107 + " provider/TestSecurityProvider"; 108 private static final String PROVIDER_NOT_FOUND_MSG = "Unable to find Test" 109 + " Security Provider"; 110 private static final String CAN_NOT_ACCESS_MSG = "cannot access class"; 111 private static final String NO_FAILURE = null; 112 private static final String SERVICE_LOADER = "SERVICE_LOADER"; 113 private static final String CLASS_LOADER = "CLASS_LOADER"; 114 private static final String SECURITY_PROP = "SECURITY_PROP"; 115 private static final List<String> MECHANISMS = Arrays.asList(SERVICE_LOADER, 116 CLASS_LOADER, SECURITY_PROP); 117 private static final Path SECURE_PROP_EXTN = Paths.get("./java.secure.ext"); 118 119 /** 120 * Generates Test specific input parameters. 121 */ 122 @Override 123 public Object[][] getTestInput() { 124 125 List<List<Object>> params = new ArrayList<>(); 126 MECHANISMS.stream().forEach((mechanism) -> { 127 boolean useCLoader = CLASS_LOADER.equals(mechanism); 128 boolean useSLoader = SERVICE_LOADER.equals(mechanism); 129 String[] args = new String[]{mechanism}; 130 //PARAMETER ORDERS - 131 //client Module Type, Service Module Type, 132 //Service META Descriptor Required, 133 //Expected Failure message, mech used to find the provider 134 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, 135 WITH_S_DESCR, NO_FAILURE, args)); 136 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, 137 WITHOUT_S_DESCR, NO_FAILURE, args)); 138 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, 139 WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG 140 : NO_FAILURE), args)); 141 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, 142 WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args)); 143 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, 144 WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG 145 : NO_FAILURE), args)); 146 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, 147 WITHOUT_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG 148 : ((useSLoader) ? PROVIDER_NOT_FOUND_MSG 149 : NO_FAILURE)), args)); 150 151 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, 152 WITH_S_DESCR, NO_FAILURE, args)); 153 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, 154 WITH_S_DESCR, NO_FAILURE, args)); 155 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, 156 WITH_S_DESCR, NO_FAILURE, args)); 157 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, 158 WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args)); 159 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, 160 WITH_S_DESCR, NO_FAILURE, args)); 161 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, 162 WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG 163 : NO_FAILURE), args)); 164 165 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, 166 WITH_S_DESCR, NO_FAILURE, args)); 167 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, 168 WITHOUT_S_DESCR, NO_FAILURE, args)); 169 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, 170 WITH_S_DESCR, NO_FAILURE, args)); 171 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, 172 WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args)); 173 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, 174 WITH_S_DESCR, NO_FAILURE, args)); 175 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, 176 WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG 177 : NO_FAILURE), args)); 178 }); 179 return params.stream().map(p -> p.toArray()).toArray(Object[][]::new); 180 } 181 182 /** 183 * Pre-compile and generate the artifacts required to run this test before 184 * running each test cases. 185 */ 186 @BeforeTest 187 public void buildArtifacts() { 188 189 boolean done = true; 190 try { 191 192 done &= CompilerUtils.compile(S_SRC, S_BUILD_DIR); 193 done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR); 194 done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL); 195 //Generate regular/modular jars with(out) META-INF 196 //Service descriptor 197 generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false); 198 generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR, 199 S_WITH_META_DESCR_BUILD_DIR, false); 200 generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false); 201 generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR, 202 S_WITH_META_DESCR_BUILD_DIR, false); 203 //Generate regular/modular(depends on explicit/auto Service) 204 //jars for client 205 done &= CompilerUtils.compile(C_SRC, C_BUILD_DIR, "-cp", 206 S_JAR.toFile().getCanonicalPath()); 207 generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BUILD_DIR, true); 208 generateJar(false, MODULE_TYPE.EXPLICIT, 209 MC_DEPENDS_ON_AUTO_SERVICE_JAR, C_BUILD_DIR, false); 210 generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BUILD_DIR, false); 211 System.out.format("%nArtifacts generated successfully? %s", done); 212 if (!done) { 213 throw new RuntimeException("Artifacts generation failed"); 214 } 215 } catch (IOException e) { 216 throw new RuntimeException(e); 217 } 218 } 219 220 /** 221 * Generate modular/regular jar based on module type for this test. 222 */ 223 private void generateJar(boolean isService, MODULE_TYPE moduleType, 224 Path jar, Path compilePath, boolean depends) throws IOException { 225 226 ModuleDescriptor mDescriptor = null; 227 if (isService) { 228 mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG, 229 S_PKG, S_INTERFACE, S_IMPL, null, M_REQUIRED, depends); 230 } else { 231 mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG, 232 C_PKG, S_INTERFACE, null, S_PKG, M_REQUIRED, depends); 233 } 234 generateJar(mDescriptor, jar, compilePath); 235 } 236 237 /** 238 * Holds Logic for the test. This method will get called with each test 239 * parameter. 240 */ 241 @Override 242 public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType, 243 Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath, 244 String... args) throws Exception { 245 246 OutputAnalyzer output = null; 247 try { 248 249 //For automated/explicit module type copy the corresponding 250 //jars to module base folder, which will be considered as 251 //module base path during execution. 252 if (!(cModuleType == MODULE_TYPE.UNNAMED 253 && sModuletype == MODULE_TYPE.UNNAMED)) { 254 copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH); 255 copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH); 256 } 257 258 System.out.format("%nExecuting java client with required" 259 + " custom security provider in class/module path."); 260 String mName = getModuleName(cModuleType, cJarPath, C_PKG); 261 Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED 262 || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null; 263 String cPath = buildClassPath(cModuleType, cJarPath, sModuletype, 264 sJarPath); 265 266 Map<String, String> VM_ARGS = getVMArgs(sModuletype, args); 267 output = ProcessTools.executeTestJava( 268 getJavaCommand(cmBasePath, cPath, mName, MAIN, VM_ARGS, 269 args)).outputTo(System.out).errorTo(System.out); 270 } finally { 271 //clean module path so that the modulepath can hold only 272 //the required jars for next run. 273 cleanModuleBasePath(M_BASE_PATH); 274 System.out.println("--------------------------------------------"); 275 } 276 return output; 277 } 278 279 /** 280 * Decide the pre-generated client/service jar path for each test case 281 * based on client/service module type. 282 */ 283 @Override 284 public Path findJarPath(boolean isService, MODULE_TYPE moduleType, 285 boolean addMetaDesc, boolean dependsOnServiceModule) { 286 if (isService) { 287 if (moduleType == MODULE_TYPE.EXPLICIT) { 288 if (addMetaDesc) { 289 return MS_WITH_DESCR_JAR; 290 } else { 291 return MS_JAR; 292 } 293 } else { 294 if (addMetaDesc) { 295 return S_WITH_DESCRIPTOR_JAR; 296 } else { 297 return S_JAR; 298 } 299 } 300 } else { 301 if (moduleType == MODULE_TYPE.EXPLICIT) { 302 if (dependsOnServiceModule) { 303 return MC_JAR; 304 } else { 305 return MC_DEPENDS_ON_AUTO_SERVICE_JAR; 306 } 307 } else { 308 return C_JAR; 309 } 310 } 311 } 312 313 /** 314 * VM argument required for the test. 315 */ 316 private Map<String, String> getVMArgs(MODULE_TYPE sModuletype, 317 String... args) throws IOException { 318 final Map<String, String> VM_ARGS = new LinkedHashMap<>(); 319 VM_ARGS.put("-Duser.language=", "en"); 320 VM_ARGS.put("-Duser.region=", "US"); 321 //If mechanism selected to find the provider through 322 //Security.getProvider() then use providerName/ProviderClassName based 323 //on modular/regular provider jar in security configuration file. 324 if (args != null && args.length > 0 && SECURITY_PROP.equals(args[0])) { 325 if (sModuletype == MODULE_TYPE.UNNAMED) { 326 Files.write(SECURE_PROP_EXTN, ("security.provider.10=" + S_IMPL) 327 .getBytes()); 328 } else { 329 Files.write(SECURE_PROP_EXTN, "security.provider.10=TEST" 330 .getBytes()); 331 } 332 VM_ARGS.put("-Djava.security.properties=", SECURE_PROP_EXTN.toFile() 333 .getCanonicalPath()); 334 } 335 return VM_ARGS; 336 } 337 338 }