You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2018/01/02 16:55:54 UTC
[03/37] ambari git commit: AMBARI-22530. Refactor internal code of
handling info between kerberos wizard actions (echekanskiy)
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
index 5ec4c10..a803dcf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
@@ -34,10 +34,11 @@ import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.KerberosHelper;
import org.apache.ambari.server.orm.dao.HostDAO;
import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
-import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
-import org.apache.ambari.server.orm.entities.HostEntity;
import org.apache.ambari.server.orm.entities.KerberosPrincipalEntity;
import org.apache.ambari.server.serveraction.ActionLog;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.KerberosKeytabController;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.directory.server.kerberos.shared.keytab.Keytab;
import org.slf4j.Logger;
@@ -52,7 +53,7 @@ import com.google.inject.Inject;
* This class mainly relies on the KerberosServerAction to iterate through metadata identifying
* the Kerberos keytab files that need to be created. For each identity in the metadata, this
* implementation's
- * {@link KerberosServerAction#processIdentity(Map, String, KerberosOperationHandler, Map, Map)}
+ * {@link KerberosServerAction#processIdentity(ResolvedKerberosPrincipal, KerberosOperationHandler, Map, Map)}
* is invoked attempting the creation of the relevant keytab file.
*/
public class CreateKeytabFilesServerAction extends KerberosServerAction {
@@ -65,12 +66,6 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
private KerberosPrincipalDAO kerberosPrincipalDAO;
/**
- * KerberosPrincipalHostDAO used to get Kerberos principal details
- */
- @Inject
- private KerberosPrincipalHostDAO kerberosPrincipalHostDAO;
-
- /**
* Configuration used to get the configured properties such as the keytab file cache directory
*/
@Inject
@@ -82,6 +77,9 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
@Inject
private HostDAO hostDAO;
+ @Inject
+ private KerberosKeytabController kerberosKeytabController;
+
/**
* A map of data used to track what has been processed in order to optimize the creation of keytabs
* such as knowing when to create a cached keytab file or use a cached keytab file.
@@ -118,10 +116,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
* If a password exists for the current evaluatedPrincipal, use a
* {@link org.apache.ambari.server.serveraction.kerberos.KerberosOperationHandler} to generate
* the keytab file. To help avoid filename collisions and to build a structure that is easy to
- * discover, each keytab file is stored in host-specific
- * ({@link org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReader#HOSTNAME})
- * directory using the SHA1 hash of its destination file path
- * ({@link org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReader#KEYTAB_FILE_PATH})
+ * discover, each keytab file is stored in host-specific directory using the SHA1 hash of its destination file path.
* <p/>
* <pre>
* data_directory
@@ -133,8 +128,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
* | |- ...
* </pre>
*
- * @param identityRecord a Map containing the data for the current identity record
- * @param evaluatedPrincipal a String indicating the relevant principal
+ * @param resolvedPrincipal a ResolvedKerberosPrincipal object to process
* @param operationHandler a KerberosOperationHandler used to perform Kerberos-related
* tasks for specific Kerberos implementations
* (MIT, Active Directory, etc...)
@@ -145,7 +139,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
* @throws AmbariException if an error occurs while processing the identity record
*/
@Override
- protected CommandReport processIdentity(Map<String, String> identityRecord, String evaluatedPrincipal,
+ protected CommandReport processIdentity(ResolvedKerberosPrincipal resolvedPrincipal,
KerberosOperationHandler operationHandler,
Map<String, String> kerberosConfiguration,
Map<String, Object> requestSharedDataContext)
@@ -160,40 +154,42 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
CommandReport commandReport = null;
String message = null;
- try {
- if (identityRecord != null) {
- String dataDirectory = getDataDirectoryPath();
- if (operationHandler == null) {
- message = String.format("Failed to create keytab file for %s, missing KerberosOperationHandler", evaluatedPrincipal);
- actionLog.writeStdErr(message);
- LOG.error(message);
- commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
- } else if (dataDirectory == null) {
- message = "The data directory has not been set. Generated keytab files can not be stored.";
- LOG.error(message);
- commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
- } else {
- Map<String, String> principalPasswordMap = getPrincipalPasswordMap(requestSharedDataContext);
- Map<String, Integer> principalKeyNumberMap = getPrincipalKeyNumberMap(requestSharedDataContext);
+ Set<ResolvedKerberosKeytab> keytabsToCreate = kerberosKeytabController.getFromPrincipal(resolvedPrincipal);
- String hostName = identityRecord.get(KerberosIdentityDataFileReader.HOSTNAME);
- String keytabFilePath = identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_PATH);
+ try {
+ String dataDirectory = getDataDirectoryPath();
+
+ if (operationHandler == null) {
+ message = String.format("Failed to create keytab file for %s, missing KerberosOperationHandler", resolvedPrincipal.getPrincipal());
+ actionLog.writeStdErr(message);
+ LOG.error(message);
+ commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
+ } else if (dataDirectory == null) {
+ message = "The data directory has not been set. Generated keytab files can not be stored.";
+ LOG.error(message);
+ commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
+ } else {
+ Map<String, String> principalPasswordMap = getPrincipalPasswordMap(requestSharedDataContext);
+ Map<String, Integer> principalKeyNumberMap = getPrincipalKeyNumberMap(requestSharedDataContext);
+ for (ResolvedKerberosKeytab rkk : keytabsToCreate) {
+ String hostName = resolvedPrincipal.getHostName();
+ String keytabFilePath = rkk.getFile();
if ((hostName != null) && !hostName.isEmpty() && (keytabFilePath != null) && !keytabFilePath.isEmpty()) {
- Set<String> visitedPrincipalKeys = visitedIdentities.get(evaluatedPrincipal);
+ Set<String> visitedPrincipalKeys = visitedIdentities.get(resolvedPrincipal.getPrincipal());
String visitationKey = String.format("%s|%s", hostName, keytabFilePath);
if ((visitedPrincipalKeys == null) || !visitedPrincipalKeys.contains(visitationKey)) {
// Look up the current evaluatedPrincipal's password.
// If found create the keytab file, else try to find it in the cache.
- String password = principalPasswordMap.get(evaluatedPrincipal);
- Integer keyNumber = principalKeyNumberMap.get(evaluatedPrincipal);
+ String password = principalPasswordMap.get(resolvedPrincipal.getPrincipal());
+ Integer keyNumber = principalKeyNumberMap.get(resolvedPrincipal.getPrincipal());
- message = String.format("Creating keytab file for %s on host %s", evaluatedPrincipal, hostName);
+ message = String.format("Creating keytab file for %s on host %s", resolvedPrincipal.getPrincipal(), hostName);
LOG.info(message);
actionLog.writeStdOut(message);
- auditEventBuilder.withPrincipal(evaluatedPrincipal).withHostName(hostName).withKeyTabFilePath(keytabFilePath);
+ auditEventBuilder.withPrincipal(resolvedPrincipal.getPrincipal()).withHostName(hostName).withKeyTabFilePath(keytabFilePath);
// Determine where to store the keytab file. It should go into a host-specific
// directory under the previously determined data directory.
@@ -206,32 +202,22 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
}
if (hostDirectory.exists()) {
- File destinationKeytabFile = new File(hostDirectory, DigestUtils.sha1Hex(keytabFilePath));
- HostEntity hostEntity = hostDAO.findByName(hostName);
- // in case of ambari-server identity there's no host entity for ambari_server host
- if (hostEntity == null && !hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME)) {
- message = "Failed to find HostEntity for hostname = " + hostName;
- actionLog.writeStdErr(message);
- LOG.error(message);
- commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
- return commandReport;
- }
+ File destinationKeytabFile = new File(hostDirectory, DigestUtils.sha256Hex(keytabFilePath));
boolean regenerateKeytabs = getOperationType(getCommandParameters()) == OperationType.RECREATE_ALL;
- KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
+ KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(resolvedPrincipal.getPrincipal());
String cachedKeytabPath = (principalEntity == null) ? null : principalEntity.getCachedKeytabPath();
if (password == null) {
- if (!regenerateKeytabs && (hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME) || kerberosPrincipalHostDAO
- .exists(evaluatedPrincipal, hostEntity.getHostId(), keytabFilePath)) && cachedKeytabPath == null) {
+ if (!regenerateKeytabs && hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME)) {
// There is nothing to do for this since it must already exist and we don't want to
// regenerate the keytab
- message = String.format("Skipping keytab file for %s, missing password indicates nothing to do", evaluatedPrincipal);
+ message = String.format("Skipping keytab file for %s, missing password indicates nothing to do", resolvedPrincipal.getPrincipal());
LOG.debug(message);
} else {
if (cachedKeytabPath == null) {
- message = String.format("Failed to create keytab for %s, missing cached file", evaluatedPrincipal);
+ message = String.format("Failed to create keytab for %s, missing cached file", resolvedPrincipal.getPrincipal());
actionLog.writeStdErr(message);
LOG.error(message);
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
@@ -239,7 +225,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
try {
operationHandler.createKeytabFile(new File(cachedKeytabPath), destinationKeytabFile);
} catch (KerberosOperationException e) {
- message = String.format("Failed to create keytab file for %s - %s", evaluatedPrincipal, e.getMessage());
+ message = String.format("Failed to create keytab file for %s - %s", resolvedPrincipal.getPrincipal(), e.getMessage());
actionLog.writeStdErr(message);
LOG.error(message, e);
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
@@ -247,24 +233,24 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
}
}
} else {
- Keytab keytab = createKeytab(evaluatedPrincipal, password, keyNumber, operationHandler, visitedPrincipalKeys != null, true, actionLog);
+ Keytab keytab = createKeytab(resolvedPrincipal.getPrincipal(), password, keyNumber, operationHandler, visitedPrincipalKeys != null, true, actionLog);
if (keytab != null) {
try {
if (operationHandler.createKeytabFile(keytab, destinationKeytabFile)) {
ensureAmbariOnlyAccess(destinationKeytabFile);
- message = String.format("Successfully created keytab file for %s at %s", evaluatedPrincipal, destinationKeytabFile.getAbsolutePath());
+ message = String.format("Successfully created keytab file for %s at %s", resolvedPrincipal.getPrincipal(), destinationKeytabFile.getAbsolutePath());
LOG.debug(message);
- auditEventBuilder.withPrincipal(evaluatedPrincipal).withHostName(hostName).withKeyTabFilePath(destinationKeytabFile.getAbsolutePath());
+ auditEventBuilder.withPrincipal(resolvedPrincipal.getPrincipal()).withHostName(hostName).withKeyTabFilePath(destinationKeytabFile.getAbsolutePath());
} else {
- message = String.format("Failed to create keytab file for %s at %s", evaluatedPrincipal, destinationKeytabFile.getAbsolutePath());
+ message = String.format("Failed to create keytab file for %s at %s", resolvedPrincipal.getPrincipal(), destinationKeytabFile.getAbsolutePath());
actionLog.writeStdErr(message);
LOG.error(message);
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
}
} catch (KerberosOperationException e) {
- message = String.format("Failed to create keytab file for %s - %s", evaluatedPrincipal, e.getMessage());
+ message = String.format("Failed to create keytab file for %s - %s", resolvedPrincipal.getPrincipal(), e.getMessage());
actionLog.writeStdErr(message);
LOG.error(message, e);
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
@@ -275,20 +261,20 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
if (visitedPrincipalKeys == null) {
visitedPrincipalKeys = new HashSet<>();
- visitedIdentities.put(evaluatedPrincipal, visitedPrincipalKeys);
+ visitedIdentities.put(resolvedPrincipal.getPrincipal(), visitedPrincipalKeys);
}
visitedPrincipalKeys.add(visitationKey);
}
} else {
message = String.format("Failed to create keytab file for %s, the container directory does not exist: %s",
- evaluatedPrincipal, hostDirectory.getAbsolutePath());
+ resolvedPrincipal.getPrincipal(), hostDirectory.getAbsolutePath());
actionLog.writeStdErr(message);
LOG.error(message);
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
}
} else {
- LOG.debug("Skipping previously processed keytab for {} on host {}", evaluatedPrincipal, hostName);
+ LOG.debug("Skipping previously processed keytab for {} on host {}", resolvedPrincipal.getPrincipal(), hostName);
}
}
}
@@ -420,7 +406,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
}
}
- File cachedKeytabFile = new File(cacheDirectory, DigestUtils.sha1Hex(principal + String.valueOf(System.currentTimeMillis())));
+ File cachedKeytabFile = new File(cacheDirectory, DigestUtils.sha256Hex(principal + String.valueOf(System.currentTimeMillis())));
try {
keytab.write(cachedKeytabFile);
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
index 0c90659..a108c9b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java
@@ -28,12 +28,13 @@ import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.audit.event.kerberos.CreatePrincipalKerberosAuditEvent;
+import org.apache.ambari.server.orm.dao.KerberosKeytabPrincipalDAO;
import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
-import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
+import org.apache.ambari.server.orm.entities.KerberosKeytabPrincipalEntity;
import org.apache.ambari.server.orm.entities.KerberosPrincipalEntity;
-import org.apache.ambari.server.orm.entities.KerberosPrincipalHostEntity;
import org.apache.ambari.server.security.SecurePasswordHelper;
import org.apache.ambari.server.serveraction.ActionLog;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,7 +46,7 @@ import com.google.inject.Inject;
* <p/>
* This class mainly relies on the KerberosServerAction to iterate through metadata identifying
* the Kerberos principals that need to be created. For each identity in the metadata, this implementation's
- * {@link KerberosServerAction#processIdentity(Map, String, KerberosOperationHandler, Map, Map)}
+ * {@link KerberosServerAction#processIdentity(ResolvedKerberosPrincipal, KerberosOperationHandler, Map, Map)}
* is invoked attempting the creation of the relevant principal.
*/
public class CreatePrincipalsServerAction extends KerberosServerAction {
@@ -58,17 +59,14 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
private KerberosPrincipalDAO kerberosPrincipalDAO;
/**
- * KerberosPrincipalHostDAO used to get Kerberos principal details
- */
- @Inject
- private KerberosPrincipalHostDAO kerberosPrincipalHostDAO;
-
- /**
* SecurePasswordHelper used to generate secure passwords for newly created principals
*/
@Inject
private SecurePasswordHelper securePasswordHelper;
+ @Inject
+ private KerberosKeytabPrincipalDAO kerberosKeytabPrincipalDAO;
+
/**
* A set of visited principal names used to prevent unnecessary processing on already processed
* principal names
@@ -106,8 +104,7 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
* store the new key numbers in the shared principal-to-key_number map so that subsequent process
* may use the data if necessary.
*
- * @param identityRecord a Map containing the data for the current identity record
- * @param evaluatedPrincipal a String indicating the relevant principal
+ * @param resolvedPrincipal a ResolvedKerberosPrincipal object to process
* @param operationHandler a KerberosOperationHandler used to perform Kerberos-related
* tasks for specific Kerberos implementations
* (MIT, Active Directory, etc...)
@@ -118,7 +115,7 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
* @throws AmbariException if an error occurs while processing the identity record
*/
@Override
- protected CommandReport processIdentity(Map<String, String> identityRecord, String evaluatedPrincipal,
+ protected CommandReport processIdentity(ResolvedKerberosPrincipal resolvedPrincipal,
KerberosOperationHandler operationHandler,
Map<String, String> kerberosConfiguration,
Map<String, Object> requestSharedDataContext)
@@ -126,16 +123,16 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
CommandReport commandReport = null;
// Only process this principal name if we haven't already processed it
- if (!seenPrincipals.contains(evaluatedPrincipal)) {
- seenPrincipals.add(evaluatedPrincipal);
+ // TODO optimize - split invalidation and principal creation to separate stages
+ if (!seenPrincipals.contains(resolvedPrincipal.getPrincipal())) {
+ seenPrincipals.add(resolvedPrincipal.getPrincipal());
boolean processPrincipal;
- // TODO add invalidate_principals option to make keytabs invalid all over the cluster.
- KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
+ KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(resolvedPrincipal.getPrincipal());
boolean regenerateKeytabs = getOperationType(getCommandParameters()) == OperationType.RECREATE_ALL;
- boolean servicePrincipal = "service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE));
+ boolean servicePrincipal = resolvedPrincipal.isService();
if (regenerateKeytabs) {
// force recreation of principal due to keytab regeneration
// regenerate only service principals if request filtered by hosts
@@ -154,24 +151,24 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
if (processPrincipal) {
Map<String, String> principalPasswordMap = getPrincipalPasswordMap(requestSharedDataContext);
- String password = principalPasswordMap.get(evaluatedPrincipal);
+ String password = principalPasswordMap.get(resolvedPrincipal.getPrincipal());
if (password == null) {
- CreatePrincipalResult result = createPrincipal(evaluatedPrincipal, servicePrincipal, kerberosConfiguration, operationHandler, regenerateKeytabs, actionLog);
+ CreatePrincipalResult result = createPrincipal(resolvedPrincipal.getPrincipal(), servicePrincipal, kerberosConfiguration, operationHandler, regenerateKeytabs, actionLog);
if (result == null) {
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
} else {
Map<String, Integer> principalKeyNumberMap = getPrincipalKeyNumberMap(requestSharedDataContext);
- principalPasswordMap.put(evaluatedPrincipal, result.getPassword());
- principalKeyNumberMap.put(evaluatedPrincipal, result.getKeyNumber());
+ principalPasswordMap.put(resolvedPrincipal.getPrincipal(), result.getPassword());
+ principalKeyNumberMap.put(resolvedPrincipal.getPrincipal(), result.getKeyNumber());
// invalidate given principal for all keytabs to make them redistributed again
- for (KerberosPrincipalHostEntity kphe: kerberosPrincipalHostDAO.findByPrincipal(evaluatedPrincipal)) {
- kphe.setDistributed(false);
- kerberosPrincipalHostDAO.merge(kphe);
+ for (KerberosKeytabPrincipalEntity kkpe: kerberosKeytabPrincipalDAO.findByPrincipal(resolvedPrincipal.getPrincipal())) {
+ kkpe.setDistributed(false);
+ kerberosKeytabPrincipalDAO.merge(kkpe);
}
// invalidate principal cache
- KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
+ KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(resolvedPrincipal.getPrincipal());
try {
new File(principalEntity.getCachedKeytabPath()).delete();
} catch (Exception e) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
index 4c80bd4..7c28494 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java
@@ -29,8 +29,13 @@ import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.audit.event.kerberos.DestroyPrincipalKerberosAuditEvent;
import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
+import org.apache.ambari.server.orm.dao.KerberosKeytabPrincipalDAO;
import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
+import org.apache.ambari.server.orm.entities.KerberosKeytabEntity;
import org.apache.ambari.server.orm.entities.KerberosPrincipalEntity;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
import org.apache.ambari.server.utils.ShellCommandUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,7 +48,7 @@ import com.google.inject.Inject;
* This class mainly relies on the KerberosServerAction to iterate through metadata identifying
* the Kerberos principals that need to be removed from the relevant KDC. For each identity in the
* metadata, this implementation's
- * {@link KerberosServerAction#processIdentity(Map, String, KerberosOperationHandler, Map, Map)}
+ * {@link KerberosServerAction#processIdentity(ResolvedKerberosPrincipal, KerberosOperationHandler, Map, Map)}
* is invoked attempting the removal of the relevant principal.
*/
public class DestroyPrincipalsServerAction extends KerberosServerAction {
@@ -52,6 +57,12 @@ public class DestroyPrincipalsServerAction extends KerberosServerAction {
@Inject
private KerberosPrincipalDAO kerberosPrincipalDAO;
+ @Inject
+ private KerberosKeytabPrincipalDAO kerberosKeytabPrincipalDAO;
+
+ @Inject
+ private KerberosKeytabDAO kerberosKeytabDAO;
+
/**
* A set of visited principal names used to prevent unnecessary processing on already processed
* principal names
@@ -81,8 +92,7 @@ public class DestroyPrincipalsServerAction extends KerberosServerAction {
/**
* For each identity, remove the principal from the configured KDC.
*
- * @param identityRecord a Map containing the data for the current identity record
- * @param evaluatedPrincipal a String indicating the relevant principal
+ * @param resolvedPrincipal a ResolvedKerberosPrincipal object to process
* @param operationHandler a KerberosOperationHandler used to perform Kerberos-related
* tasks for specific Kerberos implementations
* (MIT, Active Directory, etc...)
@@ -93,69 +103,73 @@ public class DestroyPrincipalsServerAction extends KerberosServerAction {
* @throws org.apache.ambari.server.AmbariException if an error occurs while processing the identity record
*/
@Override
- protected CommandReport processIdentity(Map<String, String> identityRecord, String evaluatedPrincipal,
+ protected CommandReport processIdentity(ResolvedKerberosPrincipal resolvedPrincipal,
KerberosOperationHandler operationHandler,
Map<String, String> kerberosConfiguration,
Map<String, Object> requestSharedDataContext)
throws AmbariException {
// Only process this principal if we haven't already processed it
- if (!seenPrincipals.contains(evaluatedPrincipal)) {
- seenPrincipals.add(evaluatedPrincipal);
+ if (!seenPrincipals.contains(resolvedPrincipal.getPrincipal())) {
+ seenPrincipals.add(resolvedPrincipal.getPrincipal());
- String message = String.format("Destroying identity, %s", evaluatedPrincipal);
+ String message = String.format("Destroying identity, %s", resolvedPrincipal.getPrincipal());
LOG.info(message);
actionLog.writeStdOut(message);
DestroyPrincipalKerberosAuditEvent.DestroyPrincipalKerberosAuditEventBuilder auditEventBuilder = DestroyPrincipalKerberosAuditEvent.builder()
.withTimestamp(System.currentTimeMillis())
.withRequestId(getHostRoleCommand().getRequestId())
.withTaskId(getHostRoleCommand().getTaskId())
- .withPrincipal(evaluatedPrincipal);
+ .withPrincipal(resolvedPrincipal.getPrincipal());
try {
try {
- boolean servicePrincipal = "service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE));
- operationHandler.removePrincipal(evaluatedPrincipal, servicePrincipal);
+ boolean servicePrincipal = resolvedPrincipal.isService();
+ operationHandler.removePrincipal(resolvedPrincipal.getPrincipal(), servicePrincipal);
} catch (KerberosOperationException e) {
- message = String.format("Failed to remove identity for %s from the KDC - %s", evaluatedPrincipal, e.getMessage());
+ message = String.format("Failed to remove identity for %s from the KDC - %s", resolvedPrincipal.getPrincipal(), e.getMessage());
LOG.warn(message);
actionLog.writeStdErr(message);
auditEventBuilder.withReasonOfFailure(message);
}
try {
- KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
+ KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(resolvedPrincipal.getPrincipal());
if (principalEntity != null) {
String cachedKeytabPath = principalEntity.getCachedKeytabPath();
-
+ KerberosKeytabEntity kke = kerberosKeytabDAO.find(resolvedPrincipal.getResolvedKerberosKeytab().getFile());
+ kerberosKeytabDAO.remove(kke);
kerberosPrincipalDAO.remove(principalEntity);
// If a cached keytabs file exists for this principal, delete it.
if (cachedKeytabPath != null) {
if (!new File(cachedKeytabPath).delete()) {
- LOG.debug("Failed to remove cached keytab for {}", evaluatedPrincipal);
+ LOG.debug("Failed to remove cached keytab for {}", resolvedPrincipal.getPrincipal());
}
}
}
// delete Ambari server keytab
- String hostName = identityRecord.get(KerberosIdentityDataFileReader.HOSTNAME);
+ String hostName = resolvedPrincipal.getHostName();
if (hostName != null && hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME)) {
- String keytabFilePath = identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_PATH);
- if (keytabFilePath != null) {
- try {
- ShellCommandUtil.Result result = ShellCommandUtil.delete(keytabFilePath, true, true);
- if (!result.isSuccessful()) {
- LOG.warn("Failed to remove ambari keytab for {} due to {}", evaluatedPrincipal, result.getStderr());
+ ResolvedKerberosKeytab resolvedKeytab = resolvedPrincipal.getResolvedKerberosKeytab();
+ if (resolvedKeytab != null) {
+ String keytabFilePath = resolvedKeytab.getFile();
+ if (keytabFilePath != null) {
+ try {
+ ShellCommandUtil.Result result = ShellCommandUtil.delete(keytabFilePath, true, true);
+ if (!result.isSuccessful()) {
+ LOG.warn("Failed to remove ambari keytab for {} due to {}", resolvedPrincipal.getPrincipal(), result.getStderr());
+ }
+ } catch (IOException|InterruptedException e) {
+ LOG.warn("Failed to remove ambari keytab for " + resolvedPrincipal.getPrincipal(), e);
}
- } catch (IOException|InterruptedException e) {
- LOG.warn("Failed to remove ambari keytab for " + evaluatedPrincipal, e);
}
}
}
} catch (Throwable t) {
- message = String.format("Failed to remove identity for %s from the Ambari database - %s", evaluatedPrincipal, t.getMessage());
+ message = String.format("Failed to remove identity for %s from the Ambari database - %s", resolvedPrincipal.getPrincipal(), t.getMessage());
LOG.warn(message);
actionLog.writeStdErr(message);
auditEventBuilder.withReasonOfFailure(message);
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
index bfd5e40..225e53e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/FinalizeKerberosServerAction.java
@@ -26,9 +26,10 @@ import java.util.concurrent.ConcurrentMap;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
import org.apache.ambari.server.utils.ShellCommandUtil;
import org.apache.ambari.server.utils.StageUtils;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,8 +44,7 @@ public class FinalizeKerberosServerAction extends KerberosServerAction {
* some user accounts and groups may not have been available (at the OS level) when the keytab files
* were created.
*
- * @param identityRecord a Map containing the data for the current identity record
- * @param evaluatedPrincipal a String indicating the relevant principal
+ * @param resolvedPrincipal a ResolvedKerberosPrincipal object to process
* @param operationHandler a KerberosOperationHandler used to perform Kerberos-related
* tasks for specific Kerberos implementations
* (MIT, Active Directory, etc...)
@@ -54,39 +54,39 @@ public class FinalizeKerberosServerAction extends KerberosServerAction {
* @throws AmbariException
*/
@Override
- protected CommandReport processIdentity(Map<String, String> identityRecord, String evaluatedPrincipal,
+ protected CommandReport processIdentity(ResolvedKerberosPrincipal resolvedPrincipal,
KerberosOperationHandler operationHandler,
Map<String, String> kerberosConfiguration,
Map<String, Object> requestSharedDataContext)
throws AmbariException {
- if (identityRecord != null) {
+ if (resolvedPrincipal != null) {
// If the record's HOSTNAME value is "ambari-server", rather than an actual hostname it will
// not match the Ambari server's host name. This will occur if the there is no agent installed
// on the Ambari server host. This is ok, since any keytab files installed on the Ambari server
// host will already have the permissions set so that only the Ambari server can read it.
// There is no need to update the permissions for those keytab files so that installed services
// can access them since no services will be installed on the host.
- if (StageUtils.getHostName().equals(identityRecord.get(KerberosIdentityDataFile.HOSTNAME))) {
+ if (StageUtils.getHostName().equals(resolvedPrincipal.getHostName())) {
// If the principal name exists in one of the shared data maps, it has been processed by the
// current "Enable Kerberos" or "Add component" workflow and therefore should already have
// the correct permissions assigned. The relevant keytab files can be skipped.
Map<String, String> principalPasswordMap = getPrincipalPasswordMap(requestSharedDataContext);
- if ((principalPasswordMap == null) || !principalPasswordMap.containsKey(evaluatedPrincipal)) {
+ if ((principalPasswordMap == null) || !principalPasswordMap.containsKey(resolvedPrincipal.getPrincipal())) {
- String keytabFilePath = identityRecord.get(KerberosIdentityDataFile.KEYTAB_FILE_PATH);
+ String keytabFilePath = resolvedPrincipal.getKeytabPath();
if (!StringUtils.isEmpty(keytabFilePath)) {
Set<String> visited = (Set<String>) requestSharedDataContext.get(this.getClass().getName() + "_visited");
if (!visited.contains(keytabFilePath)) {
- String ownerName = identityRecord.get(KerberosIdentityDataFile.KEYTAB_FILE_OWNER_NAME);
- String ownerAccess = identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_OWNER_ACCESS);
+ String ownerName = resolvedPrincipal.getResolvedKerberosKeytab().getOwnerName();
+ String ownerAccess = resolvedPrincipal.getResolvedKerberosKeytab().getOwnerAccess();
boolean ownerWritable = "w".equalsIgnoreCase(ownerAccess) || "rw".equalsIgnoreCase(ownerAccess);
boolean ownerReadable = "r".equalsIgnoreCase(ownerAccess) || "rw".equalsIgnoreCase(ownerAccess);
- String groupName = identityRecord.get(KerberosIdentityDataFile.KEYTAB_FILE_GROUP_NAME);
- String groupAccess = identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_OWNER_ACCESS);
+ String groupName = resolvedPrincipal.getResolvedKerberosKeytab().getGroupName();
+ String groupAccess = resolvedPrincipal.getResolvedKerberosKeytab().getGroupAccess();
boolean groupWritable = "w".equalsIgnoreCase(groupAccess) || "rw".equalsIgnoreCase(groupAccess);
boolean groupReadable = "r".equalsIgnoreCase(groupAccess) || "rw".equalsIgnoreCase(groupAccess);
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
index ff5f5ce..2c9aa8c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
@@ -18,11 +18,10 @@
package org.apache.ambari.server.serveraction.kerberos;
-import static org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReader.DATA_FILE_NAME;
-
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -36,6 +35,9 @@ import org.apache.ambari.server.orm.dao.HostDAO;
import org.apache.ambari.server.orm.entities.HostEntity;
import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.serveraction.AbstractServerAction;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.KerberosKeytabController;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.utils.StageUtils;
@@ -178,6 +180,10 @@ public abstract class KerberosServerAction extends AbstractServerAction {
@Inject
HostDAO hostDAO;
+
+ @Inject
+ KerberosKeytabController kerberosKeytabController;
+
/**
* Given a (command parameter) Map and a property name, attempts to safely retrieve the requested
* data.
@@ -235,10 +241,9 @@ public abstract class KerberosServerAction extends AbstractServerAction {
*/
protected static OperationType getOperationType(Map<String, String> commandParameters) {
String value = getCommandParameterValue(commandParameters, OPERATION_TYPE);
- if(StringUtils.isEmpty(value)) {
+ if (StringUtils.isEmpty(value)) {
return OperationType.DEFAULT;
- }
- else {
+ } else {
return OperationType.valueOf(value.toUpperCase());
}
}
@@ -365,14 +370,32 @@ public abstract class KerberosServerAction extends AbstractServerAction {
}
/**
+ * Returns preconfigure type passed to current action.
+ *
+ * @return PreconfigureServiceType
+ */
+ protected PreconfigureServiceType getCommandPreconfigureType() {
+ String preconfigureServices = getCommandParameterValue(getCommandParameters(), PRECONFIGURE_SERVICES);
+ PreconfigureServiceType type = null;
+ if (!StringUtils.isEmpty(preconfigureServices)) {
+ try {
+ type = PreconfigureServiceType.valueOf(preconfigureServices.toUpperCase());
+ } catch (Throwable t) {
+ LOG.warn("Invalid preconfigure_services value, assuming DEFAULT: {}", preconfigureServices);
+ type = PreconfigureServiceType.DEFAULT;
+ }
+ }
+ return type;
+ }
+
+ /**
* Iterates through the Kerberos identity metadata from the
* {@link org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReader} and calls
* the implementing class to handle each identity found.
* <p/>
- * Using the "data_directory" value from this action's command parameters map, creates a
- * {@link KerberosIdentityDataFileReader} to parse
- * the relative identity.dat file and iterate through its "records". Each "record" is process using
- * {@link #processRecord(Map, String, KerberosOperationHandler, Map, Map)}.
+ * Using {@link #getHostFilter()}, {@link #getIdentityFilter()} and {@link #getServiceComponentFilter()} it retrieve
+ * list of filtered keytabs and their principals and process each principal using
+ * {@link #processIdentity(ResolvedKerberosPrincipal, KerberosOperationHandler, Map, Map)}.
*
* @param requestSharedDataContext a Map to be used a shared data among all ServerActions related
* to a given request
@@ -390,102 +413,43 @@ public abstract class KerberosServerAction extends AbstractServerAction {
if (commandParameters != null) {
// Grab the relevant data from this action's command parameters map
PrincipalKeyCredential administratorCredential = kerberosHelper.getKDCAdministratorCredentials(getClusterName());
- String defaultRealm = getDefaultRealm(commandParameters);
KDCType kdcType = getKDCType(commandParameters);
- String dataDirectoryPath = getDataDirectoryPath(commandParameters);
-
- if (dataDirectoryPath != null) {
- File dataDirectory = new File(dataDirectoryPath);
-
- // If the data directory exists, attempt to process further, else assume there is no work to do
- if (dataDirectory.exists()) {
- if (!dataDirectory.isDirectory() || !dataDirectory.canRead()) {
- String message = String.format("Failed to process the identities, the data directory is not accessible: %s",
- dataDirectory.getAbsolutePath());
- actionLog.writeStdErr(message);
- LOG.error(message);
- throw new AmbariException(message);
- }
- // The "identity data" file may or may not exist in the data directory, depending on if
- // there is work to do or not.
- File identityDataFile = new File(dataDirectory, DATA_FILE_NAME);
-
- if (identityDataFile.exists()) {
- if (!identityDataFile.canRead()) {
- String message = String.format("Failed to process the identities, cannot read the index file: %s",
- identityDataFile.getAbsolutePath());
- actionLog.writeStdErr(message);
- LOG.error(message);
- throw new AmbariException(message);
- }
-
- KerberosOperationHandler handler = kerberosOperationHandlerFactory.getKerberosOperationHandler(kdcType);
- if (handler == null) {
- String message = String.format("Failed to process the identities, a KDC operation handler was not found for the KDC type of : %s",
- kdcType.toString());
- actionLog.writeStdErr(message);
- LOG.error(message);
- throw new AmbariException(message);
- }
-
- Map<String, String> kerberosConfiguration = getConfiguration("kerberos-env");
+ String defaultRealm = getDefaultRealm(commandParameters);
- try {
- handler.open(administratorCredential, defaultRealm, kerberosConfiguration);
- } catch (KerberosOperationException e) {
- String message = String.format("Failed to process the identities, could not properly open the KDC operation handler: %s",
- e.getMessage());
- actionLog.writeStdErr(message);
- LOG.error(message);
- throw new AmbariException(message, e);
- }
+ KerberosOperationHandler handler = kerberosOperationHandlerFactory.getKerberosOperationHandler(kdcType);
+ Map<String, String> kerberosConfiguration = getConfiguration("kerberos-env");
+
+ try {
+ handler.open(administratorCredential, defaultRealm, kerberosConfiguration);
+ } catch (KerberosOperationException e) {
+ String message = String.format("Failed to process the identities, could not properly open the KDC operation handler: %s",
+ e.getMessage());
+ actionLog.writeStdErr(message);
+ LOG.error(message);
+ throw new AmbariException(message, e);
+ }
- // Create the data file reader to parse and iterate through the records
- KerberosIdentityDataFileReader reader = null;
- try {
- reader = kerberosIdentityDataFileReaderFactory.createKerberosIdentityDataFileReader(identityDataFile);
- for (Map<String, String> record : reader) {
- // Process the current record
- commandReport = processRecord(record, defaultRealm, handler, kerberosConfiguration, requestSharedDataContext);
-
- // If the principal processor returns a CommandReport, than it is time to stop since
- // an error condition has probably occurred, else all is assumed to be well.
- if (commandReport != null) {
- break;
- }
- }
- } catch (AmbariException e) {
- // Catch this separately from IOException since the reason it was thrown was not the same
- // Note: AmbariException is an IOException, so there may be some confusion
- throw new AmbariException(e.getMessage(), e);
- } catch (IOException e) {
- String message = String.format("Failed to process the identities, cannot read the index file: %s",
- identityDataFile.getAbsolutePath());
- actionLog.writeStdErr(message);
- LOG.error(message, e);
- throw new AmbariException(message, e);
- } finally {
- if (reader != null) {
- // The reader needs to be closed, if it fails to close ignore the exception since
- // there is little we can or care to do about it now.
- try {
- reader.close();
- } catch (IOException e) {
- // Ignore this...
- }
- }
-
- // The KerberosOperationHandler needs to be closed, if it fails to close ignore the
- // exception since there is little we can or care to do about it now.
- try {
- handler.close();
- } catch (KerberosOperationException e) {
- // Ignore this...
- }
+ try {
+ for (ResolvedKerberosKeytab rkk : kerberosKeytabController.getFilteredKeytabs((Map<String, Collection<String>>) getServiceComponentFilter(), getHostFilter(), getIdentityFilter())) {
+ for (ResolvedKerberosPrincipal principal : rkk.getPrincipals()) {
+ commandReport = processIdentity(principal, handler, kerberosConfiguration, requestSharedDataContext);
+ // If the principal processor returns a CommandReport, than it is time to stop since
+ // an error condition has probably occurred, else all is assumed to be well.
+ if (commandReport != null) {
+ break;
}
}
}
+ } finally {
+ // The KerberosOperationHandler needs to be closed, if it fails to close ignore the
+ // exception since there is little we can or care to do about it now.
+ try {
+ handler.close();
+ } catch (KerberosOperationException e) {
+ // Ignore this...
+ }
}
+
}
actionLog.writeStdOut("Processing identities completed.");
@@ -502,11 +466,10 @@ public abstract class KerberosServerAction extends AbstractServerAction {
* Processes an identity as necessary.
* <p/>
* This method is called from {@link #processIdentities(Map)} for each
- * identity "record" found in the Kerberos identity metadata file. After processing, it is expected
+ * principal found by specified filter. After processing, it is expected
* that the return value is null on success and a CommandReport (indicating the error) on failure.
*
- * @param identityRecord a Map containing the data for the current identity record
- * @param evaluatedPrincipal a String indicating the relevant principal
+ * @param resolvedPrincipal a ResolvedKerberosPrincipal object to process
* @param operationHandler a KerberosOperationHandler used to perform Kerberos-related
* tasks for specific Kerberos implementations
* (MIT, Active Directory, etc...)
@@ -516,48 +479,12 @@ public abstract class KerberosServerAction extends AbstractServerAction {
* condition; or null, indicating a success condition
* @throws AmbariException if an error occurs while processing the identity record
*/
- protected abstract CommandReport processIdentity(Map<String, String> identityRecord,
- String evaluatedPrincipal,
+ protected abstract CommandReport processIdentity(ResolvedKerberosPrincipal resolvedPrincipal,
KerberosOperationHandler operationHandler,
Map<String, String> kerberosConfiguration,
Map<String, Object> requestSharedDataContext)
throws AmbariException;
- /**
- * Process and prepares an identity record to be handled by the implementing class.
- * <p/>
- * Given the data from the record Map, attempts to replace variables in the principal pattern to
- * generate a concrete principal value to further process. This "evaluated principal" is then passed to
- * {@link #processIdentity(Map, String, KerberosOperationHandler, Map, Map)}
- * to be handled as needed.
- *
- * @param record a Map containing the data for the current identity record
- * @param defaultRealm a String declaring the default Kerberos realm
- * @param operationHandler a KerberosOperationHandler used to perform Kerberos-related
- * tasks for specific Kerberos implementations
- * (MIT, Active Directory, etc...)
- * @param kerberosConfiguration a Map of configuration properties from kerberos-env
- * @param requestSharedDataContext a Map to be used a shared data among all ServerActions related
- * to a given request @return a CommandReport, indicating an error
- * condition; or null, indicating a success condition
- * @throws AmbariException if an error occurs while processing the identity record
- */
- private CommandReport processRecord(Map<String, String> record, String defaultRealm,
- KerberosOperationHandler operationHandler,
- Map<String, String> kerberosConfiguration, Map<String, Object> requestSharedDataContext)
- throws AmbariException {
- CommandReport commandReport = null;
-
- if (record != null) {
- String principal = record.get(KerberosIdentityDataFileReader.PRINCIPAL);
- if (principal != null) {
- commandReport = processIdentity(record, principal, operationHandler, kerberosConfiguration, requestSharedDataContext);
- }
- }
-
- return commandReport;
- }
-
protected void deleteDataDirectory(String dataDirectoryPath) {
// Make sure this is a relevant directory. We don't want to accidentally allow _ANY_ directory
// to be deleted.
@@ -600,7 +527,32 @@ public abstract class KerberosServerAction extends AbstractServerAction {
return hostFilers != null && hostFilers.size() > 0;
}
- protected Long ambariServerHostID(){
+
+ protected Map<String, ? extends Collection<String>> getServiceComponentFilter() {
+ String serializedValue = getCommandParameterValue(SERVICE_COMPONENT_FILTER);
+
+ if (serializedValue != null) {
+ Type type = new TypeToken<Map<String, ? extends Collection<String>>>() {
+ }.getType();
+ return StageUtils.getGson().fromJson(serializedValue, type);
+ } else {
+ return null;
+ }
+ }
+
+ protected Collection<String> getIdentityFilter() {
+ String serializedValue = getCommandParameterValue(IDENTITY_FILTER);
+
+ if (serializedValue != null) {
+ Type type = new TypeToken<Collection<String>>() {
+ }.getType();
+ return StageUtils.getGson().fromJson(serializedValue, type);
+ } else {
+ return null;
+ }
+ }
+
+ protected Long ambariServerHostID() {
String ambariServerHostName = StageUtils.getHostName();
HostEntity ambariServerHostEntity = hostDAO.findByName(ambariServerHostName);
return (ambariServerHostEntity == null)
@@ -608,6 +560,65 @@ public abstract class KerberosServerAction extends AbstractServerAction {
: ambariServerHostEntity.getHostId();
}
+
+ public static class KerberosCommandParameters {
+ private Map<String, String> params;
+
+ public KerberosCommandParameters(ExecutionCommand ec) {
+ params = ec.getCommandParams();
+ }
+
+ public KerberosCommandParameters(AbstractServerAction serverAction) {
+ this(serverAction.getExecutionCommand());
+ }
+
+ public Set<String> getHostFilter() {
+ String serializedValue = getCommandParameterValue(HOST_FILTER);
+
+ if (serializedValue != null) {
+ Type type = new TypeToken<Set<String>>() {
+ }.getType();
+ return StageUtils.getGson().fromJson(serializedValue, type);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean hasHostFilters() {
+ Set<String> hostFilers = getHostFilter();
+ return hostFilers != null && hostFilers.size() > 0;
+ }
+
+ public Map<String, ? extends Collection<String>> getServiceComponentFilter() {
+ String serializedValue = getCommandParameterValue(SERVICE_COMPONENT_FILTER);
+
+ if (serializedValue != null) {
+ Type type = new TypeToken<Map<String, ? extends Collection<String>>>() {
+ }.getType();
+ return StageUtils.getGson().fromJson(serializedValue, type);
+ } else {
+ return null;
+ }
+ }
+
+ public Collection<String> getIdentityFilter() {
+ String serializedValue = getCommandParameterValue(IDENTITY_FILTER);
+
+ if (serializedValue != null) {
+ Type type = new TypeToken<Collection<String>>() {
+ }.getType();
+ return StageUtils.getGson().fromJson(serializedValue, type);
+ } else {
+ return null;
+ }
+ }
+
+ public String getCommandParameterValue(String propertyName) {
+ Map<String, String> commandParameters = params;
+ return (commandParameters == null) ? null : commandParameters.get(propertyName);
+ }
+ }
+
/**
* A Kerberos operation type
* <ul>
@@ -623,7 +634,7 @@ public abstract class KerberosServerAction extends AbstractServerAction {
RECREATE_ALL,
/**
- * Generate keytabs for only those that are missing
+ * Generate keytabs for only those that are missing
*/
CREATE_MISSING,
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
index 671ad95..2d29bdc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
@@ -29,11 +29,11 @@ import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.ServiceComponentHost;
import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
-import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,17 +70,7 @@ public class PrepareEnableKerberosServerAction extends PrepareKerberosIdentities
Map<String, String> commandParameters = getCommandParameters();
- String preconfigureServices = getCommandParameterValue(commandParameters, PRECONFIGURE_SERVICES);
- PreconfigureServiceType type = null;
- if (!StringUtils.isEmpty(preconfigureServices)) {
- try {
- type = PreconfigureServiceType.valueOf(preconfigureServices.toUpperCase());
- } catch (Throwable t) {
- LOG.warn("Invalid preconfigure_services value, assuming DEFAULT: {}", preconfigureServices);
- type = PreconfigureServiceType.DEFAULT;
- }
- }
-
+ PreconfigureServiceType type = getCommandPreconfigureType();
KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster, type != PreconfigureServiceType.NONE);
if (type == PreconfigureServiceType.ALL) {
// Force all services to be flagged for pre-configuration...
@@ -144,7 +134,7 @@ public class PrepareEnableKerberosServerAction extends PrepareKerberosIdentities
}
@Override
- protected CommandReport processIdentity(Map<String, String> identityRecord, String evaluatedPrincipal, KerberosOperationHandler operationHandler, Map<String, String> kerberosConfiguration, Map<String, Object> requestSharedDataContext) throws AmbariException {
+ protected CommandReport processIdentity(ResolvedKerberosPrincipal resolvedPrincipal, KerberosOperationHandler operationHandler, Map<String, String> kerberosConfiguration, Map<String, Object> requestSharedDataContext) throws AmbariException {
throw new UnsupportedOperationException();
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
index 83a2106..c7f2003 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
@@ -140,15 +140,6 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
}
- @Override
- protected CommandReport processIdentity(Map<String, String> identityRecord, String evaluatedPrincipal,
- KerberosOperationHandler operationHandler,
- Map<String, String> kerberosConfiguration,
- Map<String, Object> requestSharedDataContext)
- throws AmbariException {
- throw new UnsupportedOperationException();
- }
-
/**
* Calls {@link KerberosHelper#getKerberosDescriptor(Cluster, boolean)}
*
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java
new file mode 100644
index 0000000..4993902
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.serveraction.kerberos.stageutils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
+import org.apache.ambari.server.orm.dao.KerberosKeytabPrincipalDAO;
+import org.apache.ambari.server.orm.entities.KerberosKeytabEntity;
+import org.apache.ambari.server.orm.entities.KerberosKeytabPrincipalEntity;
+import org.apache.ambari.server.orm.entities.KerberosPrincipalEntity;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * Helper class to construct convenient wrappers around database entities related to kerberos.
+ */
+@Singleton
+public class KerberosKeytabController {
+ @Inject
+ private KerberosKeytabDAO kerberosKeytabDAO;
+
+ @Inject
+ private KerberosKeytabPrincipalDAO kerberosKeytabPrincipalDAO;
+
+ /**
+ * Tries to find keytab by keytab path in destination filesystem.
+ *
+ * @param file keytab path
+ * @return found keytab or null
+ */
+ public ResolvedKerberosKeytab getKeytabByFile(String file) {
+ return getKeytabByFile(file, true);
+ }
+
+ /**
+ * Tries to find keytab by keytab path in destination filesystem.
+ *
+ * @param file keytab path
+ * @param resolvePrincipals include resolved principals
+ * @return found keytab or null
+ */
+ public ResolvedKerberosKeytab getKeytabByFile(String file, boolean resolvePrincipals) {
+ return fromKeytabEntity(kerberosKeytabDAO.find(file), resolvePrincipals);
+ }
+
+ /**
+ * Returns all keytabs managed by ambari.
+ *
+ * @return all keytabs
+ */
+ public Set<ResolvedKerberosKeytab> getAllKeytabs() {
+ return fromKeytabEntities(kerberosKeytabDAO.findAll());
+ }
+
+ /**
+ * Returns all keytabs that contains given principal.
+ *
+ * @param rkp principal to filter keytabs by
+ * @return set of keytabs found
+ */
+ public Set<ResolvedKerberosKeytab> getFromPrincipal(ResolvedKerberosPrincipal rkp) {
+ return fromKeytabEntities(kerberosKeytabDAO.findByPrincipalAndHost(rkp.getPrincipal(), rkp.getHostId()));
+ }
+
+ /**
+ * Returns keytabs with principals filtered by host, principal name or service(and component) names.
+ *
+ * @param serviceComponentFilter service-component filter
+ * @param hostFilter host filter
+ * @param identityFilter identity(principal) filter
+ * @return set of keytabs found
+ */
+ public Set<ResolvedKerberosKeytab> getFilteredKeytabs(Map<String, Collection<String>> serviceComponentFilter,
+ Set<String> hostFilter, Collection<String> identityFilter) {
+ if (serviceComponentFilter == null && hostFilter == null && identityFilter == null) {
+ return getAllKeytabs();
+ }
+ List<KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter> filters = splitServiceFilter(serviceComponentFilter);
+ for (KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter filter : filters) {
+ filter.setHostNames(hostFilter);
+ filter.setPrincipals(identityFilter);
+ }
+
+ Set<ResolvedKerberosPrincipal> filteredPrincipals = fromPrincipalEntities(kerberosKeytabPrincipalDAO.findByFilters(filters));
+ HashMap<String, ResolvedKerberosKeytab> resultMap = new HashMap<>();
+ for (ResolvedKerberosPrincipal principal : filteredPrincipals) {
+ if (!resultMap.containsKey(principal.getKeytabPath())) {
+ resultMap.put(principal.getKeytabPath(), getKeytabByFile(principal.getKeytabPath(), false));
+ }
+ ResolvedKerberosKeytab keytab = resultMap.get(principal.getKeytabPath());
+ keytab.addPrincipal(principal);
+ }
+ return Sets.newHashSet(resultMap.values());
+ }
+
+ /**
+ * This function split serviceComponentFilter to two filters, one with specific components, and another one with service
+ * only. Can return only one filter if filter contain only one type of mapping(whole service or component based)
+ * or empty filter if no serviceComponentFilter provided.
+ *
+ * @param serviceComponentFilter
+ * @return
+ */
+ private List<KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter> splitServiceFilter(Map<String, Collection<String>> serviceComponentFilter) {
+ if (serviceComponentFilter != null && serviceComponentFilter.size() > 0) {
+ Set<String> serviceSet = new HashSet<>();
+ Set<String> componentSet = new HashSet<>();
+ Set<String> serviceOnlySet = new HashSet<>();
+ serviceSet.addAll(serviceComponentFilter.keySet());
+ for (String serviceName : serviceSet) {
+ Collection<String> serviceComponents = serviceComponentFilter.get(serviceName);
+ if (serviceComponents.contains("*")) { // star means that this is filtered by whole SERVICE
+ serviceOnlySet.add(serviceName);
+ serviceSet.remove(serviceName); // remove service from regular
+ } else {
+ componentSet.addAll(serviceComponents);
+ }
+ }
+ List<KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter> result = new ArrayList<>();
+ if (serviceSet.size() > 0) {
+ result.add(new KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter(
+ null,
+ serviceSet,
+ componentSet,
+ null
+ ));
+ }
+ if (serviceOnlySet.size() > 0) {
+ result.add(new KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter(
+ null,
+ serviceOnlySet,
+ null,
+ null
+ ));
+ }
+ if (result.size() > 0) {
+ return result;
+ }
+ }
+
+ return Lists.newArrayList(new KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter(null,null,null,null));
+ }
+
+ private ResolvedKerberosKeytab fromKeytabEntity(KerberosKeytabEntity kke, boolean resolvePrincipals) {
+ Set<ResolvedKerberosPrincipal> principals = resolvePrincipals ? fromPrincipalEntities(kke.getKerberosKeytabPrincipalEntities()) : new HashSet<>();
+ return new ResolvedKerberosKeytab(
+ kke.getKeytabPath(),
+ kke.getOwnerName(),
+ kke.getOwnerAccess(),
+ kke.getGroupName(),
+ kke.getGroupAccess(),
+ principals,
+ kke.isAmbariServerKeytab(),
+ kke.isWriteAmbariJaasFile()
+ );
+ }
+
+ private ResolvedKerberosKeytab fromKeytabEntity(KerberosKeytabEntity kke) {
+ return fromKeytabEntity(kke, true);
+ }
+
+ private Set<ResolvedKerberosKeytab> fromKeytabEntities(Collection<KerberosKeytabEntity> keytabEntities) {
+ ImmutableSet.Builder<ResolvedKerberosKeytab> builder = ImmutableSet.builder();
+ for (KerberosKeytabEntity kkpe : keytabEntities) {
+ builder.add(fromKeytabEntity(kkpe));
+ }
+ return builder.build();
+ }
+
+ private Set<ResolvedKerberosPrincipal> fromPrincipalEntities(Collection<KerberosKeytabPrincipalEntity> principalEntities) {
+ ImmutableSet.Builder<ResolvedKerberosPrincipal> builder = ImmutableSet.builder();
+ for (KerberosKeytabPrincipalEntity kkpe : principalEntities) {
+ KerberosPrincipalEntity kpe = kkpe.getPrincipalEntity();
+ ResolvedKerberosPrincipal rkp = new ResolvedKerberosPrincipal(
+ kkpe.getHostId(),
+ kkpe.getHostName(),
+ kkpe.getPrincipalName(),
+ kpe.isService(),
+ kpe.getCachedKeytabPath(),
+ kkpe.getKeytabPath(),
+ kkpe.getServiceMappingAsMultimap());
+ builder.add(rkp);
+ }
+ return builder.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java
index 17e484a..3233915 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosKeytab.java
@@ -18,21 +18,17 @@
package org.apache.ambari.server.serveraction.kerberos.stageutils;
-import java.util.Map;
+import java.util.HashSet;
import java.util.Set;
import org.apache.ambari.server.state.kerberos.VariableReplacementHelper;
-import org.apache.commons.lang3.tuple.Pair;
-
-import com.google.common.collect.ImmutableSet;
/**
* Class that represents keytab. Contains principals that mapped to host.
- * Same keytab can have different set of principals on different hosts.
+ * Same keytab can have different set of principals on different hosts for different services.
+ * Each principal identified by host and keytab it belongs to and contain mapping that shows in which services and
+ * components given principal used.
*/
-// TODO This class need to replace {@link org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFile}
-// TODO and all related structures and become main item that {@link org.apache.ambari.server.serveraction.kerberos.KerberosServerAction}
-// TODO operates with instead of identity records.
public class ResolvedKerberosKeytab {
private String ownerName = null;
@@ -40,43 +36,36 @@ public class ResolvedKerberosKeytab {
private String groupName = null;
private String groupAccess = null;
private String file = null;
- private Set<Pair<Long, Pair<String, String>>> mappedPrincipals = null;
+ private Set<ResolvedKerberosPrincipal> principals = new HashSet<>();
private boolean isAmbariServerKeytab = false;
private boolean mustWriteAmbariJaasFile = false;
public ResolvedKerberosKeytab(
- String file,
- String ownerName,
- String ownerAccess,
- String groupName,
- String groupAccess,
- Set<Pair<Long, Pair<String, String>>> mappedPrincipals,
- boolean isAmbariServerKeytab,
- boolean writeAmbariJaasFile
+ String file,
+ String ownerName,
+ String ownerAccess,
+ String groupName,
+ String groupAccess,
+ Set<ResolvedKerberosPrincipal> principals,
+ boolean isAmbariServerKeytab,
+ boolean writeAmbariJaasFile
) {
this.ownerName = ownerName;
this.ownerAccess = ownerAccess;
this.groupName = groupName;
this.groupAccess = groupAccess;
this.file = file;
- this.mappedPrincipals = mappedPrincipals;
+ setPrincipals(principals);
this.isAmbariServerKeytab = isAmbariServerKeytab;
this.mustWriteAmbariJaasFile = writeAmbariJaasFile;
+
}
/**
* Gets the path to the keytab file
- * <p/>
- * The value may include variable placeholders to be replaced as needed
- * <ul>
- * <li>
- * ${variable} placeholders are replaced on the server - see
- * {@link VariableReplacementHelper#replaceVariables(String, Map)}
- * </li>
- * </ul>
*
* @return a String declaring the keytab file's absolute path
- * @see VariableReplacementHelper#replaceVariables(String, Map)
+ * @see VariableReplacementHelper#replaceVariables(String, java.util.Map)
*/
public String getFile() {
return file;
@@ -175,47 +164,36 @@ public class ResolvedKerberosKeytab {
/**
* Gets evaluated host-to-principal set associated with given keytab.
*
- * @return a Set with mappedPrincipals associated with given keytab
+ * @return a Set with principals associated with given keytab
*/
- public Set<Pair<Long, Pair<String, String>>> getMappedPrincipals() {
- return mappedPrincipals;
+ public Set<ResolvedKerberosPrincipal> getPrincipals() {
+ return principals;
}
/**
* Sets evaluated host-to-principal set associated with given keytab.
*
- * @param mappedPrincipals a Map with host-to-principal mapping associated with given keytab
- */
- public void setMappedPrincipals(Set<Pair<Long, Pair<String, String>>> mappedPrincipals) {
- this.mappedPrincipals = mappedPrincipals;
- }
-
- /**
- * Gets set of hosts associated with given keytab.
- *
- * @return a Set with hosts
+ * @param principals set of principals to add
*/
- public Set<Long> getHosts() {
- ImmutableSet.Builder<Long> builder = ImmutableSet.builder();
- for (Pair<Long, Pair<String, String>> principal : getMappedPrincipals()) {
- if (principal.getLeft() != null) {
- builder.add(principal.getLeft());
+ public void setPrincipals(Set<ResolvedKerberosPrincipal> principals) {
+ this.principals = principals;
+ if (principals != null) {
+ for (ResolvedKerberosPrincipal principal : this.principals) {
+ principal.setResolvedKerberosKeytab(this);
}
}
- return builder.build();
}
/**
- * Gets a set of principals associated with given keytab.
+ * Add principal to keytab.
*
- * @return a Set of principals
+ * @param principal resolved principal to add
*/
- public Set<Pair<String, String>> getPrincipals() {
- ImmutableSet.Builder<Pair<String, String>> builder = ImmutableSet.builder();
- for (Pair<Long, Pair<String, String>> principal : getMappedPrincipals()) {
- builder.add(principal.getRight());
+ public void addPrincipal(ResolvedKerberosPrincipal principal) {
+ if (!principals.contains(principal)) {
+ principal.setResolvedKerberosKeytab(this);
+ principals.add(principal);
}
- return builder.build();
}
/**
@@ -254,4 +232,37 @@ public class ResolvedKerberosKeytab {
public void setMustWriteAmbariJaasFile(boolean mustWriteAmbariJaasFile) {
this.mustWriteAmbariJaasFile = mustWriteAmbariJaasFile;
}
+
+ /**
+ * Merge principals from one keytab to given.
+ *
+ * @param otherKeytab keytab to merge principals from
+ */
+ public void mergePrincipals(ResolvedKerberosKeytab otherKeytab) {
+ for (ResolvedKerberosPrincipal rkp : otherKeytab.getPrincipals()) {
+ ResolvedKerberosPrincipal existent = findPrincipal(rkp.getHostId(), rkp.getPrincipal(), rkp.getKeytabPath());
+ if (existent != null) {
+ existent.mergeComponentMapping(rkp);
+ } else {
+ principals.add(rkp);
+ }
+ }
+ }
+
+ private ResolvedKerberosPrincipal findPrincipal(Long hostId, String principal, String keytabPath) {
+ for (ResolvedKerberosPrincipal rkp : principals) {
+ boolean hostIdIsSame;
+ if(hostId != null && rkp.getHostId() != null){
+ hostIdIsSame = hostId.equals(rkp.getHostId());
+ } else if(hostId == null && rkp.getHostId() == null) {
+ hostIdIsSame = true;
+ } else {
+ hostIdIsSame = false;
+ }
+ if (hostIdIsSame && principal.equals(rkp.getPrincipal())&& keytabPath.equals(rkp.getKeytabPath())) {
+ return rkp;
+ }
+ }
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/67fc4a37/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosPrincipal.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosPrincipal.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosPrincipal.java
new file mode 100644
index 0000000..100c1e2
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/ResolvedKerberosPrincipal.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.ambari.server.serveraction.kerberos.stageutils;
+
+import org.apache.ambari.server.utils.StageUtils;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * Class that represents principal and it info(host, keytab path, service and component mapping).
+ */
+public class ResolvedKerberosPrincipal {
+ private Long hostId;
+ private String hostName;
+ private String principal;
+ private boolean isService;
+ private String cacheFile;
+ private Multimap<String, String> serviceMapping = ArrayListMultimap.create();
+ private String keytabPath;
+ private ResolvedKerberosKeytab resolvedKerberosKeytab;
+
+ public ResolvedKerberosPrincipal(Long hostId, String hostName, String principal, boolean isService, String cacheFile, String serviceName, String componentName, String keytabPath) {
+ this.hostId = hostId;
+ this.hostName = hostName;
+ this.principal = principal;
+ this.isService = isService;
+ this.cacheFile = cacheFile;
+ this.keytabPath = keytabPath;
+ addComponentMapping(serviceName, componentName);
+ }
+
+ public ResolvedKerberosPrincipal(Long hostId, String hostName, String principal, boolean isService, String cacheFile, String keytabPath) {
+ this.hostId = hostId;
+ this.hostName = hostName;
+ this.principal = principal;
+ this.isService = isService;
+ this.cacheFile = cacheFile;
+ this.keytabPath = keytabPath;
+ }
+
+ public ResolvedKerberosPrincipal(Long hostId, String hostName, String principal, boolean isService, String cacheFile, String keytabPath, Multimap<String, String> serviceMapping) {
+ this.hostId = hostId;
+ this.hostName = hostName;
+ this.principal = principal;
+ this.isService = isService;
+ this.cacheFile = cacheFile;
+ this.keytabPath = keytabPath;
+ this.serviceMapping = serviceMapping;
+ }
+
+ public void addComponentMapping(String serviceName, String componentName) {
+ if (serviceName == null){
+ serviceName = "";
+ }
+ if (componentName == null) {
+ componentName = "*";
+ }
+ serviceMapping.get(serviceName).add(componentName);
+ }
+
+ public void mergeComponentMapping(ResolvedKerberosPrincipal other) {
+ serviceMapping.putAll(other.getServiceMapping());
+ }
+
+ public String getKeytabPath() {
+ return keytabPath;
+ }
+
+ public void setKeytabPath(String keytabPath) {
+ this.keytabPath = keytabPath;
+ }
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public void setHostId(Long hostId) {
+ this.hostId = hostId;
+ }
+
+ public String getHostName() {
+ if (hostName == null) {
+ return StageUtils.getHostName();
+ }
+ return hostName;
+ }
+
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
+ }
+
+ public String getPrincipal() {
+ return principal;
+ }
+
+ public void setPrincipal(String principal) {
+ this.principal = principal;
+ }
+
+ public boolean isService() {
+ return isService;
+ }
+
+ public void setService(boolean service) {
+ isService = service;
+ }
+
+ public String getCacheFile() {
+ return cacheFile;
+ }
+
+ public void setCacheFile(String cacheFile) {
+ this.cacheFile = cacheFile;
+ }
+
+ public Multimap<String, String> getServiceMapping() {
+ return serviceMapping;
+ }
+
+ public void setServiceMapping(Multimap<String, String> serviceMapping) {
+ this.serviceMapping = serviceMapping;
+ }
+
+ public ResolvedKerberosKeytab getResolvedKerberosKeytab() {
+ return resolvedKerberosKeytab;
+ }
+
+ public void setResolvedKerberosKeytab(ResolvedKerberosKeytab resolvedKerberosKeytab) {
+ this.resolvedKerberosKeytab = resolvedKerberosKeytab;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ResolvedKerberosPrincipal principal1 = (ResolvedKerberosPrincipal) o;
+ return isService == principal1.isService &&
+ Objects.equal(hostId, principal1.hostId) &&
+ Objects.equal(hostName, principal1.hostName) &&
+ Objects.equal(principal, principal1.principal) &&
+ Objects.equal(cacheFile, principal1.cacheFile) &&
+ Objects.equal(serviceMapping, principal1.serviceMapping) &&
+ Objects.equal(keytabPath, principal1.keytabPath);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(hostId, hostName, principal, isService, cacheFile, serviceMapping, keytabPath);
+ }
+}