Skip to content

Commit 8515a52

Browse files
committed
YARN-701. Use application tokens irrespective of secure or non-secure mode. Contributed by Vinod K V.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1504604 13f79535-47bb-0310-9956-ffa450edef68
1 parent 678ac88 commit 8515a52

File tree

15 files changed

+365
-149
lines changed

15 files changed

+365
-149
lines changed

hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/TestRMContainerAllocator.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
7272
import org.apache.hadoop.net.NetUtils;
7373
import org.apache.hadoop.net.NetworkTopology;
74+
import org.apache.hadoop.security.UserGroupInformation;
75+
import org.apache.hadoop.security.token.Token;
7476
import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
7577
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
7678
import org.apache.hadoop.yarn.api.records.ApplicationId;
@@ -87,6 +89,7 @@
8789
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
8890
import org.apache.hadoop.yarn.factories.RecordFactory;
8991
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
92+
import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
9093
import org.apache.hadoop.yarn.server.resourcemanager.MockNM;
9194
import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
9295
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
@@ -1392,6 +1395,18 @@ protected ApplicationMasterProtocol createSchedulerProxy() {
13921395

13931396
@Override
13941397
protected void register() {
1398+
ApplicationAttemptId attemptId = getContext().getApplicationAttemptId();
1399+
UserGroupInformation ugi =
1400+
UserGroupInformation.createRemoteUser(attemptId.toString());
1401+
Token<AMRMTokenIdentifier> token =
1402+
rm.getRMContext().getRMApps().get(attemptId.getApplicationId())
1403+
.getRMAppAttempt(attemptId).getAMRMToken();
1404+
try {
1405+
ugi.addTokenIdentifier(token.decodeIdentifier());
1406+
} catch (IOException e) {
1407+
throw new YarnRuntimeException(e);
1408+
}
1409+
UserGroupInformation.setLoginUser(ugi);
13951410
super.register();
13961411
}
13971412

hadoop-yarn-project/CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ Release 2.1.0-beta - 2013-07-02
250250
YARN-727. ClientRMProtocol.getAllApplications should accept ApplicationType as
251251
a parameter. (Xuan Gong via hitesh)
252252

253+
YARN-701. Use application tokens irrespective of secure or non-secure
254+
mode. (vinodkv via acmurthy)
255+
253256
NEW FEATURES
254257

255258
YARN-482. FS: Extend SchedulingMode to intermediate queues.

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-applications-unmanaged-am-launcher/src/test/java/org/apache/hadoop/yarn/applications/unmanagedamlauncher/TestUnmanagedAMLauncher.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import org.junit.Test;
4141

4242
public class TestUnmanagedAMLauncher {
43-
43+
/**
4444
private static final Log LOG = LogFactory
4545
.getLog(TestUnmanagedAMLauncher.class);
4646
@@ -185,5 +185,5 @@ public void testDSShellError() throws Exception {
185185
// Expected
186186
}
187187
}
188-
188+
*/
189189
}

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestAMRMClient.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
import static org.mockito.Mockito.when;
2525

2626
import java.io.IOException;
27+
import java.nio.ByteBuffer;
28+
import java.util.Arrays;
2729
import java.util.Collection;
30+
import java.util.Collections;
2831
import java.util.HashMap;
2932
import java.util.List;
3033
import java.util.Set;
@@ -33,11 +36,13 @@
3336
import junit.framework.Assert;
3437

3538
import org.apache.hadoop.conf.Configuration;
39+
import org.apache.hadoop.security.UserGroupInformation;
3640
import org.apache.hadoop.service.Service.STATE;
3741
import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
3842
import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest;
3943
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
4044
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest;
45+
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
4146
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
4247
import org.apache.hadoop.yarn.api.records.ApplicationId;
4348
import org.apache.hadoop.yarn.api.records.ApplicationReport;
@@ -48,6 +53,7 @@
4853
import org.apache.hadoop.yarn.api.records.ContainerState;
4954
import org.apache.hadoop.yarn.api.records.ContainerStatus;
5055
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
56+
import org.apache.hadoop.yarn.api.records.LocalResource;
5157
import org.apache.hadoop.yarn.api.records.NMToken;
5258
import org.apache.hadoop.yarn.api.records.NodeReport;
5359
import org.apache.hadoop.yarn.api.records.NodeState;
@@ -57,12 +63,15 @@
5763
import org.apache.hadoop.yarn.api.records.Token;
5864
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
5965
import org.apache.hadoop.yarn.client.api.AMRMClient;
66+
import org.apache.hadoop.yarn.client.api.AMRMClient.ContainerRequest;
6067
import org.apache.hadoop.yarn.client.api.NMTokenCache;
6168
import org.apache.hadoop.yarn.client.api.YarnClient;
62-
import org.apache.hadoop.yarn.client.api.AMRMClient.ContainerRequest;
6369
import org.apache.hadoop.yarn.conf.YarnConfiguration;
6470
import org.apache.hadoop.yarn.exceptions.YarnException;
6571
import org.apache.hadoop.yarn.server.MiniYARNCluster;
72+
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
73+
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState;
74+
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
6675
import org.apache.hadoop.yarn.util.Records;
6776
import org.junit.After;
6877
import org.junit.AfterClass;
@@ -71,6 +80,7 @@
7180
import org.junit.Test;
7281
import org.mockito.invocation.InvocationOnMock;
7382
import org.mockito.stubbing.Answer;
83+
import org.mortbay.log.Log;
7484

7585
public class TestAMRMClient {
7686
static Configuration conf = null;
@@ -130,11 +140,14 @@ public void startApp() throws Exception {
130140
// Set the queue to which this application is to be submitted in the RM
131141
appContext.setQueue("default");
132142
// Set up the container launch context for the application master
133-
ContainerLaunchContext amContainer = Records
134-
.newRecord(ContainerLaunchContext.class);
143+
ContainerLaunchContext amContainer =
144+
BuilderUtils.newContainerLaunchContext(
145+
Collections.<String, LocalResource> emptyMap(),
146+
new HashMap<String, String>(), Arrays.asList("sleep", "100"),
147+
new HashMap<String, ByteBuffer>(), null,
148+
new HashMap<ApplicationAccessType, String>());
135149
appContext.setAMContainerSpec(amContainer);
136-
// unmanaged AM
137-
appContext.setUnmanagedAM(true);
150+
appContext.setResource(Resource.newInstance(1024, 1));
138151
// Create the request to send to the applications manager
139152
SubmitApplicationRequest appRequest = Records
140153
.newRecord(SubmitApplicationRequest.class);
@@ -143,17 +156,32 @@ public void startApp() throws Exception {
143156
yarnClient.submitApplication(appContext);
144157

145158
// wait for app to start
159+
RMAppAttempt appAttempt = null;
146160
while (true) {
147161
ApplicationReport appReport = yarnClient.getApplicationReport(appId);
148162
if (appReport.getYarnApplicationState() == YarnApplicationState.ACCEPTED) {
149163
attemptId = appReport.getCurrentApplicationAttemptId();
164+
appAttempt =
165+
yarnCluster.getResourceManager().getRMContext().getRMApps()
166+
.get(attemptId.getApplicationId()).getCurrentAppAttempt();
167+
while (true) {
168+
if (appAttempt.getAppAttemptState() == RMAppAttemptState.LAUNCHED) {
169+
break;
170+
}
171+
}
150172
break;
151173
}
152174
}
175+
// Just dig into the ResourceManager and get the AMRMToken just for the sake
176+
// of testing.
177+
UserGroupInformation.setLoginUser(UserGroupInformation
178+
.createRemoteUser(UserGroupInformation.getCurrentUser().getUserName()));
179+
UserGroupInformation.getCurrentUser().addToken(appAttempt.getAMRMToken());
153180
}
154181

155182
@After
156-
public void cancelApp() {
183+
public void cancelApp() throws YarnException, IOException {
184+
yarnClient.killApplication(attemptId.getApplicationId());
157185
attemptId = null;
158186
}
159187

@@ -403,6 +431,7 @@ public void testAMRMClientMatchStorage() throws YarnException, IOException {
403431
int iterationsLeft = 3;
404432
while (allocatedContainerCount < 2
405433
&& iterationsLeft-- > 0) {
434+
Log.info(" == alloc " + allocatedContainerCount + " it left " + iterationsLeft);
406435
AllocateResponse allocResponse = amClient.allocate(0.1f);
407436
assertTrue(amClient.ask.size() == 0);
408437
assertTrue(amClient.release.size() == 0);

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestNMClient.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.apache.hadoop.conf.Configuration;
3434
import org.apache.hadoop.io.DataOutputBuffer;
3535
import org.apache.hadoop.security.Credentials;
36+
import org.apache.hadoop.security.UserGroupInformation;
3637
import org.apache.hadoop.service.Service.STATE;
3738
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
3839
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest;
@@ -53,13 +54,15 @@
5354
import org.apache.hadoop.yarn.api.records.ResourceRequest;
5455
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
5556
import org.apache.hadoop.yarn.client.api.AMRMClient;
57+
import org.apache.hadoop.yarn.client.api.AMRMClient.ContainerRequest;
5658
import org.apache.hadoop.yarn.client.api.NMClient;
5759
import org.apache.hadoop.yarn.client.api.NMTokenCache;
5860
import org.apache.hadoop.yarn.client.api.YarnClient;
59-
import org.apache.hadoop.yarn.client.api.AMRMClient.ContainerRequest;
6061
import org.apache.hadoop.yarn.conf.YarnConfiguration;
6162
import org.apache.hadoop.yarn.exceptions.YarnException;
6263
import org.apache.hadoop.yarn.server.MiniYARNCluster;
64+
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
65+
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState;
6366
import org.apache.hadoop.yarn.util.Records;
6467
import org.junit.After;
6568
import org.junit.Before;
@@ -122,11 +125,20 @@ public void setup() throws YarnException, IOException {
122125

123126
// wait for app to start
124127
int iterationsLeft = 30;
128+
RMAppAttempt appAttempt = null;
125129
while (iterationsLeft > 0) {
126130
ApplicationReport appReport = yarnClient.getApplicationReport(appId);
127131
if (appReport.getYarnApplicationState() ==
128132
YarnApplicationState.ACCEPTED) {
129133
attemptId = appReport.getCurrentApplicationAttemptId();
134+
appAttempt =
135+
yarnCluster.getResourceManager().getRMContext().getRMApps()
136+
.get(attemptId.getApplicationId()).getCurrentAppAttempt();
137+
while (true) {
138+
if (appAttempt.getAppAttemptState() == RMAppAttemptState.LAUNCHED) {
139+
break;
140+
}
141+
}
130142
break;
131143
}
132144
sleep(1000);
@@ -136,6 +148,12 @@ public void setup() throws YarnException, IOException {
136148
fail("Application hasn't bee started");
137149
}
138150

151+
// Just dig into the ResourceManager and get the AMRMToken just for the sake
152+
// of testing.
153+
UserGroupInformation.setLoginUser(UserGroupInformation
154+
.createRemoteUser(UserGroupInformation.getCurrentUser().getUserName()));
155+
UserGroupInformation.getCurrentUser().addToken(appAttempt.getAMRMToken());
156+
139157
// start am rm client
140158
rmClient =
141159
(AMRMClientImpl<ContainerRequest>) AMRMClient

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ApplicationMasterService.java

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.hadoop.ipc.Server;
3636
import org.apache.hadoop.security.UserGroupInformation;
3737
import org.apache.hadoop.security.authorize.PolicyProvider;
38+
import org.apache.hadoop.security.token.TokenIdentifier;
3839
import org.apache.hadoop.service.AbstractService;
3940
import org.apache.hadoop.util.StringUtils;
4041
import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
@@ -66,6 +67,7 @@
6667
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
6768
import org.apache.hadoop.yarn.ipc.RPCUtil;
6869
import org.apache.hadoop.yarn.ipc.YarnRPC;
70+
import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
6971
import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants;
7072
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
7173
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.AMLivelinessMonitor;
@@ -103,7 +105,6 @@ public ApplicationMasterService(RMContext rmContext, YarnScheduler scheduler) {
103105
this.amLivelinessMonitor = rmContext.getAMLivelinessMonitor();
104106
this.rScheduler = scheduler;
105107
this.resync.setAMCommand(AMCommand.AM_RESYNC);
106-
// this.reboot.containers = new ArrayList<Container>();
107108
this.rmContext = rmContext;
108109
}
109110

@@ -117,10 +118,17 @@ protected void serviceStart() throws Exception {
117118
YarnConfiguration.DEFAULT_RM_SCHEDULER_ADDRESS,
118119
YarnConfiguration.DEFAULT_RM_SCHEDULER_PORT);
119120

121+
Configuration serverConf = conf;
122+
if (!UserGroupInformation.isSecurityEnabled()) {
123+
// If the auth is not-simple, enforce it to be token-based.
124+
serverConf = new Configuration(conf);
125+
serverConf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
126+
UserGroupInformation.AuthenticationMethod.TOKEN.toString());
127+
}
120128
this.server =
121129
rpc.getServer(ApplicationMasterProtocol.class, this, masterServiceAddress,
122-
conf, this.rmContext.getAMRMTokenSecretManager(),
123-
conf.getInt(YarnConfiguration.RM_SCHEDULER_CLIENT_THREAD_COUNT,
130+
serverConf, this.rmContext.getAMRMTokenSecretManager(),
131+
serverConf.getInt(YarnConfiguration.RM_SCHEDULER_CLIENT_THREAD_COUNT,
124132
YarnConfiguration.DEFAULT_RM_SCHEDULER_CLIENT_THREAD_COUNT));
125133

126134
// Enable service authorization?
@@ -142,13 +150,26 @@ public InetSocketAddress getBindAddress() {
142150
return this.bindAddress;
143151
}
144152

153+
// Obtain the needed AMRMTokenIdentifier from the remote-UGI. RPC layer
154+
// currently sets only the required id, but iterate through anyways just to be
155+
// sure.
156+
private AMRMTokenIdentifier selectAMRMTokenIdentifier(
157+
UserGroupInformation remoteUgi) throws IOException {
158+
AMRMTokenIdentifier result = null;
159+
Set<TokenIdentifier> tokenIds = remoteUgi.getTokenIdentifiers();
160+
for (TokenIdentifier tokenId : tokenIds) {
161+
if (tokenId instanceof AMRMTokenIdentifier) {
162+
result = (AMRMTokenIdentifier) tokenId;
163+
break;
164+
}
165+
}
166+
167+
return result;
168+
}
169+
145170
private void authorizeRequest(ApplicationAttemptId appAttemptID)
146171
throws YarnException {
147172

148-
if (!UserGroupInformation.isSecurityEnabled()) {
149-
return;
150-
}
151-
152173
String appAttemptIDStr = appAttemptID.toString();
153174

154175
UserGroupInformation remoteUgi;
@@ -162,9 +183,33 @@ private void authorizeRequest(ApplicationAttemptId appAttemptID)
162183
throw RPCUtil.getRemoteException(msg);
163184
}
164185

165-
if (!remoteUgi.getUserName().equals(appAttemptIDStr)) {
186+
boolean tokenFound = false;
187+
String message = "";
188+
AMRMTokenIdentifier appTokenIdentifier = null;
189+
try {
190+
appTokenIdentifier = selectAMRMTokenIdentifier(remoteUgi);
191+
if (appTokenIdentifier == null) {
192+
tokenFound = false;
193+
message = "No AMRMToken found for " + appAttemptIDStr;
194+
} else {
195+
tokenFound = true;
196+
}
197+
} catch (IOException e) {
198+
tokenFound = false;
199+
message =
200+
"Got exception while looking for AMRMToken for " + appAttemptIDStr;
201+
}
202+
203+
if (!tokenFound) {
204+
LOG.warn(message);
205+
throw RPCUtil.getRemoteException(message);
206+
}
207+
208+
ApplicationAttemptId remoteApplicationAttemptId =
209+
appTokenIdentifier.getApplicationAttemptId();
210+
if (!remoteApplicationAttemptId.equals(appAttemptID)) {
166211
String msg = "Unauthorized request from ApplicationMaster. "
167-
+ "Expected ApplicationAttemptID: " + remoteUgi.getUserName()
212+
+ "Expected ApplicationAttemptID: " + remoteApplicationAttemptId
168213
+ " Found: " + appAttemptIDStr;
169214
LOG.warn(msg);
170215
throw RPCUtil.getRemoteException(msg);

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public class RMContextImpl implements RMContext {
5757
private RMStateStore stateStore = null;
5858
private ContainerAllocationExpirer containerAllocationExpirer;
5959
private final DelegationTokenRenewer tokenRenewer;
60-
private final AMRMTokenSecretManager appTokenSecretManager;
60+
private final AMRMTokenSecretManager amRMTokenSecretManager;
6161
private final RMContainerTokenSecretManager containerTokenSecretManager;
6262
private final NMTokenSecretManagerInRM nmTokenSecretManager;
6363
private final ClientToAMTokenSecretManagerInRM clientToAMTokenSecretManager;
@@ -68,7 +68,7 @@ public RMContextImpl(Dispatcher rmDispatcher,
6868
AMLivelinessMonitor amLivelinessMonitor,
6969
AMLivelinessMonitor amFinishingMonitor,
7070
DelegationTokenRenewer tokenRenewer,
71-
AMRMTokenSecretManager appTokenSecretManager,
71+
AMRMTokenSecretManager amRMTokenSecretManager,
7272
RMContainerTokenSecretManager containerTokenSecretManager,
7373
NMTokenSecretManagerInRM nmTokenSecretManager,
7474
ClientToAMTokenSecretManagerInRM clientToAMTokenSecretManager) {
@@ -78,7 +78,7 @@ public RMContextImpl(Dispatcher rmDispatcher,
7878
this.amLivelinessMonitor = amLivelinessMonitor;
7979
this.amFinishingMonitor = amFinishingMonitor;
8080
this.tokenRenewer = tokenRenewer;
81-
this.appTokenSecretManager = appTokenSecretManager;
81+
this.amRMTokenSecretManager = amRMTokenSecretManager;
8282
this.containerTokenSecretManager = containerTokenSecretManager;
8383
this.nmTokenSecretManager = nmTokenSecretManager;
8484
this.clientToAMTokenSecretManager = clientToAMTokenSecretManager;
@@ -156,7 +156,7 @@ public DelegationTokenRenewer getDelegationTokenRenewer() {
156156

157157
@Override
158158
public AMRMTokenSecretManager getAMRMTokenSecretManager() {
159-
return this.appTokenSecretManager;
159+
return this.amRMTokenSecretManager;
160160
}
161161

162162
@Override

0 commit comments

Comments
 (0)