You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by st...@apache.org on 2014/12/18 22:32:11 UTC
[03/50] incubator-slider git commit: SLIDER-677 enable operation
without keytabs for short lived applications
SLIDER-677 enable operation without keytabs for short lived applications
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/1bdf80cd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/1bdf80cd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/1bdf80cd
Branch: refs/heads/feature/SLIDER-151_REST_API
Commit: 1bdf80cdf0dcc085e9195bfe80b2ebed35f1b2f9
Parents: 3fe140c
Author: Jon Maron <jm...@hortonworks.com>
Authored: Mon Dec 1 15:32:15 2014 -0500
Committer: Jon Maron <jm...@hortonworks.com>
Committed: Mon Dec 1 15:32:15 2014 -0500
----------------------------------------------------------------------
.../slider/core/launch/AppMasterLauncher.java | 22 ++++-
.../providers/agent/AgentProviderService.java | 29 +++---
.../slideram/SliderAMClientProvider.java | 22 +++--
.../server/appmaster/SliderAppMaster.java | 97 ++++++++++++--------
.../security/SecurityConfiguration.java | 20 ++--
.../security/SecurityConfigurationTest.groovy | 15 ---
6 files changed, 118 insertions(+), 87 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/1bdf80cd/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java b/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
index 7023c80..c5526ed 100644
--- a/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
+++ b/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
@@ -21,6 +21,9 @@ package org.apache.slider.core.launch;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.security.SecurityUtil;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.TokenIdentifier;
+import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
import org.apache.hadoop.yarn.api.records.Priority;
@@ -37,6 +40,8 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
+import java.text.DateFormat;
+import java.util.Date;
import java.util.Map;
import java.util.Set;
@@ -218,8 +223,21 @@ public class AppMasterLauncher extends AbstractLauncher {
// For now, only getting tokens for the default file-system.
FileSystem fs = coreFileSystem.getFileSystem();
- fs.addDelegationTokens(tokenRenewer, credentials);
- }
+ Token<? extends TokenIdentifier>[] tokens = fs.addDelegationTokens(tokenRenewer,
+ credentials);
+ // obtain the token expiry from the first token - should be the same for all
+ // HDFS tokens
+ if (tokens != null && tokens.length > 0) {
+ AbstractDelegationTokenIdentifier id =
+ (AbstractDelegationTokenIdentifier)tokens[0].decodeIdentifier();
+ Date d = new Date(id.getIssueDate() + 24*60*60*1000);
+ log.info("HDFS delegation tokens for AM launch context require renewal by {}",
+ DateFormat.getDateTimeInstance().format(d));
+ } else {
+ log.warn("No HDFS delegation tokens obtained for AM launch context");
+ }
+
+ }
/**
* Submit the application.
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/1bdf80cd/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
index 4f981c7..808b15c 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
@@ -523,27 +523,28 @@ public class AgentProviderService extends AbstractProviderService implements
// we need to localize the keytab files in the directory
Path keytabDirPath = fileSystem.buildKeytabPath(keytabDir, null,
getClusterName());
- FileStatus[] keytabs = fileSystem.getFileSystem().listStatus(keytabDirPath);
- LocalResource keytabRes;
boolean serviceKeytabsDeployed = false;
- for (FileStatus keytab : keytabs) {
- if (!amKeytabName.equals(keytab.getPath().getName())
- && keytab.getPath().getName().endsWith(".keytab")) {
- serviceKeytabsDeployed = true;
- log.info("Localizing keytab {}", keytab.getPath().getName());
- keytabRes = fileSystem.createAmResource(keytab.getPath(),
- LocalResourceType.FILE);
- launcher.addLocalResource(SliderKeys.KEYTAB_DIR + "/" +
- keytab.getPath().getName(),
- keytabRes);
+ if (fileSystem.getFileSystem().exists(keytabDirPath)) {
+ FileStatus[] keytabs = fileSystem.getFileSystem().listStatus(keytabDirPath);
+ LocalResource keytabRes;
+ for (FileStatus keytab : keytabs) {
+ if (!amKeytabName.equals(keytab.getPath().getName())
+ && keytab.getPath().getName().endsWith(".keytab")) {
+ serviceKeytabsDeployed = true;
+ log.info("Localizing keytab {}", keytab.getPath().getName());
+ keytabRes = fileSystem.createAmResource(keytab.getPath(),
+ LocalResourceType.FILE);
+ launcher.addLocalResource(SliderKeys.KEYTAB_DIR + "/" +
+ keytab.getPath().getName(),
+ keytabRes);
+ }
}
}
if (!serviceKeytabsDeployed) {
log.warn("No service keytabs for the application have been localized. "
+ "If the application requires keytabs for secure operation, "
+ "please ensure that the required keytabs have been uploaded "
- + "to the folder designated by the property {}: {}",
- SliderXmlConfKeys.KEY_HDFS_KEYTAB_DIR, keytabDirPath);
+ + "to the folder {}", keytabDirPath);
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/1bdf80cd/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
index 5ce0a78..b790713 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
@@ -175,7 +175,6 @@ public class SliderAMClientProvider extends AbstractClientProvider
Map<String, LocalResource> providerResources =
new HashMap<String, LocalResource>();
-
ProviderUtils.addProviderJar(providerResources,
this,
SLIDER_JAR,
@@ -193,10 +192,11 @@ public class SliderAMClientProvider extends AbstractClientProvider
libdir,
libDirProp);
addKeytabResourceIfNecessary(fileSystem,
- launcher,
instanceDescription,
providerResources);
+ launcher.addLocalResources(providerResources);
+
//also pick up all env variables from a map
launcher.copyEnvVars(
instanceDescription.getInternalOperations().getOrAddComponent(
@@ -208,13 +208,11 @@ public class SliderAMClientProvider extends AbstractClientProvider
* authentication, add this keytab as a local resource for the AM launch.
*
* @param fileSystem
- * @param launcher
* @param instanceDescription
* @param providerResources
* @throws IOException
*/
protected void addKeytabResourceIfNecessary(SliderFileSystem fileSystem,
- AbstractLauncher launcher,
AggregateConf instanceDescription,
Map<String, LocalResource> providerResources)
throws IOException {
@@ -231,14 +229,20 @@ public class SliderAMClientProvider extends AbstractClientProvider
SliderXmlConfKeys.KEY_HDFS_KEYTAB_DIR);
Path keytabPath = fileSystem.buildKeytabPath(keytabDir, amKeytabName,
instanceDescription.getName());
- LocalResource keytabRes = fileSystem.createAmResource(keytabPath,
- LocalResourceType.FILE);
+ if (fileSystem.getFileSystem().exists(keytabPath)) {
+ LocalResource keytabRes = fileSystem.createAmResource(keytabPath,
+ LocalResourceType.FILE);
- providerResources.put(SliderKeys.KEYTAB_DIR + "/" +
- amKeytabName, keytabRes);
+ providerResources.put(SliderKeys.KEYTAB_DIR + "/" +
+ amKeytabName, keytabRes);
+ } else {
+ log.warn("No keytab file was found at {}. The AM will be "
+ + "started without a kerberos authenticated identity. "
+ + "The application is therefore not guaranteed to remain "
+ + "operational beyond 24 hours.", keytabPath);
+ }
}
}
- launcher.addLocalResources(providerResources);
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/1bdf80cd/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
index 1bafe4b..a84cf52 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
@@ -33,6 +33,7 @@ import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
import org.apache.hadoop.http.HttpConfig;
import org.apache.hadoop.io.DataOutputBuffer;
+import org.apache.hadoop.io.Text;
import org.apache.hadoop.ipc.ProtocolSignature;
import org.apache.hadoop.registry.client.binding.RegistryUtils;
import org.apache.hadoop.security.Credentials;
@@ -150,7 +151,7 @@ import org.apache.slider.server.appmaster.web.WebAppApi;
import org.apache.slider.server.appmaster.web.WebAppApiImpl;
import org.apache.slider.server.appmaster.web.rest.RestPaths;
import org.apache.slider.server.services.security.CertificateManager;
-import org.apache.slider.server.services.security.FsDelegationTokenManager;
+//import org.apache.slider.server.services.security.FsDelegationTokenManager;
import org.apache.slider.server.services.utility.AbstractSliderLaunchedService;
import org.apache.slider.server.appmaster.management.MetricsBindingService;
import org.apache.slider.server.services.utility.WebAppService;
@@ -376,9 +377,10 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
private String agentOpsUrl;
private String agentStatusUrl;
private YarnRegistryViewForProviders yarnRegistryOperations;
- private FsDelegationTokenManager fsDelegationTokenManager;
+ //private FsDelegationTokenManager fsDelegationTokenManager;
private RegisterApplicationMasterResponse amRegistrationData;
private PortScanner portScanner;
+ private SecurityConfiguration securityConfiguration;
/**
* Service Constructor
@@ -584,7 +586,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
Configuration serviceConf = getConfig();
- SecurityConfiguration securityConfiguration = new SecurityConfiguration(
+ securityConfiguration = new SecurityConfiguration(
serviceConf, instanceDefinition, clustername);
// obtain security state
boolean securityEnabled = securityConfiguration.isSecurityEnabled();
@@ -765,25 +767,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
appInformation.put(ResourceKeys.YARN_CORES, Integer.toString(containerMaxCores));
appInformation.put(ResourceKeys.YARN_MEMORY, Integer.toString(containerMaxMemory));
- // process the initial user to obtain the set of user
- // supplied credentials (tokens were passed in by client). Remove AMRM
- // token and HDFS delegation token, the latter because we will provide an
- // up to date token for container launches (getContainerCredentials()).
- UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
- Credentials credentials = currentUser.getCredentials();
- Iterator<Token<? extends TokenIdentifier>> iter =
- credentials.getAllTokens().iterator();
- while (iter.hasNext()) {
- Token<? extends TokenIdentifier> token = iter.next();
- log.info("Token {}", token.getKind());
- if (token.getKind().equals(AMRMTokenIdentifier.KIND_NAME) ||
- token.getKind().equals(DelegationTokenIdentifier.HDFS_DELEGATION_KIND)) {
- iter.remove();
- }
- }
- // at this point this credentials map is probably clear, but leaving this
- // code to allow for future tokens...
- containerCredentials = credentials;
+ processAMCredentials(securityConfiguration);
if (securityEnabled) {
secretManager.setMasterKey(
@@ -793,17 +777,19 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
//tell the server what the ACLs are
rpcService.getServer().refreshServiceAcl(serviceConf,
new SliderAMPolicyProvider());
- // perform keytab based login to establish kerberos authenticated
- // principal. Can do so now since AM registration with RM above required
- // tokens associated to principal
- String principal = securityConfiguration.getPrincipal();
- File localKeytabFile =
- securityConfiguration.getKeytabFile(instanceDefinition);
- // Now log in...
- login(principal, localKeytabFile);
- // obtain new FS reference that should be kerberos based and different
- // than the previously cached reference
- fs = getClusterFS();
+ if (securityConfiguration.isKeytabProvided()) {
+ // perform keytab based login to establish kerberos authenticated
+ // principal. Can do so now since AM registration with RM above required
+ // tokens associated to principal
+ String principal = securityConfiguration.getPrincipal();
+ File localKeytabFile =
+ securityConfiguration.getKeytabFile(instanceDefinition);
+ // Now log in...
+ login(principal, localKeytabFile);
+ // obtain new FS reference that should be kerberos based and different
+ // than the previously cached reference
+ fs = getClusterFS();
+ }
}
// extract container list
@@ -881,7 +867,8 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
maybeStartMonkey();
// setup token renewal and expiry handling for long lived apps
-// if (SliderUtils.isHadoopClusterSecure(getConfig())) {
+// if (!securityConfiguration.isKeytabProvided() &&
+// SliderUtils.isHadoopClusterSecure(getConfig())) {
// fsDelegationTokenManager = new FsDelegationTokenManager(actionQueues);
// fsDelegationTokenManager.acquireDelegationToken(getConfig());
// }
@@ -929,6 +916,37 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
return finish();
}
+ private void processAMCredentials(SecurityConfiguration securityConfiguration)
+ throws IOException {
+ // process the initial user to obtain the set of user
+ // supplied credentials (tokens were passed in by client). Remove AMRM
+ // token and HDFS delegation token, the latter because we will provide an
+ // up to date token for container launches (getContainerCredentials()).
+ UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
+ Credentials credentials = currentUser.getCredentials();
+ List<Text> filteredTokens = new ArrayList<Text>();
+ filteredTokens.add(AMRMTokenIdentifier.KIND_NAME);
+
+ boolean keytabProvided = securityConfiguration.isKeytabProvided();
+ log.info("Slider AM Security Mode: {}", keytabProvided ? "KEYTAB" : "TOKEN");
+ if (keytabProvided) {
+ filteredTokens.add(DelegationTokenIdentifier.HDFS_DELEGATION_KIND);
+ }
+ Iterator<Token<? extends TokenIdentifier>> iter =
+ credentials.getAllTokens().iterator();
+ while (iter.hasNext()) {
+ Token<? extends TokenIdentifier> token = iter.next();
+ log.info("Token {}", token.getKind());
+ if (filteredTokens.contains(token.getKind())) {
+ log.debug("Filtering token {} from AM tokens", token.getKind());
+ iter.remove();
+ }
+ }
+ // at this point this credentials map is probably clear, but leaving this
+ // code to allow for future tokens...
+ containerCredentials = credentials;
+ }
+
private int getPortToRequest(AggregateConf instanceDefinition)
throws SliderException {
int portToRequest = 0;
@@ -2034,10 +2052,13 @@ the registry with/without the new record format
// the login is via a keytab (see above)
Credentials credentials = new Credentials(containerCredentials);
ByteBuffer tokens = null;
- Token<? extends TokenIdentifier>[] hdfsTokens =
- getClusterFS().getFileSystem().addDelegationTokens(
- UserGroupInformation.getLoginUser().getShortUserName(), credentials);
- if (hdfsTokens.length > 0) {
+ if (securityConfiguration.isKeytabProvided()) {
+ Token<? extends TokenIdentifier>[] hdfsTokens =
+ getClusterFS().getFileSystem().addDelegationTokens(
+ UserGroupInformation.getLoginUser().getShortUserName(),
+ credentials);
+ }
+ if (credentials.getAllTokens().size() > 0) {
DataOutputBuffer dob = new DataOutputBuffer();
credentials.writeTokenStorageToStream(dob);
dob.close();
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/1bdf80cd/slider-core/src/main/java/org/apache/slider/server/appmaster/security/SecurityConfiguration.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/security/SecurityConfiguration.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/security/SecurityConfiguration.java
index 63a7543..4ff6916 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/security/SecurityConfiguration.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/security/SecurityConfiguration.java
@@ -99,15 +99,6 @@ public class SecurityConfiguration {
String keytabName = instanceDefinition.getAppConfOperations()
.getComponent(SliderKeys.COMPONENT_AM)
.get(SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME);
- if (SliderUtils.isUnset(keytabFullPath) && SliderUtils.isUnset(keytabName)) {
- throw new SliderException(SliderExitCodes.EXIT_BAD_CONFIGURATION,
- "Either a keytab path on the cluster host (%s) or a"
- + " keytab to be retrieved from HDFS (%s) are"
- + " required. Please configure one of the keytab"
- + " retrieval mechanisms.",
- SliderXmlConfKeys.KEY_AM_KEYTAB_LOCAL_PATH,
- SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME);
- }
if (SliderUtils.isSet(keytabFullPath) && SliderUtils.isSet(keytabName)) {
throw new SliderException(SliderExitCodes.EXIT_BAD_CONFIGURATION,
"Both a keytab on the cluster host (%s) and a"
@@ -141,6 +132,17 @@ public class SecurityConfiguration {
return principal;
}
+ public boolean isKeytabProvided() {
+ boolean keytabProvided = instanceDefinition.getAppConfOperations()
+ .getComponent(SliderKeys.COMPONENT_AM)
+ .get(SliderXmlConfKeys.KEY_AM_KEYTAB_LOCAL_PATH) != null ||
+ instanceDefinition.getAppConfOperations()
+ .getComponent(SliderKeys.COMPONENT_AM).
+ get(SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME) != null;
+ return keytabProvided;
+
+ }
+
public File getKeytabFile(AggregateConf instanceDefinition)
throws SliderException, IOException {
String keytabFullPath = instanceDefinition.getAppConfOperations()
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/1bdf80cd/slider-core/src/test/groovy/org/apache/slider/server/appmaster/security/SecurityConfigurationTest.groovy
----------------------------------------------------------------------
diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/security/SecurityConfigurationTest.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/security/SecurityConfigurationTest.groovy
index 4b60ead..e543b7c 100644
--- a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/security/SecurityConfigurationTest.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/security/SecurityConfigurationTest.groovy
@@ -118,21 +118,6 @@ public class SecurityConfigurationTest {
}
@Test
- public void testNoKeytabMechanismConfigured() throws Throwable {
- Configuration config = new Configuration()
- config.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, "kerberos")
- AggregateConf aggregateConf = new AggregateConf();
- MapOperations compOps =
- aggregateConf.appConfOperations.getOrAddComponent(SliderKeys.COMPONENT_AM)
- compOps.put(SliderXmlConfKeys.KEY_KEYTAB_PRINCIPAL, "test")
-
- shouldFail(SliderException) {
- SecurityConfiguration securityConfiguration =
- new SecurityConfiguration(config, aggregateConf, "testCluster")
- }
- }
-
- @Test
public void testMissingPrincipalButLoginWithDistributedConfig() throws Throwable {
Configuration config = new Configuration()
config.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, "kerberos")