diff --git hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java index 8c578fd..83a9c8a 100644 --- hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java +++ hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java @@ -447,10 +447,19 @@ public RpcDetailedMetrics getRpcDetailedMetrics() { * Refresh the service authorization ACL for the service handled by this server. */ public void refreshServiceAcl(Configuration conf, PolicyProvider provider) { - serviceAuthorizationManager.refresh(conf, provider); + serviceAuthorizationManager.refresh(conf, provider, false); } /** + * Refresh the service authorization ACL for the service handled by this + * server. If useRemoteConfiguration is set as true, refresh the service using + * the remoteConfiguration + */ + public void refreshServiceAcl(Configuration conf, PolicyProvider provider, + boolean useRemoteConfiguration) { + serviceAuthorizationManager.refresh(conf, provider, useRemoteConfiguration); + } + /** * Returns a handle to the serviceAuthorizationManager (required in tests) * @return instance of ServiceAuthorizationManager for this server */ diff --git hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ServiceAuthorizationManager.java hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ServiceAuthorizationManager.java index 8523f38..bce58a2 100644 --- hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ServiceAuthorizationManager.java +++ hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ServiceAuthorizationManager.java @@ -112,15 +112,16 @@ public void authorize(UserGroupInformation user, } public synchronized void refresh(Configuration conf, - PolicyProvider provider) { + PolicyProvider provider, boolean useRemoteConfiguration) { // Get the system property 'hadoop.policy.file' String policyFile = System.getProperty("hadoop.policy.file", HADOOP_POLICY_FILE); // Make a copy of the original config, and load the policy file Configuration policyConf = new Configuration(conf); - policyConf.addResource(policyFile); - + if (! useRemoteConfiguration) { + policyConf.addResource(policyFile); + } final Map, AccessControlList> newAcls = new IdentityHashMap, AccessControlList>(); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java index 97d7fa8..d0cdaeb 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; +import java.security.PrivilegedExceptionAction; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -39,19 +40,29 @@ import org.apache.hadoop.ha.ClientBaseWithFixes; import org.apache.hadoop.ha.HAServiceProtocol; import org.apache.hadoop.ha.proto.HAServiceProtocolProtos; +import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.service.Service.STATE; +import org.apache.hadoop.yarn.api.ApplicationClientProtocol; +import org.apache.hadoop.yarn.api.protocolrecords.GetNewApplicationRequest; +import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest; import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext; +import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; +import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.client.api.YarnClient; import org.apache.hadoop.yarn.conf.HAUtil; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException; import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.ipc.YarnRPC; import org.apache.hadoop.yarn.server.MiniYARNCluster; import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshQueuesRequest; +import org.apache.hadoop.yarn.server.api.protocolrecords.RefreshServiceAclsRequest; import org.apache.hadoop.yarn.server.resourcemanager.AdminService; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration; import org.apache.hadoop.yarn.server.webproxy.WebAppProxyServer; +import org.apache.hadoop.yarn.util.Records; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -299,6 +310,44 @@ public void testAdminServiceRefreshQueuesOnHA() throws IOException, Assert.assertTrue(maxAppsAfter != maxAppsBefore); } + @Test + public void testAdminServiceRefreshServiceAclsOnHA() throws IOException, + YarnException, InterruptedException { + Configuration.addDefaultResource("config-with-security.xml"); + Configuration confWithSecurity = new YarnConfiguration(conf); + cluster.init(confWithSecurity); + cluster.start(); + getAdminService(0).transitionToActive(req); + assertFalse("RM never turned active", -1 == cluster.getActiveRMIndex()); + + // clean the remoteDirectory + cleanRemoteDirectory(); + + RefreshServiceAclsRequest request = RefreshServiceAclsRequest.newInstance(); + getAdminService(0).refreshServiceAcls(request); + Configuration conf = new Configuration(); + conf.set("security.applicationclient.protocol.acl", "alice,bob users,wheel"); + String hadoopConfFile = writeConfigurationXML(conf, "hadoop-policy.xml"); + + // upload the file into Remote File System + uploadToRemoteFileSystem(new Path(hadoopConfFile)); + + getAdminService(0).refreshServiceAcls(request); + + try { + submitApplicationByUser("tester"); + fail("Submit Application by user tester should fail"); + } catch (Exception ex) { + // Expected + } + + try { + submitApplicationByUser("alice"); + } catch (Exception ex) { + fail("Submit Application by user alice should not fail"); + } + } + private String writeConfigurationXML(Configuration conf, String confXMLName) throws IOException { DataOutputStream output = null; @@ -337,4 +386,38 @@ private void cleanRemoteDirectory() throws IOException { } } } + + private void submitApplicationByUser(String user) throws Exception { + ApplicationClientProtocol rmClient; + final YarnRPC rpc = YarnRPC.create(conf); + UserGroupInformation owner = UserGroupInformation + .createRemoteUser(user); + rmClient = + owner.doAs(new PrivilegedExceptionAction() { + + @Override + public ApplicationClientProtocol run() throws Exception { + return (ApplicationClientProtocol) rpc.getProxy( + ApplicationClientProtocol.class, + cluster.getConfig().getSocketAddr( + YarnConfiguration.RM_ADDRESS, + YarnConfiguration.DEFAULT_RM_ADDRESS, + YarnConfiguration.DEFAULT_RM_PORT), cluster.getConfig()); + } + }); + ApplicationId applicationId = rmClient.getNewApplication( + GetNewApplicationRequest.newInstance()).getApplicationId(); + ApplicationSubmissionContext appContext = + Records.newRecord(ApplicationSubmissionContext.class); + appContext.setApplicationId(applicationId); + ContainerLaunchContext amContainer = + Records.newRecord(ContainerLaunchContext.class); + appContext.setAMContainerSpec(amContainer); + Resource capability = Records.newRecord(Resource.class); + capability.setMemory(10); + capability.setVirtualCores(1); + appContext.setResource(capability); + rmClient + .submitApplication(SubmitApplicationRequest.newInstance(appContext)); + } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java index 24a3b7d..388c92d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java @@ -155,7 +155,8 @@ protected void startServer() throws Exception { if (conf.getBoolean( CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false)) { - refreshServiceAcls(conf, new RMPolicyProvider()); + refreshServiceAcls(conf, new RMPolicyProvider(), + this.rmContext.isHAEnabled()); } if (rmContext.isHAEnabled()) { @@ -425,9 +426,9 @@ public RefreshAdminAclsResponse refreshAdminAcls( @Override public RefreshServiceAclsResponse refreshServiceAcls( - RefreshServiceAclsRequest request) throws YarnException { - Configuration conf = new Configuration(); - if (!conf.getBoolean( + RefreshServiceAclsRequest request) throws YarnException, IOException { + String argName = "refreshServiceAcls"; + if (!getConfig().getBoolean( CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false)) { throw RPCUtil.getRemoteException( @@ -436,26 +437,43 @@ public RefreshServiceAclsResponse refreshServiceAcls( ") not enabled.")); } - PolicyProvider policyProvider = new RMPolicyProvider(); - - refreshServiceAcls(conf, policyProvider); - if (isRMActive()) { - rmContext.getClientRMService().refreshServiceAcls(conf, policyProvider); - rmContext.getApplicationMasterService().refreshServiceAcls( - conf, policyProvider); - rmContext.getResourceTrackerService().refreshServiceAcls( - conf, policyProvider); - } else { - LOG.warn("ResourceManager is not active. Not refreshing ACLs for " + - "Clients, ApplicationMasters and NodeManagers"); + if (!isRMActive()) { + RMAuditLogger.logFailure(UserGroupInformation.getCurrentUser() + .getShortUserName(), argName, + adminAcl.toString(), "AdminService", + "ResourceManager is not active. Can not refresh Service ACLs."); + throwStandbyException(); } - - return recordFactory.newRecordInstance(RefreshServiceAclsResponse.class); + + PolicyProvider policyProvider = new RMPolicyProvider(); + RefreshServiceAclsResponse response = recordFactory + .newRecordInstance(RefreshServiceAclsResponse.class); + Configuration conf = getConfiguration(argName); + if (this.rmContext.isHAEnabled() && conf == null) { + LOG.warn(printFailureDescription(getConfigurationFileName(argName), + argName)); + return response; + } + refreshServiceAcls(conf, policyProvider, this.rmContext.isHAEnabled()); + rmContext.getClientRMService().refreshServiceAcls( + getConfiguration(argName), policyProvider, + this.rmContext.isHAEnabled()); + rmContext.getApplicationMasterService().refreshServiceAcls( + getConfiguration(argName), policyProvider, + this.rmContext.isHAEnabled()); + rmContext.getResourceTrackerService().refreshServiceAcls( + getConfiguration(argName), policyProvider, + this.rmContext.isHAEnabled()); + RMAuditLogger.logSuccess(UserGroupInformation.getCurrentUser() + .getShortUserName(), argName, + "AdminService"); + return response; } void refreshServiceAcls(Configuration configuration, - PolicyProvider policyProvider) { - this.server.refreshServiceAcl(configuration, policyProvider); + PolicyProvider policyProvider, boolean useRemoteConfiguration) { + this.server.refreshServiceAcl(configuration, policyProvider, + useRemoteConfiguration); } @Override diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ApplicationMasterService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ApplicationMasterService.java index 57605c0..dfe9c47 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ApplicationMasterService.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ApplicationMasterService.java @@ -137,7 +137,8 @@ protected void serviceStart() throws Exception { if (conf.getBoolean( CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false)) { - refreshServiceAcls(conf, new RMPolicyProvider()); + refreshServiceAcls(conf, new RMPolicyProvider(), + this.rmContext.isHAEnabled()); } this.server.start(); @@ -577,8 +578,9 @@ public void unregisterAttempt(ApplicationAttemptId attemptId) { } public void refreshServiceAcls(Configuration configuration, - PolicyProvider policyProvider) { - this.server.refreshServiceAcl(configuration, policyProvider); + PolicyProvider policyProvider, boolean useRemoteConfiguration) { + this.server.refreshServiceAcl(configuration, policyProvider, + useRemoteConfiguration); } @Override diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java index 1df67f8..c35f6dc 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java @@ -163,7 +163,8 @@ protected void serviceStart() throws Exception { if (conf.getBoolean( CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false)) { - refreshServiceAcls(conf, new RMPolicyProvider()); + refreshServiceAcls(conf, new RMPolicyProvider(), + this.rmContext.isHAEnabled()); } this.server.start(); @@ -703,8 +704,9 @@ private String getRenewerForToken(Token token) } void refreshServiceAcls(Configuration configuration, - PolicyProvider policyProvider) { - this.server.refreshServiceAcl(configuration, policyProvider); + PolicyProvider policyProvider, boolean useReomteConfiguration) { + this.server.refreshServiceAcl(configuration, policyProvider, + useReomteConfiguration); } private boolean isAllowedDelegationTokenOp() throws IOException { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java index f80ce85..ad87090 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java @@ -161,7 +161,8 @@ protected void serviceStart() throws Exception { if (conf.getBoolean( CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false)) { - refreshServiceAcls(conf, new RMPolicyProvider()); + refreshServiceAcls(conf, new RMPolicyProvider(), + this.rmContext.isHAEnabled()); } this.server.start(); @@ -414,7 +415,8 @@ public static Node resolve(String hostName) { } void refreshServiceAcls(Configuration configuration, - PolicyProvider policyProvider) { - this.server.refreshServiceAcl(configuration, policyProvider); + PolicyProvider policyProvider, boolean useRemoteConfiguration) { + this.server.refreshServiceAcl(configuration, policyProvider, + useRemoteConfiguration); } }