blob: 70722dced2421a063e9d3fabd2fd982c3261f16b [file] [log] [blame]
/**
* 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);
}
}