You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by jm...@apache.org on 2014/10/11 03:28:21 UTC
git commit: SLIDER-491 some corrections to delegation retrieval code
and ability to specify full keytab location in HDFS
Repository: incubator-slider
Updated Branches:
refs/heads/develop da67c440b -> 6f0d9cb65
SLIDER-491 some corrections to delegation retrieval code and ability to specify full keytab location in HDFS
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/6f0d9cb6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/6f0d9cb6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/6f0d9cb6
Branch: refs/heads/develop
Commit: 6f0d9cb6537b7eb3498cab44ff4cfa1404507e7c
Parents: da67c44
Author: Jon Maron <jm...@hortonworks.com>
Authored: Fri Oct 10 18:27:46 2014 -0700
Committer: Jon Maron <jm...@hortonworks.com>
Committed: Fri Oct 10 18:27:46 2014 -0700
----------------------------------------------------------------------
.../apache/slider/common/SliderXmlConfKeys.java | 1 +
.../slider/common/tools/CoreFileSystem.java | 18 ++++---
.../providers/agent/AgentProviderService.java | 30 ++++++-----
.../slideram/SliderAMClientProvider.java | 49 +++++++++++++++++-
.../server/appmaster/SliderAppMaster.java | 37 +++++++-------
.../security/SecurityConfiguration.java | 52 ++++----------------
.../security/SecurityConfigurationTest.groovy | 17 +++++++
7 files changed, 122 insertions(+), 82 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6f0d9cb6/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java b/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java
index cc2a03f..6bc007b 100644
--- a/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java
+++ b/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java
@@ -145,6 +145,7 @@ public interface SliderXmlConfKeys {
"hadoop.http.filter.initializers";
String KEY_KEYSTORE_LOCATION = "ssl.server.keystore.location";
String KEY_AM_LOGIN_KEYTAB_NAME = "slider.am.login.keytab.name";
+ String KEY_HDFS_KEYTAB_DIR = "slider.hdfs.keytab.dir";
String KEY_AM_KEYTAB_LOCAL_PATH = "slider.am.keytab.local.path";
String KEY_KEYTAB_PRINCIPAL = "slider.keytab.principal.name";
String KEY_SECURITY_ENABLED = "site.global.security_enabled";
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6f0d9cb6/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java b/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
index 2ea371b..9a96bd1 100644
--- a/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
+++ b/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
@@ -139,13 +139,17 @@ public class CoreFileSystem {
*
* @return the path for keytab installation location
*/
- public Path buildKeytabPath(String keytabName, String applicationName) {
- Preconditions.checkNotNull(applicationName);
- Path basePath = getBaseApplicationPath();
- Path baseKeytabDir = new Path(basePath, SliderKeys.KEYTAB_DIR);
- Path appKeytabDir = new Path(baseKeytabDir, applicationName);
- return keytabName == null ? appKeytabDir :
- new Path(appKeytabDir, keytabName);
+ public Path buildKeytabPath(String keytabDir, String keytabName, String clusterName) {
+ Path homePath = getHomeDirectory();
+ Path baseKeytabDir;
+ if (keytabDir != null) {
+ baseKeytabDir = new Path(homePath, keytabDir);
+ } else {
+ baseKeytabDir = new Path(buildClusterDirPath(clusterName),
+ SliderKeys.KEYTAB_DIR);
+ }
+ return keytabName == null ? baseKeytabDir :
+ new Path(baseKeytabDir, keytabName);
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6f0d9cb6/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 330ffa3..44777c3 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
@@ -357,20 +357,24 @@ public class AgentProviderService extends AbstractProviderService implements
}
if (SliderUtils.isHadoopClusterSecure(getConfig())) {
- String keytabFullPath = instanceDefinition.getAppConfOperations()
+ String keytabPathOnHost = instanceDefinition.getAppConfOperations()
.getComponent(SliderKeys.COMPONENT_AM).get(
SliderXmlConfKeys.KEY_AM_KEYTAB_LOCAL_PATH);
- String amKeytabName = instanceDefinition.getAppConfOperations()
- .getComponent(SliderKeys.COMPONENT_AM).get(
- SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME);
- if (SliderUtils.isUnset(keytabFullPath)) {
+ if (SliderUtils.isUnset(keytabPathOnHost)) {
+ String amKeytabName = instanceDefinition.getAppConfOperations()
+ .getComponent(SliderKeys.COMPONENT_AM).get(
+ SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME);
+ String keytabDir = instanceDefinition.getAppConfOperations()
+ .getComponent(SliderKeys.COMPONENT_AM).get(
+ SliderXmlConfKeys.KEY_HDFS_KEYTAB_DIR);
// we need to localize the keytab files in the directory
- Path keytabDir = fileSystem.buildKeytabPath(null,
- getAmState().getApplicationName());
- FileStatus[] keytabs = fileSystem.getFileSystem().listStatus(keytabDir);
+ Path keytabDirPath = fileSystem.buildKeytabPath(keytabDir, null,
+ clusterName);
+ FileStatus[] keytabs = fileSystem.getFileSystem().listStatus(keytabDirPath);
LocalResource keytabRes;
for (FileStatus keytab : keytabs) {
- if (!amKeytabName.equals(keytab.getPath().getName())) {
+ if (!amKeytabName.equals(keytab.getPath().getName())
+ && keytab.getPath().getName().endsWith(".keytab")) {
log.info("Localizing keytab {}", keytab.getPath().getName());
keytabRes = fileSystem.createAmResource(keytab.getPath(),
LocalResourceType.FILE);
@@ -678,12 +682,12 @@ public class AgentProviderService extends AbstractProviderService implements
serviceRecord.addInternalEndpoint(
new Endpoint(CustomRegistryConstants.AGENT_SECURE_REST_API,
- ProtocolTypes.PROTOCOL_REST,
- restURL.toURI()));
+ ProtocolTypes.PROTOCOL_REST,
+ restURL.toURI()));
serviceRecord.addInternalEndpoint(
new Endpoint(CustomRegistryConstants.AGENT_ONEWAY_REST_API,
- ProtocolTypes.PROTOCOL_REST,
- agentStatusURL.toURI()));
+ ProtocolTypes.PROTOCOL_REST,
+ agentStatusURL.toURI()));
} catch (URISyntaxException e) {
throw new IOException(e);
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6f0d9cb6/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 991a6b1..5edf1bf 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
@@ -25,12 +25,15 @@ import org.apache.curator.CuratorZookeeperClient;
import org.apache.curator.framework.CuratorFramework;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.api.records.LocalResource;
+import org.apache.hadoop.yarn.api.records.LocalResourceType;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.slider.api.InternalKeys;
import org.apache.slider.api.ResourceKeys;
import org.apache.slider.api.RoleKeys;
import org.apache.slider.common.SliderKeys;
+import org.apache.slider.common.SliderXmlConfKeys;
import org.apache.slider.common.tools.SliderFileSystem;
import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.core.conf.AggregateConf;
@@ -206,8 +209,12 @@ public class SliderAMClientProvider extends AbstractClientProvider
ProviderUtils.addDependencyJars(providerResources, fileSystem, tempPath,
libdir, jars,
classes);
-
- launcher.addLocalResources(providerResources);
+
+ addKeytabResourceIfNecessary(fileSystem,
+ launcher,
+ instanceDescription,
+ providerResources);
+
//also pick up all env variables from a map
launcher.copyEnvVars(
instanceDescription.getInternalOperations().getOrAddComponent(
@@ -215,6 +222,44 @@ public class SliderAMClientProvider extends AbstractClientProvider
}
/**
+ * If the cluster is secure, and an HDFS installed keytab is available for AM
+ * 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 {
+ if (UserGroupInformation.isSecurityEnabled()) {
+ String keytabPathOnHost = instanceDescription.getAppConfOperations()
+ .getComponent(SliderKeys.COMPONENT_AM).get(
+ SliderXmlConfKeys.KEY_AM_KEYTAB_LOCAL_PATH);
+ if (SliderUtils.isUnset(keytabPathOnHost)) {
+ String amKeytabName = instanceDescription.getAppConfOperations()
+ .getComponent(SliderKeys.COMPONENT_AM).get(
+ SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME);
+ String keytabDir = instanceDescription.getAppConfOperations()
+ .getComponent(SliderKeys.COMPONENT_AM).get(
+ SliderXmlConfKeys.KEY_HDFS_KEYTAB_DIR);
+ Path keytabPath = fileSystem.buildKeytabPath(keytabDir, amKeytabName,
+ instanceDescription.getName());
+ LocalResource keytabRes = fileSystem.createAmResource(keytabPath,
+ LocalResourceType.FILE);
+
+ providerResources.put(SliderKeys.KEYTAB_DIR + "/" +
+ amKeytabName, keytabRes);
+ }
+ }
+ launcher.addLocalResources(providerResources);
+ }
+
+ /**
* Update the AM resource with any local needs
* @param capability capability to update
*/
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6f0d9cb6/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 4baa11c..a887cf8 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
@@ -34,6 +34,7 @@ import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.security.SaslRpcServer;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.service.Service;
import org.apache.hadoop.service.ServiceStateChangeListener;
import org.apache.hadoop.yarn.api.ApplicationConstants;
@@ -234,7 +235,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
/**
* token blob
*/
- private Credentials containerTokens;
+ private Credentials containerCredentials;
private WorkflowRpcService rpcService;
@@ -716,12 +717,13 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
// 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 (getContainerTokens()).
+ // up to date token for container launches (getContainerCredentials()).
UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
Credentials credentials = currentUser.getCredentials();
- Iterator<Token<?>> iter = credentials.getAllTokens().iterator();
+ Iterator<Token<? extends TokenIdentifier>> iter =
+ credentials.getAllTokens().iterator();
while (iter.hasNext()) {
- Token<?> token = iter.next();
+ 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)) {
@@ -730,7 +732,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
}
// at this point this credentials map is probably clear, but leaving this
// code to allow for future tokens...
- containerTokens = credentials;
+ containerCredentials = credentials;
if (securityEnabled) {
secretManager.setMasterKey(
@@ -744,8 +746,8 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
// principal. Can do so now since AM registration with RM above required
// tokens associated to principal
String principal = securityConfiguration.getPrincipal();
- File localKeytabFile = securityConfiguration.getKeytabFile(
- fs, instanceDefinition, principal);
+ File localKeytabFile =
+ securityConfiguration.getKeytabFile(instanceDefinition);
// Now log in...
login(principal, localKeytabFile);
// obtain new FS reference that should be kerberos based and different
@@ -898,13 +900,14 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
}
Credentials credentials =
user.getCredentials();
- Iterator<Token<?>> iter = credentials.getAllTokens().iterator();
+ Iterator<Token<? extends TokenIdentifier>> iter =
+ credentials.getAllTokens().iterator();
while (iter.hasNext()) {
- Token<?> token = iter.next();
+ Token<? extends TokenIdentifier> token = iter.next();
log.info("Token {}", token.getKind());
if (token.getKind().equals(
DelegationTokenIdentifier.HDFS_DELEGATION_KIND)) {
- log.info("Unexpected HDFS delegation token. Removing...");
+ log.info("HDFS delegation token {}. Removing...", token);
iter.remove();
}
}
@@ -1907,7 +1910,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
// inside the distributed shell.
// add current HDFS delegation token with an up to date token
- ByteBuffer tokens = getContainerTokens();
+ ByteBuffer tokens = getContainerCredentials();
if (tokens != null) {
ctx.setTokens(tokens);
@@ -1918,15 +1921,15 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
nmClientAsync.startContainerAsync(container, ctx);
}
- private ByteBuffer getContainerTokens() throws IOException {
+ private ByteBuffer getContainerCredentials() throws IOException {
// a delegation token can be retrieved from filesystem since
// the login is via a keytab (see above)
+ Credentials credentials = new Credentials(containerCredentials);
ByteBuffer tokens = null;
- Token hdfsToken = getClusterFS().getFileSystem().getDelegationToken
- (UserGroupInformation.getLoginUser().getShortUserName());
- if (hdfsToken != null) {
- Credentials credentials = new Credentials(containerTokens);
- credentials.addToken(hdfsToken.getKind(), hdfsToken);
+ Token<? extends TokenIdentifier> hdfsTokens[] =
+ getClusterFS().getFileSystem().addDelegationTokens(
+ UserGroupInformation.getLoginUser().getShortUserName(), credentials);
+ if (hdfsTokens.length > 0) {
DataOutputBuffer dob = new DataOutputBuffer();
credentials.writeTokenStorageToStream(dob);
dob.close();
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6f0d9cb6/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 e5cdad2..63a7543 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
@@ -141,8 +141,7 @@ public class SecurityConfiguration {
return principal;
}
- public File getKeytabFile(SliderFileSystem fs,
- AggregateConf instanceDefinition, String principal)
+ public File getKeytabFile(AggregateConf instanceDefinition)
throws SliderException, IOException {
String keytabFullPath = instanceDefinition.getAppConfOperations()
.getComponent(SliderKeys.COMPONENT_AM)
@@ -151,52 +150,19 @@ public class SecurityConfiguration {
if (SliderUtils.isUnset(keytabFullPath)) {
// get the keytab
String keytabName = instanceDefinition.getAppConfOperations()
- .getComponent(SliderKeys.COMPONENT_AM).get(SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME);
- log.info("No host keytab file path specified. Downloading keytab {}"
- + " from HDFS to perform login of using principal {}",
- keytabName, principal);
+ .getComponent(SliderKeys.COMPONENT_AM).
+ get(SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME);
+ log.info("No host keytab file path specified. Will attempt to retrieve"
+ + " keytab file {} as a local resource for the container",
+ keytabName);
// download keytab to local, protected directory
- localKeytabFile = getFileFromFileSystem(fs, keytabName);
+ localKeytabFile = new File(SliderKeys.KEYTAB_DIR, keytabName);
} else {
- log.info("Leveraging host keytab file {} to login principal {}",
- keytabFullPath, principal);
+ log.info("Leveraging host keytab file {} for login",
+ keytabFullPath);
localKeytabFile = new File(keytabFullPath);
}
return localKeytabFile;
}
- /**
- * Download the keytab file from FileSystem to local file.
- * @param fs
- * @param keytabName
- * @return
- * @throws SliderException
- * @throws IOException
- */
- protected File getFileFromFileSystem(SliderFileSystem fs, String keytabName)
- throws SliderException, IOException {
- File keytabDestinationDir = new File(
- FileUtils.getTempDirectory().getAbsolutePath() +
- "/keytab" + System.currentTimeMillis());
- if (!keytabDestinationDir.mkdirs()) {
- throw new SliderException("Unable to create local keytab directory");
- }
- RawLocalFileSystem fileSystem = new RawLocalFileSystem();
- // allow app user to access local keytab dir
- FsPermission permissions = new FsPermission(FsAction.ALL, FsAction.NONE,
- FsAction.NONE);
- fileSystem.setPermission(new Path(keytabDestinationDir.getAbsolutePath()),
- permissions);
-
- Path keytabPath = fs.buildKeytabPath(keytabName, clusterName);
- File localKeytabFile = new File(keytabDestinationDir, keytabName);
- FileUtil.copy(fs.getFileSystem(), keytabPath,
- localKeytabFile,
- false, configuration);
- // set permissions on actual keytab file to be read-only for user
- permissions = new FsPermission(FsAction.READ, FsAction.NONE, FsAction.NONE);
- fileSystem.setPermission(new Path(localKeytabFile.getAbsolutePath()),
- permissions);
- return localKeytabFile;
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6f0d9cb6/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 4ef142a..4b60ead 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
@@ -157,4 +157,21 @@ public class SecurityConfigurationTest {
SecurityConfiguration securityConfiguration =
new SecurityConfiguration(config, aggregateConf, "testCluster")
}
+
+ @Test
+ public void testKeypathLocationOnceLocalized() 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_AM_LOGIN_KEYTAB_NAME, "some.keytab")
+
+ SecurityConfiguration securityConfiguration =
+ new SecurityConfiguration(config, aggregateConf, "testCluster")
+
+ assert new File(SliderKeys.KEYTAB_DIR, "some.keytab").getAbsolutePath() ==
+ securityConfiguration.getKeytabFile(aggregateConf).getAbsolutePath()
+ }
+
}