|
@@ -0,0 +1,120 @@
|
|
|
+/**
|
|
|
+* 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.mapreduce.security;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.security.PrivilegedAction;
|
|
|
+import java.security.PrivilegedExceptionAction;
|
|
|
+
|
|
|
+import junit.framework.Assert;
|
|
|
+
|
|
|
+import org.apache.hadoop.conf.Configuration;
|
|
|
+import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
|
|
|
+import org.apache.hadoop.io.Text;
|
|
|
+import org.apache.hadoop.mapred.JobConf;
|
|
|
+import org.apache.hadoop.mapreduce.v2.api.HSClientProtocol;
|
|
|
+import org.apache.hadoop.mapreduce.v2.api.MRClientProtocol;
|
|
|
+import org.apache.hadoop.mapreduce.v2.api.MRDelegationTokenIdentifier;
|
|
|
+import org.apache.hadoop.mapreduce.v2.api.protocolrecords.GetDelegationTokenRequest;
|
|
|
+import org.apache.hadoop.mapreduce.v2.api.protocolrecords.GetJobReportRequest;
|
|
|
+import org.apache.hadoop.mapreduce.v2.hs.JobHistoryServer;
|
|
|
+import org.apache.hadoop.mapreduce.v2.jobhistory.JHAdminConfig;
|
|
|
+import org.apache.hadoop.mapreduce.v2.util.MRBuilderUtils;
|
|
|
+import org.apache.hadoop.security.UserGroupInformation;
|
|
|
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
|
|
|
+import org.apache.hadoop.security.token.Token;
|
|
|
+import org.apache.hadoop.yarn.api.records.DelegationToken;
|
|
|
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
|
+import org.apache.hadoop.yarn.exceptions.YarnRemoteException;
|
|
|
+import org.apache.hadoop.yarn.ipc.YarnRPC;
|
|
|
+import org.apache.hadoop.yarn.util.Records;
|
|
|
+import org.apache.log4j.Level;
|
|
|
+import org.apache.log4j.LogManager;
|
|
|
+import org.apache.log4j.Logger;
|
|
|
+import org.junit.Test;
|
|
|
+
|
|
|
+public class TestJHSSecurity {
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testDelegationToken() throws IOException, InterruptedException {
|
|
|
+
|
|
|
+ Logger rootLogger = LogManager.getRootLogger();
|
|
|
+ rootLogger.setLevel(Level.DEBUG);
|
|
|
+
|
|
|
+ final YarnConfiguration conf = new YarnConfiguration(new JobConf());
|
|
|
+ // Just a random principle
|
|
|
+ conf.set(JHAdminConfig.MR_HISTORY_PRINCIPAL,
|
|
|
+ "RandomOrc/localhost@apache.org");
|
|
|
+
|
|
|
+ conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
|
|
|
+ "kerberos");
|
|
|
+ UserGroupInformation.setConfiguration(conf);
|
|
|
+
|
|
|
+ final JobHistoryServer jobHistoryServer = new JobHistoryServer() {
|
|
|
+ protected void doSecureLogin(Configuration conf) throws IOException {
|
|
|
+ // no keytab based login
|
|
|
+ };
|
|
|
+ };
|
|
|
+ jobHistoryServer.init(conf);
|
|
|
+ jobHistoryServer.start();
|
|
|
+
|
|
|
+ // Fake the authentication-method
|
|
|
+ UserGroupInformation loggedInUser = UserGroupInformation.getCurrentUser();
|
|
|
+ loggedInUser.setAuthenticationMethod(AuthenticationMethod.KERBEROS);
|
|
|
+
|
|
|
+ // Get the delegation token directly as it is a little difficult to setup
|
|
|
+ // the kerberos based rpc.
|
|
|
+ DelegationToken token =
|
|
|
+ loggedInUser.doAs(new PrivilegedExceptionAction<DelegationToken>() {
|
|
|
+ @Override
|
|
|
+ public DelegationToken run() throws YarnRemoteException {
|
|
|
+ GetDelegationTokenRequest request =
|
|
|
+ Records.newRecord(GetDelegationTokenRequest.class);
|
|
|
+ request.setRenewer("OneRenewerToRuleThemAll");
|
|
|
+ return jobHistoryServer.getClientService().getClientHandler()
|
|
|
+ .getDelegationToken(request).getDelegationToken();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Now try talking to JHS using the delegation token
|
|
|
+ UserGroupInformation ugi =
|
|
|
+ UserGroupInformation.createRemoteUser("TheDarkLord");
|
|
|
+ ugi.addToken(new Token<MRDelegationTokenIdentifier>(token.getIdentifier()
|
|
|
+ .array(), token.getPassword().array(), new Text(token.getKind()),
|
|
|
+ new Text(token.getService())));
|
|
|
+ final YarnRPC rpc = YarnRPC.create(conf);
|
|
|
+ MRClientProtocol userUsingDT =
|
|
|
+ ugi.doAs(new PrivilegedAction<MRClientProtocol>() {
|
|
|
+ @Override
|
|
|
+ public MRClientProtocol run() {
|
|
|
+ return (MRClientProtocol) rpc.getProxy(HSClientProtocol.class,
|
|
|
+ jobHistoryServer.getClientService().getBindAddress(), conf);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ GetJobReportRequest jobReportRequest =
|
|
|
+ Records.newRecord(GetJobReportRequest.class);
|
|
|
+ jobReportRequest.setJobId(MRBuilderUtils.newJobId(123456, 1, 1));
|
|
|
+ try {
|
|
|
+ userUsingDT.getJobReport(jobReportRequest);
|
|
|
+ } catch (YarnRemoteException e) {
|
|
|
+ Assert.assertEquals("Unknown job job_123456_0001", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|