/** * 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 org.apache.hadoop.mapred; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.security.GeneralSecurityException; import javax.crypto.SecretKey; import org.apache.hadoop.http.HttpServer; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.security.SecureShuffleUtils; import org.apache.hadoop.mapreduce.security.token.JobTokenIdentifier; import org.apache.hadoop.mapreduce.security.token.JobTokenSecretManager; import org.apache.hadoop.security.token.Token; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertTrue; public class TestShuffleJobToken { private static HttpServer server; private static URL baseUrl; private static File dir; private static final String JOB_ID = "job_20091117075357176_0001"; private static final String BAD_JOB_ID = "job_20091117075357176_0002"; // create fake url private URL getMapOutputURL(String host) throws MalformedURLException { // Get the base url StringBuffer url = new StringBuffer(host); url.append("mapOutput?"); url.append("job=" + JOB_ID + "&"); url.append("reduce=0&"); url.append("map=attempt"); return new URL(url.toString()); } @Before public void setUp() throws Exception { dir = new File(System.getProperty("build.webapps", "build/webapps") + "/test"); System.out.println("dir="+dir.getAbsolutePath()); if(!dir.exists()) { assertTrue(dir.mkdirs()); } server = new HttpServer("test", "0.0.0.0", 0, true); server.addServlet("shuffle", "/mapOutput", TaskTracker.MapOutputServlet.class); server.start(); int port = server.getPort(); baseUrl = new URL("http://localhost:" + port + "/"); } @After public void tearDown() throws Exception { if(dir.exists()) dir.delete(); if(server!=null) server.stop(); } /** * try positive and negative case with invalid urlHash */ @Test public void testInvalidJobToken() throws IOException, GeneralSecurityException { URL url = getMapOutputURL(baseUrl.toString()); String enc_str = SecureShuffleUtils.buildMsgFrom(url); URLConnection connectionGood = url.openConnection(); TaskTracker tt = new TaskTracker(); JobTokenSecretManager jtSecretManager = new JobTokenSecretManager(); // create fake TaskTracker - needed for keys storage JobTokenIdentifier identifier = new JobTokenIdentifier(new Text(JOB_ID)); Token<JobTokenIdentifier> jt = new Token<JobTokenIdentifier>(identifier, jtSecretManager); SecretKey tokenSecret = JobTokenSecretManager.createSecretKey(jt.getPassword()); addJobToken(tt, JOB_ID, jt); // fake id server.setAttribute("task.tracker", tt); // encode the url String urlHashGood = SecureShuffleUtils.generateHash(enc_str.getBytes(), tokenSecret); // valid hash // another the key JobTokenIdentifier badIdentifier = new JobTokenIdentifier(new Text(BAD_JOB_ID)); Token<JobTokenIdentifier> badToken = new Token<JobTokenIdentifier>(badIdentifier, jtSecretManager); SecretKey badSecret = JobTokenSecretManager.createSecretKey(badToken.getPassword()); String urlHashBad = SecureShuffleUtils.generateHash(enc_str.getBytes(), badSecret); // invalid hash // put url hash into http header connectionGood.addRequestProperty(SecureShuffleUtils.HTTP_HEADER_URL_HASH, urlHashGood); // valid url hash should not fail with security error try { connectionGood.getInputStream(); } catch (IOException ie) { String msg = ie.getLocalizedMessage(); if(msg.contains("Server returned HTTP response code: 401 for URL:")) { fail("securtity failure with valid urlHash:"+ie); } System.out.println("valid urlhash passed validation"); } // invalid url hash URLConnection connectionBad = url.openConnection(); connectionBad.addRequestProperty(SecureShuffleUtils.HTTP_HEADER_URL_HASH, urlHashBad); try { connectionBad.getInputStream(); fail("Connection should've failed because of invalid urlHash"); } catch (IOException ie) { String msg = ie.getLocalizedMessage(); if(!msg.contains("Server returned HTTP response code: 401 for URL:")) { fail("connection failed with other then validation error:"+ie); } System.out.println("validation worked, failed with:"+ie); } } /*Note that this method is there for a unit testcase (TestShuffleJobToken)*/ void addJobToken(TaskTracker tt, String jobIdStr, Token<JobTokenIdentifier> token) { JobID jobId = JobID.forName(jobIdStr); TaskTracker.RunningJob rJob = new TaskTracker.RunningJob(jobId); synchronized (tt.runningJobs) { tt.runningJobs.put(jobId, rJob); } tt.getJobTokenSecretManager().addTokenForJob(jobIdStr, token); } }