You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ec...@apache.org on 2017/11/01 15:59:32 UTC
[2/2] ambari git commit: AMBARI-22278. Improve Kerberos principal and
keytab accounting (echekanskiy)
AMBARI-22278. Improve Kerberos principal and keytab accounting (echekanskiy)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d03c24b9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d03c24b9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d03c24b9
Branch: refs/heads/trunk
Commit: d03c24b9f21cd91af78e0bfca2a1ce1e0de51bdf
Parents: 8a8d48f
Author: Eugene Chekanskiy <ec...@hortonworks.com>
Authored: Thu Oct 12 13:22:15 2017 +0300
Committer: Eugene Chekanskiy <ec...@hortonworks.com>
Committed: Wed Nov 1 17:52:04 2017 +0200
----------------------------------------------------------------------
.../ambari/server/agent/HeartbeatProcessor.java | 72 ++++--
.../controller/DeleteIdentityHandler.java | 3 +-
.../server/controller/KerberosHelper.java | 21 +-
.../server/controller/KerberosHelperImpl.java | 138 +++++++++-
.../HostKerberosIdentityResourceProvider.java | 16 +-
.../ServiceComponentUninstalledEvent.java | 11 +-
.../server/orm/dao/KerberosKeytabDAO.java | 110 ++++++++
.../server/orm/dao/KerberosPrincipalDAO.java | 7 +
.../orm/dao/KerberosPrincipalHostDAO.java | 40 ++-
.../orm/entities/KerberosKeytabEntity.java | 86 +++++++
.../entities/KerberosPrincipalHostEntity.java | 57 +++-
.../entities/KerberosPrincipalHostEntityPK.java | 19 +-
.../AbstractPrepareKerberosServerAction.java | 29 ++-
.../kerberos/CleanupServerAction.java | 14 +-
.../server/serveraction/kerberos/Component.java | 13 +-
.../ConfigureAmbariIdentitiesServerAction.java | 31 ++-
.../kerberos/CreateKeytabFilesServerAction.java | 64 +++--
.../kerberos/CreatePrincipalsServerAction.java | 48 ++--
.../kerberos/KerberosIdentityDataFile.java | 2 -
.../KerberosIdentityDataFileWriter.java | 9 +-
.../kerberos/KerberosServerAction.java | 27 +-
.../PrepareDisableKerberosServerAction.java | 2 +-
.../PrepareEnableKerberosServerAction.java | 2 +-
.../PrepareKerberosIdentitiesServerAction.java | 3 +-
.../stageutils/ResolvedKerberosKeytab.java | 257 +++++++++++++++++++
.../upgrades/PreconfigureKerberosAction.java | 48 +++-
.../apache/ambari/server/state/ServiceImpl.java | 2 +-
.../svccomphost/ServiceComponentHostImpl.java | 2 +-
.../main/resources/Ambari-DDL-Derby-CREATE.sql | 15 +-
.../main/resources/Ambari-DDL-MySQL-CREATE.sql | 13 +-
.../main/resources/Ambari-DDL-Oracle-CREATE.sql | 13 +-
.../resources/Ambari-DDL-Postgres-CREATE.sql | 11 +-
.../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 13 +-
.../resources/Ambari-DDL-SQLServer-CREATE.sql | 13 +-
.../src/main/resources/META-INF/persistence.xml | 1 +
.../package/scripts/kerberos_common.py | 7 +-
.../package/scripts/kerberos_common.py | 7 +-
.../server/agent/TestHeartbeatHandler.java | 2 +-
.../server/controller/KerberosHelperTest.java | 6 +
...ostKerberosIdentityResourceProviderTest.java | 12 +-
.../utilities/KerberosIdentityCleanerTest.java | 10 +-
.../HostVersionOutOfSyncListenerTest.java | 2 +-
...AbstractPrepareKerberosServerActionTest.java | 11 +-
...nfigureAmbariIdentitiesServerActionTest.java | 11 +-
.../FinalizeKerberosServerActionTest.java | 5 +
.../kerberos/KerberosIdentityDataFileTest.java | 8 +-
.../kerberos/KerberosServerActionTest.java | 10 +-
.../PreconfigureKerberosActionTest.java | 10 +
48 files changed, 1097 insertions(+), 216 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
index 2690008..83d2c98 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
@@ -52,7 +52,9 @@ import org.apache.ambari.server.events.publishers.AlertEventPublisher;
import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
import org.apache.ambari.server.events.publishers.VersionEventPublisher;
import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
+import org.apache.ambari.server.orm.entities.KerberosPrincipalHostEntity;
import org.apache.ambari.server.state.Alert;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
@@ -88,7 +90,6 @@ import com.google.inject.Injector;
/**
* HeartbeatProcessor class is used for bulk processing data retrieved from agents in background
- *
*/
public class HeartbeatProcessor extends AbstractService{
private static final Logger LOG = LoggerFactory.getLogger(HeartbeatProcessor.class);
@@ -135,6 +136,9 @@ public class HeartbeatProcessor extends AbstractService{
KerberosPrincipalHostDAO kerberosPrincipalHostDAO;
@Inject
+ KerberosKeytabDAO kerberosKeytabDao;
+
+ @Inject
Gson gson;
@Inject
@@ -153,7 +157,7 @@ public class HeartbeatProcessor extends AbstractService{
@Override
protected void doStart() {
LOG.info("**** Starting heartbeats processing threads ****");
- for (int i=0; i< poolSize; i++) {
+ for (int i = 0; i < poolSize; i++) {
executor.scheduleAtFixedRate(new HeartbeatProcessingTask(), delay, period, TimeUnit.MILLISECONDS);
}
}
@@ -201,6 +205,7 @@ public class HeartbeatProcessor extends AbstractService{
/**
* Incapsulates logic for processing data from agent heartbeat
+ *
* @param heartbeat Agent heartbeat object
* @throws AmbariException
*/
@@ -217,14 +222,12 @@ public class HeartbeatProcessor extends AbstractService{
}
-
/**
* Extracts all of the {@link Alert}s from the heartbeat and fires
* {@link AlertEvent}s for each one. If there is a problem looking up the
* cluster, then alerts will not be processed.
*
- * @param heartbeat
- * the heartbeat to process.
+ * @param heartbeat the heartbeat to process.
*/
protected void processAlerts(HeartBeat heartbeat) {
if (heartbeat == null) {
@@ -247,6 +250,7 @@ public class HeartbeatProcessor extends AbstractService{
/**
* Update host status basing on components statuses
+ *
* @param heartbeat heartbeat to process
* @throws AmbariException
*/
@@ -349,8 +353,9 @@ public class HeartbeatProcessor extends AbstractService{
/**
* Process reports of tasks executed on agents
+ *
* @param heartbeat heartbeat to process
- * @param now cached current time
+ * @param now cached current time
* @throws AmbariException
*/
protected void processCommandReports(
@@ -424,8 +429,7 @@ public class HeartbeatProcessor extends AbstractService{
String customCommand = report.getCustomCommand();
- boolean adding = SET_KEYTAB.equalsIgnoreCase(customCommand);
- if (adding || REMOVE_KEYTAB.equalsIgnoreCase(customCommand)) {
+ if (SET_KEYTAB.equalsIgnoreCase(customCommand) || REMOVE_KEYTAB.equalsIgnoreCase(customCommand)) {
WriteKeytabsStructuredOut writeKeytabsStructuredOut;
try {
writeKeytabsStructuredOut = gson.fromJson(report.getStructuredOut(), WriteKeytabsStructuredOut.class);
@@ -435,25 +439,35 @@ public class HeartbeatProcessor extends AbstractService{
}
if (writeKeytabsStructuredOut != null) {
- Map<String, String> keytabs = writeKeytabsStructuredOut.getKeytabs();
- if (keytabs != null) {
- for (Map.Entry<String, String> entry : keytabs.entrySet()) {
- String principal = entry.getKey();
- if (!kerberosPrincipalHostDAO.exists(principal, host.getHostId())) {
- if (adding) {
- kerberosPrincipalHostDAO.create(principal, host.getHostId());
- } else if ("_REMOVED_".equalsIgnoreCase(entry.getValue())) {
- kerberosPrincipalHostDAO.remove(principal, host.getHostId());
- }
+ if (SET_KEYTAB.equalsIgnoreCase(customCommand)) {
+ Map<String, String> keytabs = writeKeytabsStructuredOut.getKeytabs();
+ if (keytabs != null) {
+ for (Map.Entry<String, String> entry : keytabs.entrySet()) {
+ String principal = entry.getKey();
+ String keytabPath = entry.getValue();
+ KerberosPrincipalHostEntity kphe = kerberosPrincipalHostDAO.find(principal, host.getHostId(), keytabPath);
+ kphe.setDistributed(true);
+ kerberosPrincipalHostDAO.merge(kphe);
+ }
+ }
+ } else if (REMOVE_KEYTAB.equalsIgnoreCase(customCommand)) {
+ Map<String, String> deletedKeytabs = writeKeytabsStructuredOut.getRemovedKeytabs();
+ if (deletedKeytabs != null) {
+ for (Map.Entry<String, String> entry : deletedKeytabs.entrySet()) {
+ String keytabPath = entry.getValue();
+ kerberosPrincipalHostDAO.removeByKeytabPath(keytabPath);
+ kerberosKeytabDao.remove(keytabPath);
}
}
}
}
} else if (CHECK_KEYTABS.equalsIgnoreCase(customCommand)) {
ListKeytabsStructuredOut structuredOut = gson.fromJson(report.getStructuredOut(), ListKeytabsStructuredOut.class);
- for (MissingKeytab each : structuredOut.missingKeytabs){
- LOG.info("Missing keytab: {} on host: {} principal: {}", each.keytabFilePath, hostname, each.principal);
- kerberosPrincipalHostDAO.remove(each.principal, host.getHostId());
+ for (MissingKeytab each : structuredOut.missingKeytabs) {
+ LOG.info("Missing principal: {} for keytab: {} on host: {}", each.principal, each.keytabFilePath, hostname);
+ KerberosPrincipalHostEntity kphe = kerberosPrincipalHostDAO.find(each.principal, host.getHostId(), each.keytabFilePath);
+ kphe.setDistributed(false);
+ kerberosPrincipalHostDAO.merge(kphe);
}
}
}
@@ -517,7 +531,7 @@ public class HeartbeatProcessor extends AbstractService{
// Necessary for resetting clients stale configs after starting service
if ((RoleCommand.INSTALL.toString().equals(report.getRoleCommand()) ||
(RoleCommand.CUSTOM_COMMAND.toString().equals(report.getRoleCommand()) &&
- "INSTALL".equals(report.getCustomCommand()))) && svcComp.isClientComponent()){
+ "INSTALL".equals(report.getCustomCommand()))) && svcComp.isClientComponent()) {
scHost.updateActualConfigs(report.getConfigurationTags());
scHost.setRestartRequired(false);
}
@@ -588,6 +602,7 @@ public class HeartbeatProcessor extends AbstractService{
/**
* Process reports of status commands
+ *
* @param heartbeat heartbeat to process
* @throws AmbariException
*/
@@ -701,7 +716,10 @@ public class HeartbeatProcessor extends AbstractService{
*/
private static class WriteKeytabsStructuredOut {
@SerializedName("keytabs")
- private Map<String,String> keytabs;
+ private Map<String, String> keytabs;
+
+ @SerializedName("removedKeytabs")
+ private Map<String, String> removedKeytabs;
public Map<String, String> getKeytabs() {
return keytabs;
@@ -710,6 +728,14 @@ public class HeartbeatProcessor extends AbstractService{
public void setKeytabs(Map<String, String> keytabs) {
this.keytabs = keytabs;
}
+
+ public Map<String, String> getRemovedKeytabs() {
+ return removedKeytabs;
+ }
+
+ public void setRemovedKeytabs(Map<String, String> removedKeytabs) {
+ this.removedKeytabs = removedKeytabs;
+ }
}
private static class ListKeytabsStructuredOut {
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
index 29f8e2a..a7b9d80 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
@@ -227,8 +227,7 @@ class DeleteIdentityHandler {
calculateConfig(kerberosDescriptor, serviceNames()),
new HashMap<>(),
false,
- new HashMap<>(),
- false);
+ new HashMap<>());
return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
index b8e1be1..749943d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
@@ -33,6 +33,7 @@ import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileWr
import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
import org.apache.ambari.server.serveraction.kerberos.KerberosMissingAdminCredentialsException;
import org.apache.ambari.server.serveraction.kerberos.KerberosOperationException;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.SecurityType;
import org.apache.ambari.server.state.ServiceComponentHost;
@@ -588,15 +589,15 @@ public interface KerberosHelper {
* values
* @param configurations a Map of configurations to use a replacements for variables
* in identity fields
- * @param ignoreHeadless boolean value to specify if headless principals must not be processed
* @return an integer indicating the number of identities added to the data file
* @throws java.io.IOException if an error occurs while writing a record to the data file
*/
int addIdentities(KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter,
Collection<KerberosIdentityDescriptor> identities,
- Collection<String> identityFilter, String hostname, String serviceName,
+ Collection<String> identityFilter, String hostname, Long hostId, String serviceName,
String componentName, Map<String, Map<String, String>> kerberosConfigurations,
- Map<String, Map<String, String>> configurations, boolean ignoreHeadless)
+ Map<String, Map<String, String>> configurations,
+ Map<String, ResolvedKerberosKeytab> resolvedKeytabs, String realm)
throws IOException;
/**
* Calculates the map of configurations relative to the cluster and host.
@@ -735,6 +736,20 @@ public interface KerberosHelper {
PrincipalKeyCredential getKDCAdministratorCredentials(String clusterName) throws AmbariException;
/**
+ * Saves underlying entities in persistent storage.
+ *
+ * @param resolvedKerberosKeytab kerberos keytab to be persisted
+ */
+ void processResolvedKeytab(ResolvedKerberosKeytab resolvedKerberosKeytab);
+
+ /**
+ * Removes existent persisted keytabs if they are not in {@code expectedKeytabs} collection.
+ *
+ * @param expectedKeytabs collection to compare existent keytabs
+ */
+ void removeStaleKeytabs(Collection<ResolvedKerberosKeytab> expectedKeytabs);
+
+ /**
* Translates a collection of configuration specifications (<code>config-type/property-name</code>)
* to a map of configuration types to a set of property names.
* <p>
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
index 4f14614..f913831 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
@@ -60,8 +60,11 @@ import org.apache.ambari.server.controller.internal.RequestStageContainer;
import org.apache.ambari.server.controller.utilities.KerberosChecker;
import org.apache.ambari.server.metadata.RoleCommandOrder;
import org.apache.ambari.server.orm.dao.ArtifactDAO;
+import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
+import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
import org.apache.ambari.server.orm.entities.ArtifactEntity;
+import org.apache.ambari.server.orm.entities.KerberosKeytabEntity;
import org.apache.ambari.server.security.credential.Credential;
import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.security.encryption.CredentialStoreService;
@@ -91,6 +94,7 @@ import org.apache.ambari.server.serveraction.kerberos.PrepareDisableKerberosServ
import org.apache.ambari.server.serveraction.kerberos.PrepareEnableKerberosServerAction;
import org.apache.ambari.server.serveraction.kerberos.PrepareKerberosIdentitiesServerAction;
import org.apache.ambari.server.serveraction.kerberos.UpdateKerberosConfigsServerAction;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
import org.apache.ambari.server.stageplanner.RoleGraph;
import org.apache.ambari.server.stageplanner.RoleGraphFactory;
import org.apache.ambari.server.state.Cluster;
@@ -125,12 +129,14 @@ import org.apache.ambari.server.utils.StageUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.directory.server.kerberos.shared.keytab.Keytab;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
@@ -202,6 +208,12 @@ public class KerberosHelperImpl implements KerberosHelper {
@Inject
private ArtifactDAO artifactDAO;
+ @Inject
+ private KerberosKeytabDAO kerberosKeytabDAO;
+
+ @Inject
+ KerberosPrincipalHostDAO kerberosPrincipalHostDAO;
+
/**
* The injector used to create new instances of helper classes like CreatePrincipalsServerAction
* and CreateKeytabFilesServerAction.
@@ -1484,9 +1496,10 @@ public class KerberosHelperImpl implements KerberosHelper {
@Override
public int addIdentities(KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter,
Collection<KerberosIdentityDescriptor> identities,
- Collection<String> identityFilter, String hostname, String serviceName,
+ Collection<String> identityFilter, String hostname, Long hostId, String serviceName,
String componentName, Map<String, Map<String, String>> kerberosConfigurations,
- Map<String, Map<String, String>> configurations, boolean ignoreHeadless)
+ Map<String, Map<String, String>> configurations,
+ Map<String, ResolvedKerberosKeytab> resolvedKeytabs, String realm)
throws IOException {
int identitiesAdded = 0;
@@ -1514,7 +1527,6 @@ public class KerberosHelperImpl implements KerberosHelper {
String keytabFileGroupName = null;
String keytabFileGroupAccess = null;
String keytabFileConfiguration = null;
- boolean keytabIsCachable = false;
if (keytabDescriptor != null) {
keytabFilePath = variableReplacementHelper.replaceVariables(keytabDescriptor.getFile(), configurations);
@@ -1523,24 +1535,84 @@ public class KerberosHelperImpl implements KerberosHelper {
keytabFileGroupName = variableReplacementHelper.replaceVariables(keytabDescriptor.getGroupName(), configurations);
keytabFileGroupAccess = variableReplacementHelper.replaceVariables(keytabDescriptor.getGroupAccess(), configurations);
keytabFileConfiguration = variableReplacementHelper.replaceVariables(keytabDescriptor.getConfiguration(), configurations);
- keytabIsCachable = keytabDescriptor.isCachable();
+ }
+ // Evaluate the principal "pattern" found in the record to generate the "evaluated principal"
+ // by replacing the _HOST and _REALM variables.
+ String evaluatedPrincipal = principal.replace("_HOST", hostname).replace("_REALM", realm);
+
+ ResolvedKerberosKeytab resolvedKeytab = new ResolvedKerberosKeytab(
+ keytabFilePath,
+ keytabFileOwnerName,
+ keytabFileOwnerAccess,
+ keytabFileGroupName,
+ keytabFileGroupAccess,
+ Sets.newHashSet(Pair.of(hostId, evaluatedPrincipal)),
+ serviceName.equalsIgnoreCase("AMBARI"),
+ componentName.equalsIgnoreCase("AMBARI_SERVER_SELF")
+ );
+ if (resolvedKeytabs.containsKey(keytabFilePath)) {
+ ResolvedKerberosKeytab sameKeytab = resolvedKeytabs.get(keytabFilePath);
+ // validating owner and group
+ String warnTemplate = "Keytab '{}' on host '{}' have different {}, originally set to '{}' and '{}:{}' has '{}', using '{}'";
+ if (!resolvedKeytab.getOwnerName().equals(sameKeytab.getOwnerName())) {
+ LOG.warn(warnTemplate,
+ keytabFilePath, hostname, "owners", sameKeytab.getOwnerName(),
+ serviceName, componentName, resolvedKeytab.getOwnerName(),
+ sameKeytab.getOwnerName());
+ }
+ if (!resolvedKeytab.getOwnerAccess().equals(sameKeytab.getOwnerAccess())) {
+ LOG.warn(warnTemplate,
+ keytabFilePath, hostname, "owner access", sameKeytab.getOwnerAccess(),
+ serviceName, componentName, resolvedKeytab.getOwnerAccess(),
+ sameKeytab.getOwnerAccess());
+ }
+ // TODO probably fail on group difference. Some services can inject its principals to same keytab, but
+ // TODO with different owners, so make sure that keytabs are accessible through group acls
+ // TODO this includes same group name and group 'r' mode
+ if (!resolvedKeytab.getGroupName().equals(sameKeytab.getGroupName())) {
+ LOG.warn(warnTemplate,
+ keytabFilePath, hostname, "groups", sameKeytab.getGroupName(),
+ serviceName, componentName, resolvedKeytab.getGroupName(),
+ sameKeytab.getGroupName());
+ }
+ if (!resolvedKeytab.getGroupAccess().equals(sameKeytab.getGroupAccess())) {
+ LOG.warn(warnTemplate,
+ keytabFilePath, hostname, "group access", sameKeytab.getGroupAccess(),
+ serviceName, componentName, resolvedKeytab.getGroupAccess(),
+ sameKeytab.getGroupAccess());
+ }
+ // end validating
+ // merge principal to keytab
+ sameKeytab.getMappedPrincipals().addAll(resolvedKeytab.getMappedPrincipals());
+ // ensure that keytab file on ambari-server host creating jass file
+ if (sameKeytab.isMustWriteAmbariJaasFile() || resolvedKeytab.isMustWriteAmbariJaasFile()) {
+ sameKeytab.setMustWriteAmbariJaasFile(true);
+ }
+ // ensure that this keytab is ambari-keytab, server will distribute it manually
+ if (sameKeytab.isAmbariServerKeytab() || resolvedKeytab.isAmbariServerKeytab()) {
+ sameKeytab.setAmbariServerKeytab(true);
+ }
+ } else {
+ resolvedKeytabs.put(keytabFilePath, resolvedKeytab);
+ LOG.info("Keytab {} owner:'{}:{}', group:'{}:{}' is defined", keytabFilePath,
+ keytabFileOwnerName, keytabFileOwnerAccess, keytabFileGroupName, keytabFileGroupAccess);
}
// Append an entry to the action data file builder...
+ // TODO obsolete, move to ResolvedKerberosKeytab
if(kerberosIdentityDataFileWriter != null) {
kerberosIdentityDataFileWriter.writeRecord(
hostname,
serviceName,
componentName,
- principal,
+ evaluatedPrincipal,
principalType,
keytabFilePath,
keytabFileOwnerName,
keytabFileOwnerAccess,
keytabFileGroupName,
keytabFileGroupAccess,
- (keytabIsCachable) ? "true" : "false",
- (ignoreHeadless && principalDescriptor.getType() == KerberosPrincipalType.USER) ? "true" : "false");
+ "true");
}
// Add the principal-related configuration to the map of configurations
@@ -1793,6 +1865,46 @@ public class KerberosHelperImpl implements KerberosHelper {
}
}
+ /**
+ * Creates and saves underlying {@link org.apache.ambari.server.orm.entities.KerberosPrincipalEntity},
+ * {@link org.apache.ambari.server.orm.entities.KerberosKeytabEntity} and
+ * {@link org.apache.ambari.server.orm.entities.KerberosPrincipalHostEntity} entities in JPA storage.
+ *
+ * @param resolvedKerberosKeytab kerberos keytab to be persisted
+ */
+ @Override
+ public void processResolvedKeytab(ResolvedKerberosKeytab resolvedKerberosKeytab) {
+ if (kerberosKeytabDAO.find(resolvedKerberosKeytab.getFile()) == null) {
+ kerberosKeytabDAO.create(resolvedKerberosKeytab.getFile());
+ }
+ for (Pair<Long, String> principalPair : resolvedKerberosKeytab.getMappedPrincipals()) {
+ String principal = principalPair.getRight();
+ Long hostId = principalPair.getLeft();
+ if (!kerberosPrincipalDAO.exists(principal)) {
+ kerberosPrincipalDAO.create(principal, false);
+ }
+ if (hostId != null) {
+ if(!kerberosPrincipalHostDAO.exists(principal, hostId, resolvedKerberosKeytab.getFile())) {
+ kerberosPrincipalHostDAO.create(principal, hostId, resolvedKerberosKeytab.getFile());
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeStaleKeytabs(Collection<ResolvedKerberosKeytab> expectedKeytabs) {
+ List<KerberosKeytabEntity> allKeytabs = kerberosKeytabDAO.findAll();
+ Set<KerberosKeytabEntity> staleKeytabs;
+ staleKeytabs = allKeytabs != null ? new HashSet<>(allKeytabs) : Collections.emptySet();
+ for (ResolvedKerberosKeytab keytab : expectedKeytabs) {
+ staleKeytabs.remove(new KerberosKeytabEntity(keytab.getFile()));
+ }
+ for (KerberosKeytabEntity staleKeytab: staleKeytabs) {
+ kerberosPrincipalHostDAO.removeByKeytabPath(staleKeytab.getKeytabPath());
+ kerberosKeytabDAO.remove(staleKeytab);
+ }
+ }
+
@Override
public Map<String, Set<String>> translateConfigurationSpecifications(Collection<String> configurationSpecifications) {
Map<String, Set<String>> translation = null;
@@ -2181,6 +2293,17 @@ public class KerberosHelperImpl implements KerberosHelper {
if (sch.getState() == State.INSTALLED) {
String hostname = sch.getHostName();
+ if(kerberosKeytabDAO.find(keytabFilePath) == null) {
+ kerberosKeytabDAO.create(keytabFilePath);
+ }
+ // create principals
+ if (!kerberosPrincipalDAO.exists(principal)) {
+ kerberosPrincipalDAO.create(principal, false);
+ }
+ if (!kerberosPrincipalHostDAO.exists(principal, sch.getHost().getHostId(), keytabFilePath)) {
+ kerberosPrincipalHostDAO.create(principal, sch.getHost().getHostId(), keytabFilePath);
+ }
+
kerberosIdentityDataFileWriter.writeRecord(
hostname,
Service.Type.KERBEROS.name(),
@@ -2192,7 +2315,6 @@ public class KerberosHelperImpl implements KerberosHelper {
keytabFileOwnerAccess,
keytabFileGroupName,
keytabFileGroupAccess,
- "false",
"false");
hostsWithValidKerberosClient.add(hostname);
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java
index bfaf7b4..0672500 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostKerberosIdentityResourceProvider.java
@@ -76,7 +76,7 @@ public class HostKerberosIdentityResourceProvider extends ReadOnlyResourceProvid
);
protected static final Set<String> PK_PROPERTY_IDS = Collections.unmodifiableSet(
- new HashSet<>(PK_PROPERTY_MAP.values())
+ new HashSet<>(PK_PROPERTY_MAP.values())
);
protected static final Set<String> PROPERTY_IDS = Collections.unmodifiableSet(
@@ -183,7 +183,7 @@ public class HostKerberosIdentityResourceProvider extends ReadOnlyResourceProvid
KerberosPrincipalType principalType = principalDescriptor.getType();
// Assume the principal is a service principal if not specified
- if(principalType == null) {
+ if (principalType == null) {
principalType = KerberosPrincipalType.SERVICE;
}
@@ -194,10 +194,17 @@ public class HostKerberosIdentityResourceProvider extends ReadOnlyResourceProvid
setResourceProperty(resource, KERBEROS_IDENTITY_PRINCIPAL_TYPE_PROPERTY_ID, principalType, requestPropertyIds);
setResourceProperty(resource, KERBEROS_IDENTITY_PRINCIPAL_LOCAL_USERNAME_PROPERTY_ID, principalDescriptor.getLocalUsername(), requestPropertyIds);
+ KerberosKeytabDescriptor keytabDescriptor = descriptor.getKeytabDescriptor();
+
String installedStatus;
+
if ((hostId != null) && kerberosPrincipalDAO.exists(principal)) {
- if (kerberosPrincipalHostDAO.exists(principal, hostId)) {
- installedStatus = "true";
+ if (keytabDescriptor != null) {
+ if (kerberosPrincipalHostDAO.exists(principal, hostId, keytabDescriptor.getFile())) {
+ installedStatus = "true";
+ } else {
+ installedStatus = "false";
+ }
} else {
installedStatus = "false";
}
@@ -207,7 +214,6 @@ public class HostKerberosIdentityResourceProvider extends ReadOnlyResourceProvid
setResourceProperty(resource, KERBEROS_IDENTITY_KEYTAB_FILE_INSTALLED_PROPERTY_ID, installedStatus, requestPropertyIds);
- KerberosKeytabDescriptor keytabDescriptor = descriptor.getKeytabDescriptor();
if (keytabDescriptor != null) {
String ownerAccess = keytabDescriptor.getOwnerAccess();
String groupAccess = keytabDescriptor.getGroupAccess();
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
index 8acc401..b91135f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceComponentUninstalledEvent.java
@@ -27,6 +27,7 @@ public class ServiceComponentUninstalledEvent extends ServiceEvent {
private final String m_componentName;
private final String m_hostName;
private final boolean m_recoveryEnabled;
+ private final Long m_hostId;
/**
* Constructor.
@@ -40,7 +41,7 @@ public class ServiceComponentUninstalledEvent extends ServiceEvent {
*/
public ServiceComponentUninstalledEvent(long clusterId, String stackName,
String stackVersion, String serviceName, String componentName,
- String hostName, boolean recoveryEnabled) {
+ String hostName, boolean recoveryEnabled, Long hostId) {
super(AmbariEventType.SERVICE_COMPONENT_UNINSTALLED_SUCCESS, clusterId,
stackName,
stackVersion, serviceName);
@@ -48,6 +49,7 @@ public class ServiceComponentUninstalledEvent extends ServiceEvent {
m_componentName = componentName;
m_hostName = hostName;
m_recoveryEnabled = recoveryEnabled;
+ m_hostId = hostId;
}
/**
@@ -71,6 +73,10 @@ public class ServiceComponentUninstalledEvent extends ServiceEvent {
return m_recoveryEnabled;
}
+ public Long getHostId() {
+ return m_hostId;
+ }
+
/**
* {@inheritDoc}
*/
@@ -84,11 +90,12 @@ public class ServiceComponentUninstalledEvent extends ServiceEvent {
buffer.append(", componentName=").append(m_componentName);
buffer.append(", hostName=").append(m_hostName);
buffer.append(", recoveryEnabled=").append(m_recoveryEnabled);
+ buffer.append(", hostId=").append(m_hostId);
buffer.append("}");
return buffer.toString();
}
public Component getComponent() {
- return new Component(getHostName(), getServiceName(), getComponentName());
+ return new Component(getHostName(), getServiceName(), getComponentName(), getHostId());
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabDAO.java
new file mode 100644
index 0000000..a8723b7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabDAO.java
@@ -0,0 +1,110 @@
+/*
+ * 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.orm.dao;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.HostEntity;
+import org.apache.ambari.server.orm.entities.KerberosKeytabEntity;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
+@Singleton
+public class KerberosKeytabDAO {
+ @Inject
+ Provider<EntityManager> entityManagerProvider;
+
+ @Transactional
+ public void create(KerberosKeytabEntity kerberosKeytabEntity) {
+ entityManagerProvider.get().persist(kerberosKeytabEntity);
+ }
+
+ public void create(String keytabPath) {
+ create(new KerberosKeytabEntity(keytabPath));
+ }
+
+ @Transactional
+ public KerberosKeytabEntity merge(KerberosKeytabEntity kerberosKeytabEntity) {
+ return entityManagerProvider.get().merge(kerberosKeytabEntity);
+ }
+
+ @Transactional
+ public void remove(KerberosKeytabEntity kerberosKeytabEntity) {
+ entityManagerProvider.get().remove(merge(kerberosKeytabEntity));
+ }
+
+ public void remove(String keytabPath) {
+ KerberosKeytabEntity kke = find(keytabPath);
+ if (kke != null) {
+ remove(kke);
+ }
+ }
+
+ @Transactional
+ public void refresh(KerberosKeytabEntity kerberosKeytabEntity) {
+ entityManagerProvider.get().refresh(kerberosKeytabEntity);
+ }
+
+
+ @RequiresSession
+ public KerberosKeytabEntity find(String keytabPath) {
+ return entityManagerProvider.get().find(KerberosKeytabEntity.class, keytabPath);
+ }
+
+ @RequiresSession
+ public List<KerberosKeytabEntity> findAll() {
+ TypedQuery<KerberosKeytabEntity> query = entityManagerProvider.get().
+ createNamedQuery("KerberosKeytabEntity.findAll", KerberosKeytabEntity.class);
+
+ return query.getResultList();
+ }
+
+ @RequiresSession
+ public boolean exists(String keytabPath) {
+ return find(keytabPath) != null;
+ }
+
+ @RequiresSession
+ public Collection<KerberosKeytabEntity> findByHost(Long hostId) {
+ TypedQuery<KerberosKeytabEntity> query = entityManagerProvider.get().
+ createNamedQuery("KerberosKeytabEntity.findByHost", KerberosKeytabEntity.class);
+ query.setParameter("hostId", hostId);
+ return query.getResultList();
+ }
+
+ public Collection<KerberosKeytabEntity> findByHost(HostEntity hostEntity) {
+ return findByHost(hostEntity.getHostId());
+ }
+
+ public void remove(List<KerberosKeytabEntity> entities) {
+ if (entities != null) {
+ for (KerberosKeytabEntity entity : entities) {
+ entityManagerProvider.get().remove(entity);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalDAO.java
index 93c55c1..81e4b3d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalDAO.java
@@ -161,4 +161,11 @@ public class KerberosPrincipalDAO {
return find(principalName) != null;
}
+ public void remove(List<KerberosPrincipalEntity> entities) {
+ if (entities != null) {
+ for (KerberosPrincipalEntity entity : entities) {
+ remove(entity);
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalHostDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalHostDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalHostDAO.java
index 0c17f19..f27dc48 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalHostDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosPrincipalHostDAO.java
@@ -56,8 +56,8 @@ public class KerberosPrincipalHostDAO {
entityManagerProvider.get().persist(kerberosPrincipalHostEntity);
}
- public void create(String principal, Long hostId) {
- create(new KerberosPrincipalHostEntity(principal, hostId));
+ public void create(String principal, Long hostId, String keytabPath) {
+ create(new KerberosPrincipalHostEntity(principal, hostId, keytabPath));
}
/**
@@ -121,6 +121,19 @@ public class KerberosPrincipalHostDAO {
}
/**
+ * Find KerberosPrincipalHostEntities for the requested host
+ *
+ * @return a List of requested KerberosPrincipalHostEntities or null if none were found
+ */
+ @RequiresSession
+ public List<KerberosPrincipalHostEntity> findByKeytabPath(String keytabPath) {
+ final TypedQuery<KerberosPrincipalHostEntity> query = entityManagerProvider.get()
+ .createNamedQuery("KerberosPrincipalHostEntityFindByKeytabPath", KerberosPrincipalHostEntity.class);
+ query.setParameter("keytabPath", keytabPath);
+ return query.getResultList();
+ }
+
+ /**
* Find the KerberosPrincipalHostEntity for the specified primary key
*
* @param primaryKey a KerberosPrincipalHostEntityPK containing the requested principal and host names
@@ -139,9 +152,9 @@ public class KerberosPrincipalHostDAO {
* @return the KerberosPrincipalHostEntity or null if not found
*/
@RequiresSession
- public KerberosPrincipalHostEntity find(String principalName, Long hostId) {
+ public KerberosPrincipalHostEntity find(String principalName, Long hostId, String keytabPath) {
return entityManagerProvider.get().find(KerberosPrincipalHostEntity.class,
- new KerberosPrincipalHostEntityPK(principalName, hostId));
+ new KerberosPrincipalHostEntityPK(principalName, hostId, keytabPath));
}
/**
@@ -179,6 +192,15 @@ public class KerberosPrincipalHostDAO {
}
/**
+ * Remove KerberosPrincipalHostEntity instances for the specified host
+ *
+ * @param keytabPath a String indicating the keytab path of principal
+ */
+ @Transactional
+ public void removeByKeytabPath(String keytabPath) {
+ remove(findByKeytabPath(keytabPath));
+ }
+ /**
* Remove KerberosPrincipalHostEntity instance for the specified principal and host
*
* @param principalName a String indicating the name of the principal
@@ -186,8 +208,8 @@ public class KerberosPrincipalHostDAO {
* @see #remove(org.apache.ambari.server.orm.entities.KerberosPrincipalHostEntity)
*/
@Transactional
- public void remove(String principalName, Long hostId) {
- remove(new KerberosPrincipalHostEntity(principalName, hostId));
+ public void remove(String principalName, Long hostId, String keytabPath) {
+ remove(new KerberosPrincipalHostEntity(principalName, hostId, keytabPath));
}
/**
@@ -210,8 +232,8 @@ public class KerberosPrincipalHostDAO {
* @return true if the requested principal exists
*/
@RequiresSession
- public boolean exists(String principalName, Long hostId) {
- return find(principalName, hostId) != null;
+ public boolean exists(String principalName, Long hostId, String keytabPath) {
+ return find(principalName, hostId, keytabPath) != null;
}
/**
@@ -219,7 +241,7 @@ public class KerberosPrincipalHostDAO {
*
* @param entities a collection of KerberosPrincipalHostEntity items to remove
*/
- private void remove(List<KerberosPrincipalHostEntity> entities) {
+ public void remove(List<KerberosPrincipalHostEntity> entities) {
if (entities != null) {
for (KerberosPrincipalHostEntity entity : entities) {
entityManagerProvider.get().remove(entity);
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosKeytabEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosKeytabEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosKeytabEntity.java
new file mode 100644
index 0000000..a25931b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosKeytabEntity.java
@@ -0,0 +1,86 @@
+/*
+ * 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.orm.entities;
+
+import java.util.Collection;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "kerberos_keytab")
+@NamedQueries({
+ @NamedQuery(name = "KerberosKeytabEntity.findAll", query = "SELECT kk FROM KerberosKeytabEntity kk"),
+ @NamedQuery(name = "KerberosKeytabEntity.findByHost",
+ query = "SELECT kk FROM KerberosKeytabEntity kk JOIN kk.kerberosPrincipalHostEntities he WHERE he.hostId=:hostId")
+})
+public class KerberosKeytabEntity {
+ @Id
+ @Column(name = "keytab_path", insertable = true, updatable = false, nullable = false)
+ private String keytabPath = null;
+
+ @OneToMany(mappedBy = "keytabEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
+ private Collection<KerberosPrincipalHostEntity> kerberosPrincipalHostEntities;
+
+ public KerberosKeytabEntity(){
+
+ }
+
+ public KerberosKeytabEntity(String keytabPath){
+ setKeytabPath(keytabPath);
+ }
+
+ public String getKeytabPath() {
+ return keytabPath;
+ }
+
+ public void setKeytabPath(String keytabPath) {
+ this.keytabPath = keytabPath;
+ }
+
+ public Collection<KerberosPrincipalHostEntity> getKerberosPrincipalHostEntities() {
+ return kerberosPrincipalHostEntities;
+ }
+
+ public void setKerberosPrincipalHostEntities(Collection<KerberosPrincipalHostEntity> kerberosPrincipalHostEntities) {
+ this.kerberosPrincipalHostEntities = kerberosPrincipalHostEntities;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ KerberosKeytabEntity that = (KerberosKeytabEntity) o;
+
+ return keytabPath.equals(that.keytabPath);
+ }
+
+ @Override
+ public int hashCode() {
+ return keytabPath.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntity.java
index bb67131..d4e80c6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntity.java
@@ -23,6 +23,7 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
@@ -40,7 +41,9 @@ import javax.persistence.Table;
@NamedQuery(name = "KerberosPrincipalHostEntityFindByPrincipal",
query = "SELECT kph FROM KerberosPrincipalHostEntity kph WHERE kph.principalName=:principalName"),
@NamedQuery(name = "KerberosPrincipalHostEntityFindByHost",
- query = "SELECT kph FROM KerberosPrincipalHostEntity kph WHERE kph.hostId=:hostId")
+ query = "SELECT kph FROM KerberosPrincipalHostEntity kph WHERE kph.hostId=:hostId"),
+ @NamedQuery(name = "KerberosPrincipalHostEntityFindByKeytabPath",
+ query = "SELECT kph FROM KerberosPrincipalHostEntity kph WHERE kph.keytabPath=:keytabPath"),
})
public class KerberosPrincipalHostEntity {
@@ -52,6 +55,10 @@ public class KerberosPrincipalHostEntity {
@Column(name = "host_id", insertable = true, updatable = false, nullable = false)
private Long hostId;
+ @Id
+ @Column(name = "keytab_path", updatable = false, nullable = false)
+ private String keytabPath;
+
@ManyToOne
@JoinColumn(name = "principal_name", referencedColumnName = "principal_name", nullable = false, insertable = false, updatable = false)
private KerberosPrincipalEntity principalEntity;
@@ -60,6 +67,14 @@ public class KerberosPrincipalHostEntity {
@JoinColumn(name = "host_id", referencedColumnName = "host_id", nullable = false, insertable = false, updatable = false)
private HostEntity hostEntity;
+ @ManyToOne
+ @JoinColumns({
+ @JoinColumn(name = "keytab_path", referencedColumnName = "keytab_path", nullable = false, insertable = false, updatable = false)
+ })
+ private KerberosKeytabEntity keytabEntity;
+
+ @Column(name = "is_distributed", insertable = true, updatable = true, nullable = false)
+ private Integer isDistributed = 0;
/**
* Constucts an empty KerberosPrincipalHostEntity
*/
@@ -72,9 +87,23 @@ public class KerberosPrincipalHostEntity {
* @param principalName a String indicating this KerberosPrincipalHostEntity's principal name
* @param hostId a Long indicating the KerberosPrincipalHostEntity's host id
*/
- public KerberosPrincipalHostEntity(String principalName, Long hostId) {
+ public KerberosPrincipalHostEntity(String principalName, Long hostId, String keytabPath) {
+ setPrincipalName(principalName);
+ setHostId(hostId);
+ setKeytabPath(keytabPath);
+ }
+
+ /**
+ * Constructs a new KerberosPrincipalHostEntity
+ *
+ * @param principalName a String indicating this KerberosPrincipalHostEntity's principal name
+ * @param hostId a Long indicating the KerberosPrincipalHostEntity's host id
+ */
+ public KerberosPrincipalHostEntity(String principalName, Long hostId, String keytabPath, boolean isDistributed) {
setPrincipalName(principalName);
setHostId(hostId);
+ setKeytabPath(keytabPath);
+ setDistributed(isDistributed);
}
/**
@@ -157,4 +186,28 @@ public class KerberosPrincipalHostEntity {
public void setPrincipalEntity(KerberosPrincipalEntity principalEntity) {
this.principalEntity = principalEntity;
}
+
+ public String getKeytabPath() {
+ return keytabPath;
+ }
+
+ public void setKeytabPath(String keytabPath) {
+ this.keytabPath = keytabPath;
+ }
+
+ public KerberosKeytabEntity getKeytabEntity() {
+ return keytabEntity;
+ }
+
+ public void setKeytabEntity(KerberosKeytabEntity keytabEntity) {
+ this.keytabEntity = keytabEntity;
+ }
+
+ public Boolean getDistributed() {
+ return isDistributed == 1;
+ }
+
+ public void setDistributed(Boolean isDistributed) {
+ this.isDistributed = (isDistributed) ? 1 : 0;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntityPK.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntityPK.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntityPK.java
index 600bb8b..7e57e4a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntityPK.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/KerberosPrincipalHostEntityPK.java
@@ -36,12 +36,17 @@ public class KerberosPrincipalHostEntityPK implements Serializable{
@Column(name = "host_id", insertable = false, updatable = false, nullable = false)
private Long hostId = null;
+ @Id
+ @Column(name = "keytab_path", insertable = false, updatable = false, nullable = false)
+ private String keytabPath = null;
+
public KerberosPrincipalHostEntityPK() {
}
- public KerberosPrincipalHostEntityPK(String principalName, Long hostId) {
+ public KerberosPrincipalHostEntityPK(String principalName, Long hostId, String keytabPath) {
setPrincipalName(principalName);
setHostId(hostId);
+ setKeytabPath(keytabPath);
}
/**
@@ -92,11 +97,19 @@ public class KerberosPrincipalHostEntityPK implements Serializable{
KerberosPrincipalHostEntityPK that = (KerberosPrincipalHostEntityPK) o;
return this.principalName.equals(that.principalName) &&
- this.hostId.equals(that.hostId);
+ this.hostId.equals(that.hostId) && this.keytabPath.equals(that.keytabPath);
}
@Override
public int hashCode() {
- return 31 * principalName.hashCode() + hostId.hashCode();
+ return 31 * principalName.hashCode() + hostId.hashCode() + keytabPath.hashCode();
+ }
+
+ public String getKeytabPath() {
+ return keytabPath;
+ }
+
+ public void setKeytabPath(String keytabPath) {
+ this.keytabPath = keytabPath;
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
index 7948a60..1dc8ca8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
@@ -33,6 +33,7 @@ import java.util.Set;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.ServiceComponentHost;
import org.apache.ambari.server.state.kerberos.KerberosComponentDescriptor;
@@ -77,13 +78,12 @@ public abstract class AbstractPrepareKerberosServerAction extends KerberosServer
Map<String, Map<String, String>> currentConfigurations,
Map<String, Map<String, String>> kerberosConfigurations,
boolean includeAmbariIdentity,
- Map<String, Set<String>> propertiesToBeIgnored,
- boolean excludeHeadless) throws AmbariException {
+ Map<String, Set<String>> propertiesToBeIgnored) throws AmbariException {
List<Component> components = new ArrayList<>();
for (ServiceComponentHost each : schToProcess) {
components.add(Component.fromServiceComponentHost(each));
}
- processServiceComponents(cluster, kerberosDescriptor, components, identityFilter, dataDirectory, currentConfigurations, kerberosConfigurations, includeAmbariIdentity, propertiesToBeIgnored, excludeHeadless);
+ processServiceComponents(cluster, kerberosDescriptor, components, identityFilter, dataDirectory, currentConfigurations, kerberosConfigurations, includeAmbariIdentity, propertiesToBeIgnored);
}
protected void processServiceComponents(Cluster cluster, KerberosDescriptor kerberosDescriptor,
@@ -92,8 +92,7 @@ public abstract class AbstractPrepareKerberosServerAction extends KerberosServer
Map<String, Map<String, String>> currentConfigurations,
Map<String, Map<String, String>> kerberosConfigurations,
boolean includeAmbariIdentity,
- Map<String, Set<String>> propertiesToBeIgnored,
- boolean excludeHeadless) throws AmbariException {
+ Map<String, Set<String>> propertiesToBeIgnored) throws AmbariException {
actionLog.writeStdOut("Processing Kerberos identities and configurations");
@@ -125,15 +124,17 @@ public abstract class AbstractPrepareKerberosServerAction extends KerberosServer
throw new AmbariException(message, e);
}
+ HashMap<String, ResolvedKerberosKeytab> resolvedKeytabs = new HashMap<>();
+ String realm = getDefaultRealm(getCommandParameters());
+
try {
Map<String, Set<String>> propertiesToIgnore = null;
-
// Iterate over the components installed on the current host to get the service and
// component-level Kerberos descriptors in order to determine which principals,
// keytab files, and configurations need to be created or updated.
for (Component sch : schToProcess) {
String hostName = sch.getHostName();
-
+ Long hostId = sch.getHostId();
String serviceName = sch.getServiceName();
String componentName = sch.getServiceComponentName();
@@ -157,7 +158,8 @@ public abstract class AbstractPrepareKerberosServerAction extends KerberosServer
// Add service-level principals (and keytabs)
kerberosHelper.addIdentities(kerberosIdentityDataFileWriter, serviceIdentities,
- identityFilter, hostName, serviceName, componentName, kerberosConfigurations, currentConfigurations, excludeHeadless);
+ identityFilter, hostName, hostId, serviceName, componentName, kerberosConfigurations, currentConfigurations,
+ resolvedKeytabs, realm);
propertiesToIgnore = gatherPropertiesToIgnore(serviceIdentities, propertiesToIgnore);
KerberosComponentDescriptor componentDescriptor = serviceDescriptor.getComponent(componentName);
@@ -172,7 +174,8 @@ public abstract class AbstractPrepareKerberosServerAction extends KerberosServer
// Add component-level principals (and keytabs)
kerberosHelper.addIdentities(kerberosIdentityDataFileWriter, componentIdentities,
- identityFilter, hostName, serviceName, componentName, kerberosConfigurations, currentConfigurations, excludeHeadless);
+ identityFilter, hostName, hostId, serviceName, componentName, kerberosConfigurations, currentConfigurations,
+ resolvedKeytabs, realm);
propertiesToIgnore = gatherPropertiesToIgnore(componentIdentities, propertiesToIgnore);
}
}
@@ -193,7 +196,8 @@ public abstract class AbstractPrepareKerberosServerAction extends KerberosServer
List<KerberosIdentityDescriptor> componentIdentities = Collections.singletonList(identity);
kerberosHelper.addIdentities(kerberosIdentityDataFileWriter, componentIdentities,
- identityFilter, KerberosHelper.AMBARI_SERVER_HOST_NAME, "AMBARI", componentName, kerberosConfigurations, currentConfigurations, excludeHeadless);
+ identityFilter, StageUtils.getHostName(), ambariServerHostID(), "AMBARI",componentName, kerberosConfigurations, currentConfigurations,
+ resolvedKeytabs, realm);
propertiesToIgnore = gatherPropertiesToIgnore(componentIdentities, propertiesToIgnore);
}
}
@@ -202,6 +206,11 @@ public abstract class AbstractPrepareKerberosServerAction extends KerberosServer
if ((propertiesToBeIgnored != null) && (propertiesToIgnore != null)) {
propertiesToBeIgnored.putAll(propertiesToIgnore);
}
+
+ // create database records for keytabs that must be presented on cluster
+ for (ResolvedKerberosKeytab keytab : resolvedKeytabs.values()) {
+ kerberosHelper.processResolvedKeytab(keytab);
+ }
} catch (IOException e) {
String message = String.format("Failed to write index file - %s", identityDataFile.getAbsolutePath());
LOG.error(message, e);
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
index dae8254..002076d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CleanupServerAction.java
@@ -32,15 +32,24 @@ import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
+import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.SecurityType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.inject.Inject;
+
/**
* Used to perform Kerberos Cleanup Operations as part of the Unkerberization process
*/
public class CleanupServerAction extends KerberosServerAction {
+ @Inject
+ KerberosKeytabDAO kerberosKeytabDAO;
+
+ @Inject
+ KerberosPrincipalDAO kerberosPrincipalDAO;
private final static Logger LOG = LoggerFactory.getLogger(CleanupServerAction.class);
@@ -102,11 +111,12 @@ public class CleanupServerAction extends KerberosServerAction {
ClusterController clusterController = ClusterControllerHelper.getClusterController();
- ResourceProvider artifactProvider =
- clusterController.ensureResourceProvider(Resource.Type.Artifact);
+ ResourceProvider artifactProvider = clusterController.ensureResourceProvider(Resource.Type.Artifact);
try {
artifactProvider.deleteResources(new RequestImpl(null, null, null, null), predicate);
+ kerberosPrincipalDAO.remove(kerberosPrincipalDAO.findAll());
+ kerberosKeytabDAO.remove(kerberosKeytabDAO.findAll());
LOG.info("Kerberos descriptor removed successfully.");
actionLog.writeStdOut("Kerberos descriptor removed successfully.");
} catch (NoSuchResourceException e) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/Component.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/Component.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/Component.java
index 4f1ee52..ed7642c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/Component.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/Component.java
@@ -25,18 +25,21 @@ public class Component {
private final String hostName;
private final String serviceName;
private final String serviceComponentName;
+ private final Long hostId;
public static Component fromServiceComponentHost(ServiceComponentHost serviceComponentHost) {
return new Component(
serviceComponentHost.getHostName(),
serviceComponentHost.getServiceName(),
- serviceComponentHost.getServiceComponentName());
+ serviceComponentHost.getServiceComponentName(),
+ serviceComponentHost.getHost().getHostId());
}
- public Component(String hostName, String serviceName, String serviceComponentName) {
+ public Component(String hostName, String serviceName, String serviceComponentName, Long hostId) {
this.hostName = hostName;
this.serviceName = serviceName;
this.serviceComponentName = serviceComponentName;
+ this.hostId = hostId;
}
public String getHostName() {
@@ -51,6 +54,10 @@ public class Component {
return serviceComponentName;
}
+ public Long getHostId() {
+ return hostId;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -60,6 +67,7 @@ public class Component {
.append(hostName, component.hostName)
.append(serviceName, component.serviceName)
.append(serviceComponentName, component.serviceComponentName)
+ .append(hostId, component.hostId)
.isEquals();
}
@@ -69,6 +77,7 @@ public class Component {
.append(hostName)
.append(serviceName)
.append(serviceComponentName)
+ .append(hostId)
.toHashCode();
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
index fca1b6f..3384152 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
@@ -26,11 +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.controller.KerberosHelper;
import org.apache.ambari.server.controller.utilities.KerberosChecker;
-import org.apache.ambari.server.orm.dao.HostDAO;
+import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
-import org.apache.ambari.server.orm.entities.HostEntity;
+import org.apache.ambari.server.orm.entities.KerberosPrincipalHostEntity;
import org.apache.ambari.server.serveraction.ActionLog;
import org.apache.ambari.server.utils.ShellCommandUtil;
import org.apache.ambari.server.utils.StageUtils;
@@ -63,7 +62,7 @@ public class ConfigureAmbariIdentitiesServerAction extends KerberosServerAction
private KerberosPrincipalHostDAO kerberosPrincipalHostDAO;
@Inject
- private HostDAO hostDAO;
+ private KerberosKeytabDAO kerberosKeytabDAO;
/**
* Called to execute this action. Upon invocation, calls
@@ -121,7 +120,8 @@ public class ConfigureAmbariIdentitiesServerAction extends KerberosServerAction
} else {
String hostName = identityRecord.get(KerberosIdentityDataFileReader.HOSTNAME);
- if (hostName != null && hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME)) {
+ String serviceName = identityRecord.get(KerberosIdentityDataFileReader.SERVICE);
+ if (hostName != null && serviceName.equals("AMBARI")) {
String destKeytabFilePath = identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_PATH);
File hostDirectory = new File(dataDirectory, hostName);
File srcKeytabFile = new File(hostDirectory, DigestUtils.sha1Hex(destKeytabFilePath));
@@ -182,11 +182,7 @@ public class ConfigureAmbariIdentitiesServerAction extends KerberosServerAction
groupName, groupReadable, groupWritable);
String ambariServerHostName = StageUtils.getHostName();
- HostEntity ambariServerHostEntity = hostDAO.findByName(ambariServerHostName);
- Long ambariServerHostID = (ambariServerHostEntity == null)
- ? null
- : ambariServerHostEntity.getHostId();
-
+ Long ambariServerHostID = ambariServerHostID();
if (ambariServerHostID == null) {
String message = String.format("Failed to add the kerberos_principal_host record for %s on " +
"the Ambari server host since the host id for Ambari server host, %s, was not found." +
@@ -196,8 +192,19 @@ public class ConfigureAmbariIdentitiesServerAction extends KerberosServerAction
if (actionLog != null) {
actionLog.writeStdErr(message);
}
- } else if (!kerberosPrincipalHostDAO.exists(principal, ambariServerHostID)) {
- kerberosPrincipalHostDAO.create(principal, ambariServerHostID);
+ } else if (!kerberosPrincipalHostDAO.exists(principal, ambariServerHostID, destKeytabFilePath)) {
+ if (!kerberosKeytabDAO.exists(destKeytabFilePath)) {
+ kerberosKeytabDAO.create(destKeytabFilePath);
+ }
+ if(!kerberosPrincipalHostDAO.exists(principal, ambariServerHostID, destKeytabFilePath)) {
+ kerberosPrincipalHostDAO.create(
+ new KerberosPrincipalHostEntity(principal, ambariServerHostID, destKeytabFilePath, true)
+ );
+ } else {
+ KerberosPrincipalHostEntity kphe = kerberosPrincipalHostDAO.find(principal, ambariServerHostID, destKeytabFilePath);
+ kphe.setDistributed(true);
+ kerberosPrincipalHostDAO.merge(kphe);
+ }
}
if (actionLog != null) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/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 355f515..aa65e61 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
@@ -205,33 +205,29 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
ensureAmbariOnlyAccess(hostDirectory);
}
- 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;
- }
+ 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;
+ }
- boolean regenerateKeytabs = getOperationType(getCommandParameters()) == OperationType.RECREATE_ALL;
- boolean onlyKeytabWrite = "true".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.ONLY_KEYTAB_WRITE));
- boolean grabKeytabFromCache = regenerateKeytabs && onlyKeytabWrite;
- // if grabKeytabFromCache=true we will try to get keytab from cache and send to agent, it will be true for
- // headless cached keytabs
- if (password == null) {
- if (!grabKeytabFromCache && (hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME) || kerberosPrincipalHostDAO
- .exists(evaluatedPrincipal, hostEntity.getHostId()))) {
- // 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);
- LOG.debug(message);
- } else {
- KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
- String cachedKeytabPath = (principalEntity == null) ? null : principalEntity.getCachedKeytabPath();
+ boolean regenerateKeytabs = getOperationType(getCommandParameters()) == OperationType.RECREATE_ALL;
+ if (password == null) {
+ if (!regenerateKeytabs && (hostName.equalsIgnoreCase(KerberosHelper.AMBARI_SERVER_HOST_NAME) || kerberosPrincipalHostDAO
+ .exists(evaluatedPrincipal, hostEntity.getHostId(), keytabFilePath))) {
+ // 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);
+ LOG.debug(message);
+ } else {
+ KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
+ String cachedKeytabPath = (principalEntity == null) ? null : principalEntity.getCachedKeytabPath();
if (cachedKeytabPath == null) {
message = String.format("Failed to create keytab for %s, missing cached file", evaluatedPrincipal);
@@ -250,9 +246,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
}
}
} else {
- boolean canCache = ("true".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.KEYTAB_FILE_IS_CACHABLE)));
-
- Keytab keytab = createKeytab(evaluatedPrincipal, password, keyNumber, operationHandler, visitedPrincipalKeys != null, canCache, actionLog);
+ Keytab keytab = createKeytab(evaluatedPrincipal, password, keyNumber, operationHandler, visitedPrincipalKeys != null, true, actionLog);
if (keytab != null) {
try {
@@ -287,7 +281,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
}
} else {
message = String.format("Failed to create keytab file for %s, the container directory does not exist: %s",
- evaluatedPrincipal, hostDirectory.getAbsolutePath());
+ evaluatedPrincipal, hostDirectory.getAbsolutePath());
actionLog.writeStdErr(message);
LOG.error(message);
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
@@ -299,10 +293,10 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
}
}
} finally {
- if(commandReport != null && HostRoleStatus.FAILED.toString().equals(commandReport.getStatus())) {
+ if (commandReport != null && HostRoleStatus.FAILED.toString().equals(commandReport.getStatus())) {
auditEventBuilder.withReasonOfFailure(message == null ? "Unknown error" : message);
}
- if(commandReport != null || auditEventBuilder.hasPrincipal()) {
+ if (commandReport != null || auditEventBuilder.hasPrincipal()) {
auditLog(auditEventBuilder.build());
}
}
@@ -359,12 +353,12 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
// and store that location so it can be reused rather than recreate it.
KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(principal);
if (principalEntity != null) {
- if (!principalEntity.isService() && canCache) {
+ if (canCache) {
File cachedKeytabFile = cacheKeytab(principal, keytab);
String previousCachedFilePath = principalEntity.getCachedKeytabPath();
String cachedKeytabFilePath = ((cachedKeytabFile == null) || !cachedKeytabFile.exists())
- ? null
- : cachedKeytabFile.getAbsolutePath();
+ ? null
+ : cachedKeytabFile.getAbsolutePath();
principalEntity.setCachedKeytabPath(cachedKeytabFilePath);
kerberosPrincipalDAO.merge(principalEntity);
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/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 1c0853b9..08e03bd 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
@@ -18,6 +18,7 @@
package org.apache.ambari.server.serveraction.kerberos;
+import java.io.File;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -30,6 +31,7 @@ import org.apache.ambari.server.audit.event.kerberos.CreatePrincipalKerberosAudi
import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
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.commons.lang.StringUtils;
@@ -128,27 +130,24 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
seenPrincipals.add(evaluatedPrincipal);
boolean processPrincipal;
+
+ // TODO add invalidate_principals option to make keytabs invalid all over the cluster.
+ KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
+
boolean regenerateKeytabs = getOperationType(getCommandParameters()) == OperationType.RECREATE_ALL;
if (regenerateKeytabs) {
- // do not process cached identities that can be passed as is(headless identities)
- processPrincipal = "false".equals(identityRecord.get(KerberosIdentityDataFileReader.ONLY_KEYTAB_WRITE).toLowerCase());
+ // force recreation of principal due to keytab regeneration
+ processPrincipal = true;
+ } else if (kerberosPrincipalEntity == null) {
+ // This principal has not been processed before, process it.
+ processPrincipal = true;
+ } else if (!StringUtils.isEmpty(kerberosPrincipalEntity.getCachedKeytabPath())) {
+ // This principal has been processed and a keytab file has been cached for it... do not process it.
+ processPrincipal = false;
} else {
- KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
-
- if (kerberosPrincipalEntity == null) {
- // This principal has not been processed before, process it.
- processPrincipal = true;
- } else if (!StringUtils.isEmpty(kerberosPrincipalEntity.getCachedKeytabPath())) {
- // This principal has been processed and a keytab file has been cached for it... do not process it.
- processPrincipal = false;
- } else if (kerberosPrincipalHostDAO.exists(evaluatedPrincipal)) {
- // This principal has been processed and a keytab file has been distributed... do not process it.
- processPrincipal = false;
- } else {
- // This principal has been processed but a keytab file for it has not been distributed... process it.
- processPrincipal = true;
- }
+ // This principal has been processed but a keytab file for it has not been distributed... process it.
+ processPrincipal = true;
}
if (processPrincipal) {
@@ -159,7 +158,6 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
if (password == null) {
boolean servicePrincipal = "service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE));
CreatePrincipalResult result = createPrincipal(evaluatedPrincipal, servicePrincipal, kerberosConfiguration, operationHandler, regenerateKeytabs, actionLog);
-
if (result == null) {
commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
} else {
@@ -167,6 +165,20 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
principalPasswordMap.put(evaluatedPrincipal, result.getPassword());
principalKeyNumberMap.put(evaluatedPrincipal, 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);
+ }
+ // invalidate principal cache
+ KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal);
+ try {
+ new File(principalEntity.getCachedKeytabPath()).delete();
+ } catch (Exception e) {
+ LOG.debug("Failed to delete cache file '{}'", principalEntity.getCachedKeytabPath());
+ }
+ principalEntity.setCachedKeytabPath(null);
+ kerberosPrincipalDAO.merge(principalEntity);
}
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFile.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFile.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFile.java
index ddf3d1b..ae1217c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFile.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFile.java
@@ -36,6 +36,4 @@ public interface KerberosIdentityDataFile extends KerberosDataFile {
String KEYTAB_FILE_GROUP_NAME = "keytab_file_group_name";
String KEYTAB_FILE_GROUP_ACCESS = "keytab_file_group_access";
String KEYTAB_FILE_IS_CACHABLE = "keytab_file_is_cachable";
- String ONLY_KEYTAB_WRITE = "only_keytab_write";
-
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/d03c24b9/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFileWriter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFileWriter.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFileWriter.java
index ea742bd..f55c6f4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFileWriter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosIdentityDataFileWriter.java
@@ -68,8 +68,7 @@ public class KerberosIdentityDataFileWriter extends AbstractKerberosDataFileWrit
String principal, String principalType,
String keytabFilePath, String keytabFileOwnerName,
String keytabFileOwnerAccess, String keytabFileGroupName,
- String keytabFileGroupAccess, String keytabFileCanCache,
- String onlyKeytabWrite)
+ String keytabFileGroupAccess, String keytabFileCanCache)
throws IOException {
super.appendRecord(hostName,
serviceName,
@@ -81,8 +80,7 @@ public class KerberosIdentityDataFileWriter extends AbstractKerberosDataFileWrit
keytabFileOwnerAccess,
keytabFileGroupName,
keytabFileGroupAccess,
- keytabFileCanCache,
- onlyKeytabWrite);
+ keytabFileCanCache);
}
@Override
@@ -97,7 +95,6 @@ public class KerberosIdentityDataFileWriter extends AbstractKerberosDataFileWrit
KEYTAB_FILE_OWNER_ACCESS,
KEYTAB_FILE_GROUP_NAME,
KEYTAB_FILE_GROUP_ACCESS,
- KEYTAB_FILE_IS_CACHABLE,
- ONLY_KEYTAB_WRITE);
+ KEYTAB_FILE_IS_CACHABLE);
}
}