diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java index b3ac7bbe748..19504676eed 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java @@ -1046,6 +1046,14 @@ ApplicationId submitApp(Service app) throws IOException, YarnException { amLaunchContext.setCommands(Collections.singletonList(cmdStr)); amLaunchContext.setEnvironment(env); amLaunchContext.setLocalResources(localResources); + Map acls = new HashMap<>(2); + acls.put(ApplicationAccessType.VIEW_APP, YarnServiceConf.get( + YarnServiceConf.YARN_SERVICE_VIEW_ACLS, YarnServiceConf. + DEFAULT_YARN_SERVICE_VIEW_ACLS, app.getConfiguration(), conf)); + acls.put(ApplicationAccessType.MODIFY_APP, YarnServiceConf.get( + YarnServiceConf.YARN_SERVICE_MODIFY_ACLS, YarnServiceConf. + DEFAULT_YARN_SERVICE_MODIFY_ACLS, app.getConfiguration(), conf)); + amLaunchContext.setApplicationACLs(acls); addCredentials(amLaunchContext, app); submissionContext.setAMContainerSpec(amLaunchContext); yarnClient.submitApplication(submissionContext); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/YarnServiceConf.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/YarnServiceConf.java index 86c4de2ef89..2653780cd3a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/YarnServiceConf.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/YarnServiceConf.java @@ -53,6 +53,13 @@ public static final String YARN_QUEUE = "yarn.service.queue"; public static final String DEFAULT_YARN_QUEUE = "default"; + public static final String YARN_SERVICE_VIEW_ACLS = YARN_SERVICE_PREFIX + + "view.acls"; + public static final String DEFAULT_YARN_SERVICE_VIEW_ACLS = " "; + public static final String YARN_SERVICE_MODIFY_ACLS = YARN_SERVICE_PREFIX + + "modify.acls"; + public static final String DEFAULT_YARN_SERVICE_MODIFY_ACLS = " "; + public static final String API_SERVER_ADDRESS = "yarn.service.api-server.address"; public static final String DEFAULT_API_SERVER_ADDRESS = "0.0.0.0:"; public static final int DEFAULT_API_SERVER_PORT = 9191; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/containerlaunch/AbstractLauncher.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/containerlaunch/AbstractLauncher.java index d1dda38eeb5..bca3e830fb4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/containerlaunch/AbstractLauncher.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/containerlaunch/AbstractLauncher.java @@ -25,6 +25,7 @@ import org.apache.hadoop.yarn.api.records.ContainerRetryContext; import org.apache.hadoop.yarn.api.records.ContainerRetryPolicy; import org.apache.hadoop.yarn.api.records.LocalResource; +import org.apache.hadoop.yarn.api.records.ApplicationAccessType; import org.apache.hadoop.yarn.service.ServiceContext; import org.apache.hadoop.yarn.service.conf.YarnServiceConstants; import org.apache.hadoop.yarn.service.utils.ServiceUtils; @@ -239,6 +240,10 @@ public void putEnv(Map map) { } + public void setApplicationACLs(Map acls) { + containerLaunchContext.setApplicationACLs(acls); + } + public void setDockerImage(String dockerImage) { this.dockerImage = dockerImage; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java index 52f2a4eb018..4c2965fa1fa 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java @@ -20,6 +20,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.ApplicationConstants; +import org.apache.hadoop.yarn.api.records.ApplicationAccessType; import org.apache.hadoop.yarn.api.records.Container; import org.apache.hadoop.yarn.service.api.records.Service; import org.apache.hadoop.yarn.service.component.ComponentRestartPolicy; @@ -37,6 +38,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -46,6 +48,10 @@ import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.DEFAULT_CONTAINER_FAILURES_VALIDITY_INTERVAL; import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.DEFAULT_CONTAINER_RETRY_INTERVAL; import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.DEFAULT_CONTAINER_RETRY_MAX; +import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.YARN_SERVICE_VIEW_ACLS; +import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.YARN_SERVICE_MODIFY_ACLS; +import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.DEFAULT_YARN_SERVICE_VIEW_ACLS; +import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.DEFAULT_YARN_SERVICE_MODIFY_ACLS; import static org.apache.hadoop.yarn.service.utils.ServiceApiUtil.$; public abstract class AbstractProviderService implements ProviderService, @@ -136,6 +142,19 @@ public void buildContainerRetry(AbstractLauncher launcher, } } + public void buildApplicationACLs(AbstractLauncher launcher, + Configuration yarnConf, + ContainerLaunchService.ComponentLaunchContext compLaunchContext) { + Map acls = new HashMap<>(2); + acls.put(ApplicationAccessType.VIEW_APP, YarnServiceConf + .get(YARN_SERVICE_VIEW_ACLS, DEFAULT_YARN_SERVICE_VIEW_ACLS, + compLaunchContext.getConfiguration(), yarnConf)); + acls.put(ApplicationAccessType.MODIFY_APP, YarnServiceConf + .get(YARN_SERVICE_MODIFY_ACLS, DEFAULT_YARN_SERVICE_MODIFY_ACLS, + compLaunchContext.getConfiguration(), yarnConf)); + launcher.setApplicationACLs(acls); + } + public ResolvedLaunchParams buildContainerLaunchContext( AbstractLauncher launcher, Service service, ComponentInstance instance, @@ -171,6 +190,9 @@ public ResolvedLaunchParams buildContainerLaunchContext( // Setup container retry settings buildContainerRetry(launcher, yarnConf, compLaunchContext, instance); + // Setup application ACLs + buildApplicationACLs(launcher, yarnConf, compLaunchContext); + return resolved; } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestYarnNativeServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestYarnNativeServices.java index 948c4076820..360c02f5091 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestYarnNativeServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestYarnNativeServices.java @@ -25,6 +25,7 @@ import org.apache.hadoop.registry.client.binding.RegistryPathUtils; import org.apache.hadoop.registry.client.binding.RegistryUtils; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authorize.AccessControlList; import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.yarn.api.protocolrecords.GetContainersRequest; import org.apache.hadoop.yarn.api.records.*; @@ -33,6 +34,8 @@ import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration; +import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; import org.apache.hadoop.yarn.service.api.records.Component; import org.apache.hadoop.yarn.service.api.records.ComponentState; import org.apache.hadoop.yarn.service.api.records.Configuration; @@ -982,4 +985,60 @@ public void testAMFailureValidity() throws Exception { Assert.assertEquals(ServiceState.STABLE, client.getStatus( exampleApp.getName()).getState()); } + + + @Test (timeout = 200000) + public void testApplicationACLs() throws Exception { + YarnConfiguration conf = new YarnConfiguration(); + conf.set(YarnConfiguration.YARN_ACL_ENABLE, "true"); + conf.set(YarnConfiguration.YARN_ADMIN_ACL, " "); + setConf(conf); + setupInternal(NUM_NMS); + + CapacitySchedulerConfiguration csConf = new CapacitySchedulerConfiguration( + this.getConf()); + Map aclsOnDefault = new HashMap<>(); + AccessControlList submitACL = new AccessControlList("*"); + AccessControlList adminACL = new AccessControlList(" "); + aclsOnDefault.put(QueueACL.SUBMIT_APPLICATIONS, submitACL); + aclsOnDefault.put(QueueACL.ADMINISTER_QUEUE, adminACL); + csConf.setAcls(CapacitySchedulerConfiguration.ROOT + "." + "default", + aclsOnDefault); + // refreshQueue + getYarnCluster().getResourceManager().getResourceScheduler().reinitialize( + csConf, getYarnCluster().getResourceManager().getRMContext()); + + String user = UserGroupInformation.getCurrentUser().getUserName(); + System.setProperty("user.name", user); + + ServiceClient client = createClient(getConf()); + Service exampleApp = new Service(); + exampleApp.setName("example-app"); + exampleApp.setVersion("v1"); + exampleApp.addComponent(createComponent("compa", 2, "sleep 1000")); + Configuration serviceConfig = new Configuration(); + serviceConfig.setProperty("yarn.service.view.acls", "user1"); + serviceConfig.setProperty("yarn.service.modify.acls", "user1"); + exampleApp.setConfiguration(serviceConfig); + client.actionCreate(exampleApp); + waitForServiceToBeStable(client, exampleApp); + + Service appStatus = client.getStatus(exampleApp.getName()); + ApplicationId exampleAppId = ApplicationId.fromString(appStatus.getId()); + + ApplicationACLsManager manager = getYarnCluster().getResourceManager() + .getApplicationACLsManager(); + + UserGroupInformation ugi = UserGroupInformation.createRemoteUser("user1"); + Assert.assertTrue(manager.checkAccess(ugi, ApplicationAccessType.VIEW_APP, + user, exampleAppId)); + Assert.assertTrue(manager.checkAccess(ugi, ApplicationAccessType.MODIFY_APP, + user, exampleAppId)); + + ugi = UserGroupInformation.createRemoteUser("user2"); + Assert.assertFalse(manager.checkAccess(ugi, ApplicationAccessType.VIEW_APP, + user, exampleAppId)); + Assert.assertFalse(manager.checkAccess(ugi, ApplicationAccessType.MODIFY_APP, + user, exampleAppId)); + } }