/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.jstorm.daemon.supervisor; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import backtype.storm.Config; import backtype.storm.utils.Utils; import com.alibaba.jstorm.client.ConfigExtension; import com.alibaba.jstorm.cluster.StormConfig; /** * Right now generate java sandbox policy through template file * * In the future, generating java sandbox policy will through hardcode * * @author longda * @version */ public class SandBoxMaker { private static final Logger LOG = LoggerFactory.getLogger(SandBoxMaker.class); public static final String SANBOX_TEMPLATE_NAME = "sandbox.policy"; public static final String JSTORM_HOME_KEY = "%JSTORM_HOME%"; public static final String CLASS_PATH_KEY = "%CLASS_PATH%"; public static final String LOCAL_DIR_KEY = "%JSTORM_LOCAL_DIR%"; // this conf should only be Supervisor Conf private final Map conf; private final boolean isEnable; private final Map<String, String> replaceBaseMap = new HashMap<String, String>(); public SandBoxMaker(Map conf) { this.conf = conf; isEnable = ConfigExtension.isJavaSandBoxEnable(conf); LOG.info("Java Sandbox Policy :" + String.valueOf(isEnable)); String jstormHome = System.getProperty("jstorm.home"); if (jstormHome == null) { jstormHome = "./"; } replaceBaseMap.put(JSTORM_HOME_KEY, jstormHome); replaceBaseMap.put(LOCAL_DIR_KEY, (String) conf.get(Config.STORM_LOCAL_DIR)); LOG.info("JSTORM_HOME is " + jstormHome); } private String genClassPath(String classPathLine) { StringBuilder sb = new StringBuilder(); String[] classPathes = classPathLine.split(":"); for (String classpath : classPathes) { if (StringUtils.isBlank(classpath)) { continue; } File file = new File(classpath); if (file.isDirectory()) { sb.append(" permission java.io.FilePermission \""); sb.append(classpath).append(File.separator).append("**"); sb.append("\", \"read\";\n"); } else { sb.append(" permission java.io.FilePermission \""); sb.append(classpath); sb.append("\", \"read\";\n"); } } return sb.toString(); } private String replaceLine(String line, Map<String, String> replaceMap) { for (Entry<String, String> entry : replaceMap.entrySet()) { if (line.contains(CLASS_PATH_KEY)) { return genClassPath(entry.getValue()); } else if (line.contains(entry.getKey())) { return line.replace(entry.getKey(), entry.getValue()); } } return line; } public String generatePolicyFile(Map<String, String> replaceMap) throws IOException { // dynamic generate policy file, no static file String tmpPolicy = StormConfig.supervisorTmpDir(conf) + File.separator + UUID.randomUUID().toString(); InputStream inputStream = SandBoxMaker.class.getClassLoader().getResourceAsStream(SANBOX_TEMPLATE_NAME); PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(tmpPolicy))); BufferedReader reader = null; InputStreamReader inputReader = null; try { inputReader = new InputStreamReader(inputStream); reader = new BufferedReader(new LineNumberReader(inputReader)); String line = null; while ((line = reader.readLine()) != null) { String replaced = replaceLine(line, replaceMap); writer.println(replaced); } return tmpPolicy; } catch (Exception e) { LOG.error("Failed to generate policy file\n", e); throw new IOException(e); } finally { if (inputStream != null) { inputStream.close(); } if (writer != null) { writer.close(); } if (reader != null){ reader.close(); } if (inputReader != null){ inputReader.close(); } } } /** * Generate command string * * @param workerId * @return * @throws IOException */ public String sandboxPolicy(String workerId, Map<String, String> replaceMap) throws IOException { if (isEnable == false) { return ""; } replaceMap.putAll(replaceBaseMap); String tmpPolicy = generatePolicyFile(replaceMap); File file = new File(tmpPolicy); String policyPath = StormConfig.worker_root(conf, workerId) + File.separator + SANBOX_TEMPLATE_NAME; File dest = new File(policyPath); file.renameTo(dest); StringBuilder sb = new StringBuilder(); sb.append(" -Djava.security.manager -Djava.security.policy="); sb.append(policyPath); return sb.toString(); } public static void main(String[] args) { Map<Object, Object> conf = Utils.readStormConfig(); conf.put("java.sandbox.enable", Boolean.valueOf(true)); SandBoxMaker maker = new SandBoxMaker(conf); try { System.out.println("sandboxPolicy:" + maker.sandboxPolicy("simple", new HashMap<String, String>())); } catch (IOException e) { e.printStackTrace(); } } }