JavaSandboxLinuxContainerRuntime extends DefaultLinuxContainerRuntime { @Override public void prepareContainer(ContainerRuntimeContext ctx) throws ContainerExecutionException { @SuppressWarnings("unchecked") List<String> localDirs = ctx.getExecutionAttribute(CONTAINER_LOCAL_DIRS); @SuppressWarnings("unchecked") Map<org.apache.hadoop.fs.Path, List<String>> resources = ctx.getExecutionAttribute(LOCALIZED_RESOURCES); @SuppressWarnings("unchecked") List<String> commands = ctx.getExecutionAttribute(CONTAINER_RUN_CMDS); Map<String, String> env = ctx.getContainer().getLaunchContext().getEnvironment(); String username = ctx.getExecutionAttribute(USER); if(!isSandboxContainerWhitelisted(username, commands)) { String tmpDirBase = configuration.get("hadoop.tmp.dir"); if (tmpDirBase == null) { throw new ContainerExecutionException("hadoop.tmp.dir not set!"); } try { String containerID = ctx.getExecutionAttribute(CONTAINER_ID_STR); initializePolicyDir(); List<String> groupPolicyFiles = getGroupPolicyFiles(configuration, ctx.getExecutionAttribute(USER)); Path policyFilePath = Files.createFile( Paths.get(policyFileDir.toString(), containerID + "-" + NMContainerPolicyUtils.POLICY_FILE), POLICY_ATTR); try(OutputStream policyOutputStream = Files.newOutputStream(policyFilePath)) { containerPolicies.put(containerID, policyFilePath); NMContainerPolicyUtils.generatePolicyFile(policyOutputStream, localDirs, groupPolicyFiles, resources, configuration); NMContainerPolicyUtils.appendSecurityFlags( commands, env, policyFilePath, sandboxMode); } } catch (IOException e) { throw new ContainerExecutionException(e); } } } JavaSandboxLinuxContainerRuntime(
      PrivilegedOperationExecutor privilegedOperationExecutor); @Override void initialize(Configuration conf, Context nmContext); @Override void prepareContainer(ContainerRuntimeContext ctx); @Override void launchContainer(ContainerRuntimeContext ctx); @Override void relaunchContainer(ContainerRuntimeContext ctx); @Override boolean isRuntimeRequested(Map<String, String> env); static final String POLICY_FILE_DIR; }
@Test public void testGroupPolicies() throws IOException, ContainerExecutionException { File openSocketPolicyFile = File.createTempFile("openSocket", "policy", baseTestDirectory); File classLoaderPolicyFile = File.createTempFile("createClassLoader", "policy", baseTestDirectory); Permission socketPerm = new SocketPermission("localhost:0", "listen"); Permission runtimePerm = new RuntimePermission("createClassLoader"); StringBuilder socketPermString = new StringBuilder(); Formatter openSocketPolicyFormatter = new Formatter(socketPermString); openSocketPolicyFormatter.format(SOCKET_PERMISSION_FORMAT, socketPerm.getClass().getName(), socketPerm.getName(), socketPerm.getActions()); FileWriter socketPermWriter = new FileWriter(openSocketPolicyFile); socketPermWriter.write(socketPermString.toString()); socketPermWriter.close(); StringBuilder classLoaderPermString = new StringBuilder(); Formatter classLoaderPolicyFormatter = new Formatter(classLoaderPermString); classLoaderPolicyFormatter.format(RUNTIME_PERMISSION_FORMAT, runtimePerm.getClass().getName(), runtimePerm.getName()); FileWriter classLoaderPermWriter = new FileWriter(classLoaderPolicyFile); classLoaderPermWriter.write(classLoaderPermString.toString()); classLoaderPermWriter.close(); conf.set(YarnConfiguration.YARN_CONTAINER_SANDBOX_POLICY_GROUP_PREFIX + WHITELIST_GROUP, openSocketPolicyFile.toString()); conf.set(YarnConfiguration.YARN_CONTAINER_SANDBOX_POLICY_GROUP_PREFIX + NORMAL_GROUP, classLoaderPolicyFile.toString()); String[] inputCommand = {"$JAVA_HOME/bin/java jar MyJob.jar"}; List<String> commands = Arrays.asList(inputCommand); runtimeContextBuilder.setExecutionAttribute(USER, WHITELIST_USER); runtimeContextBuilder.setExecutionAttribute(CONTAINER_RUN_CMDS, commands); runtime.prepareContainer(runtimeContextBuilder.build()); Matcher policyMatches = Pattern.compile(POLICY_APPEND_FLAG + "=?([^ ]+)") .matcher(commands.get(0)); policyMatches.find(); String generatedPolicy = policyMatches.group(1); Assert.assertTrue( Files.readAllLines(Paths.get(generatedPolicy)).contains( classLoaderPermString.toString().split("\n")[1])); Assert.assertTrue( Files.readAllLines(Paths.get(generatedPolicy)).contains( socketPermString.toString().split("\n")[1])); }
@Test public void testDisabledSandboxWithWhitelist() throws ContainerExecutionException { String[] inputCommand = { "java jar MyJob.jar" }; List<String> commands = Arrays.asList(inputCommand); conf.set(YarnConfiguration.YARN_CONTAINER_SANDBOX_WHITELIST_GROUP, WHITELIST_GROUP); runtimeContextBuilder.setExecutionAttribute(USER, WHITELIST_USER); runtimeContextBuilder.setExecutionAttribute(CONTAINER_RUN_CMDS, commands); runtime.prepareContainer(runtimeContextBuilder.build()); Assert.assertTrue("Command should not be modified when user is " + "member of whitelisted group", inputCommand[0].equals(commands.get(0))); }
@Test public void testEnabledSandboxWithWhitelist() throws ContainerExecutionException{ String[] inputCommand = { "$JAVA_HOME/bin/java jar -Djava.security.manager MyJob.jar" }; List<String> commands = Arrays.asList(inputCommand); conf.set(YarnConfiguration.YARN_CONTAINER_SANDBOX_WHITELIST_GROUP, WHITELIST_GROUP); runtimeContextBuilder.setExecutionAttribute(USER, WHITELIST_USER); runtimeContextBuilder.setExecutionAttribute(CONTAINER_RUN_CMDS, commands); runtime.prepareContainer(runtimeContextBuilder.build()); Assert.assertTrue("Command should be modified to include " + "policy file in whitelisted Sandbox mode", commands.get(0).contains(SECURITY_FLAG) && commands.get(0).contains(POLICY_FLAG)); }
@Test public void testDeniedWhitelistGroup() throws ContainerExecutionException { String[] inputCommand = { "$JAVA_HOME/bin/java jar MyJob.jar" }; List<String> commands = Arrays.asList(inputCommand); conf.set(YarnConfiguration.YARN_CONTAINER_SANDBOX_WHITELIST_GROUP, WHITELIST_GROUP); runtimeContextBuilder.setExecutionAttribute(USER, NORMAL_USER); runtimeContextBuilder.setExecutionAttribute(CONTAINER_RUN_CMDS, commands); runtime.prepareContainer(runtimeContextBuilder.build()); Assert.assertTrue("Java security manager must be enabled for " + "unauthorized users", commands.get(0).contains(SECURITY_FLAG)); }