You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jl...@apache.org on 2017/10/11 05:25:11 UTC
[15/31] ambari git commit: AMBARI-22138. When regenerating keytab
files for a service, non-service-specific principals are affected (rlevas)
AMBARI-22138. When regenerating keytab files for a service, non-service-specific principals are affected (rlevas)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5af1e539
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5af1e539
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5af1e539
Branch: refs/heads/branch-feature-AMBARI-14714
Commit: 5af1e539cce928b32fc5aca67c7bf8dbc2bd3c2e
Parents: b0c24a5
Author: Robert Levas <rl...@hortonworks.com>
Authored: Mon Oct 9 13:06:13 2017 -0400
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Mon Oct 9 13:06:19 2017 -0400
----------------------------------------------------------------------
.../server/controller/KerberosHelper.java | 9 +-
.../server/controller/KerberosHelperImpl.java | 244 ++++++++++++-------
.../utilities/RemovableIdentities.java | 2 +-
.../kerberos/CreateKeytabFilesServerAction.java | 2 +-
.../kerberos/CreatePrincipalsServerAction.java | 2 +-
.../kerberos/KerberosServerAction.java | 71 ++++--
.../PrepareDisableKerberosServerAction.java | 3 +-
.../PrepareEnableKerberosServerAction.java | 6 +-
.../PrepareKerberosIdentitiesServerAction.java | 142 ++++++++---
.../kerberos/AbstractKerberosDescriptor.java | 25 ++
.../AbstractKerberosDescriptorContainer.java | 18 +-
.../kerberos/KerberosIdentityDescriptor.java | 160 ++++++++++++
.../server/controller/KerberosHelperTest.java | 5 -
.../utilities/KerberosIdentityCleanerTest.java | 8 +-
.../state/kerberos/KerberosDescriptorTest.java | 150 +++++++++++-
15 files changed, 665 insertions(+), 182 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/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 20c5708..b8e1be1 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
@@ -442,12 +442,6 @@ public interface KerberosHelper {
* @param hostFilter a set of hostname indicating the set of hosts to process -
* if null, no filter is relevant; if empty, the filter
* indicates no relevant hosts
- * @param identityFilter a Collection of identity names indicating the relevant
- * identities - if null, no filter is relevant; if empty,
- * the filter indicates no relevant identities
- * @param shouldProcessCommand a Command implementation to determine if the relevant component
- * is in a state in which is should be process for the current
- * Kerberos operation.
* @return a list of ServiceComponentHost instances and should be processed during the relevant
* Kerberos operation.
* @throws AmbariException
@@ -455,8 +449,7 @@ public interface KerberosHelper {
List<ServiceComponentHost> getServiceComponentHostsToProcess(Cluster cluster,
KerberosDescriptor kerberosDescriptor,
Map<String, ? extends Collection<String>> serviceComponentFilter,
- Collection<String> hostFilter, Collection<String> identityFilter,
- Command<Boolean, ServiceComponentHost> shouldProcessCommand)
+ Collection<String> hostFilter)
throws AmbariException;
Set<String> getHostsWithValidKerberosClient(Cluster cluster) throws AmbariException;
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/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 b691968..f8fe31a 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
@@ -122,6 +122,7 @@ import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
import org.apache.ambari.server.state.kerberos.VariableReplacementHelper;
import org.apache.ambari.server.state.svccomphost.ServiceComponentHostServerActionEvent;
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.directory.server.kerberos.shared.keytab.Keytab;
@@ -268,10 +269,12 @@ public class KerberosHelperImpl implements KerberosHelper {
boolean updateConfigurations = !requestProperties.containsKey(DIRECTIVE_IGNORE_CONFIGS)
|| !"true".equalsIgnoreCase(requestProperties.get(DIRECTIVE_IGNORE_CONFIGS));
+ boolean forceAllHosts = (hostFilter == null) || (hostFilter.contains("*"));
+
if ("true".equalsIgnoreCase(value) || "all".equalsIgnoreCase(value)) {
- handler = new CreatePrincipalsAndKeytabsHandler(true, updateConfigurations, true);
+ handler = new CreatePrincipalsAndKeytabsHandler(KerberosServerAction.OperationType.RECREATE_ALL, updateConfigurations, forceAllHosts, true);
} else if ("missing".equalsIgnoreCase(value)) {
- handler = new CreatePrincipalsAndKeytabsHandler(false, updateConfigurations, true);
+ handler = new CreatePrincipalsAndKeytabsHandler(KerberosServerAction.OperationType.CREATE_MISSING, updateConfigurations, forceAllHosts, true);
}
if (handler != null) {
@@ -326,7 +329,7 @@ public class KerberosHelperImpl implements KerberosHelper {
if (serviceComponentsArray.length == 2) {
serviceComponentFilter.put(serviceName, ImmutableSet.copyOf(serviceComponentsArray[1].split(";")));
} else {
- serviceComponentFilter.put(serviceName, null);
+ serviceComponentFilter.put(serviceName, ImmutableSet.of("*"));
}
}
return serviceComponentFilter.build();
@@ -340,7 +343,7 @@ public class KerberosHelperImpl implements KerberosHelper {
RequestStageContainer requestStageContainer, Boolean manageIdentities)
throws AmbariException, KerberosOperationException {
return handle(cluster, getKerberosDetails(cluster, manageIdentities), serviceComponentFilter, hostFilter, identityFilter,
- hostsToForceKerberosOperations, requestStageContainer, new CreatePrincipalsAndKeytabsHandler(false, false,
+ hostsToForceKerberosOperations, requestStageContainer, new CreatePrincipalsAndKeytabsHandler(KerberosServerAction.OperationType.DEFAULT, false, false,
false));
}
@@ -1061,7 +1064,7 @@ public class KerberosHelperImpl implements KerberosHelper {
RequestStageContainer requestStageContainer)
throws KerberosOperationException, AmbariException {
return handleTestIdentity(cluster, getKerberosDetails(cluster, null), commandParamsStage, requestStageContainer,
- new CreatePrincipalsAndKeytabsHandler(false, false, false));
+ new CreatePrincipalsAndKeytabsHandler(KerberosServerAction.OperationType.DEFAULT, false, false, false));
}
@Override
@@ -1230,27 +1233,25 @@ public class KerberosHelperImpl implements KerberosHelper {
public List<ServiceComponentHost> getServiceComponentHostsToProcess(final Cluster cluster,
final KerberosDescriptor kerberosDescriptor,
final Map<String, ? extends Collection<String>> serviceComponentFilter,
- final Collection<String> hostFilter, Collection<String> identityFilter,
- final Command<Boolean, ServiceComponentHost> shouldProcessCommand)
+ final Collection<String> hostFilter)
throws AmbariException {
return getServiceComponentHosts(cluster, new Command<Boolean, ServiceComponentHost>() {
@Override
public Boolean invoke(ServiceComponentHost sch) throws AmbariException {
if (sch != null) {
// Check the host filter
- if ((hostFilter == null) || hostFilter.contains(sch.getHostName())) {
+ if ((hostFilter == null) || hostFilter.contains("*") || hostFilter.contains(sch.getHostName())) {
String serviceName = sch.getServiceName();
// Check the service filter
- if ((serviceComponentFilter == null) || serviceComponentFilter.containsKey(serviceName)) {
+ if ((serviceComponentFilter == null) || serviceComponentFilter.containsKey("*") || serviceComponentFilter.containsKey(serviceName)) {
KerberosServiceDescriptor serviceDescriptor = kerberosDescriptor.getService(serviceName);
if (serviceDescriptor != null) {
- Collection<String> componentFilter = (serviceComponentFilter == null) ? null : serviceComponentFilter.get(serviceName);
+ Collection<String> componentFilter = ((serviceComponentFilter == null) || serviceComponentFilter.containsKey("*")) ? null : serviceComponentFilter.get(serviceName);
- // Check the service/component filter and the shouldProcessCommand
- return (((componentFilter == null) || componentFilter.contains(sch.getServiceComponentName())) &&
- ((shouldProcessCommand == null) || shouldProcessCommand.invoke(sch)));
+ // Check the service/component filter
+ return (((componentFilter == null) || componentFilter.contains("*") || componentFilter.contains(sch.getServiceComponentName())));
}
}
}
@@ -1491,8 +1492,9 @@ public class KerberosHelperImpl implements KerberosHelper {
if (identities != null) {
for (KerberosIdentityDescriptor identity : identities) {
- // If there is no filter or the filter contains the current identity's name...
- if ((identityFilter == null) || identityFilter.contains(identity.getName())) {
+ // If there is no filter or the filter contains the current identity's path...
+ if ((identityFilter == null) || identityFilter.contains(identity.getPath())) {
+
KerberosPrincipalDescriptor principalDescriptor = identity.getPrincipalDescriptor();
String principal = null;
String principalType = null;
@@ -2030,10 +2032,7 @@ public class KerberosHelperImpl implements KerberosHelper {
cluster,
kerberosDescriptor,
serviceComponentFilter,
- hostFilter,
- identityFilter,
- arg -> true);
-
+ hostFilter);
// While iterating over all the ServiceComponentHosts find hosts that have KERBEROS_CLIENT
// components in the INSTALLED state and add them to the hostsWithValidKerberosClient Set.
@@ -3378,12 +3377,11 @@ public class KerberosHelperImpl implements KerberosHelper {
requestStageContainer.addStages(roleGraph.getStages());
}
- public void addDistributeKeytabFilesStage(Cluster cluster, List<ServiceComponentHost> serviceComponentHosts,
- String clusterHostInfoJson, String hostParamsJson,
- Map<String, String> commandParameters,
- RoleCommandOrder roleCommandOrder,
- RequestStageContainer requestStageContainer,
- Set<String> hostsWithValidKerberosClient)
+ void addDistributeKeytabFilesStage(Cluster cluster, String clusterHostInfoJson,
+ String hostParamsJson, Map<String, String> commandParameters,
+ RoleCommandOrder roleCommandOrder,
+ RequestStageContainer requestStageContainer,
+ List<String> hosts)
throws AmbariException {
Stage stage = createNewStage(requestStageContainer.getLastStageId(),
@@ -3393,20 +3391,13 @@ public class KerberosHelperImpl implements KerberosHelper {
StageUtils.getGson().toJson(commandParameters),
hostParamsJson);
- Collection<ServiceComponentHost> filteredComponents = filterServiceComponentHostsForHosts(
- new ArrayList<>(serviceComponentHosts), hostsWithValidKerberosClient);
-
- if (!filteredComponents.isEmpty()) {
- List<String> hostsToUpdate = createUniqueHostList(filteredComponents, Collections.singleton(HostState.HEALTHY));
+ if (!hosts.isEmpty()) {
Map<String, String> requestParams = new HashMap<>();
- List<RequestResourceFilter> requestResourceFilters = new ArrayList<>();
- RequestResourceFilter reqResFilter = new RequestResourceFilter(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name(), hostsToUpdate);
- requestResourceFilters.add(reqResFilter);
ActionExecutionContext actionExecContext = new ActionExecutionContext(
cluster.getClusterName(),
SET_KEYTAB,
- requestResourceFilters,
+ createRequestResourceFilters(hosts),
requestParams);
customCommandExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage,
requestParams, null);
@@ -3422,7 +3413,12 @@ public class KerberosHelperImpl implements KerberosHelper {
/**
* Send a custom command to the KERBEROS_CLIENT to check if there are missing keytabs on each hosts.
*/
- public void addCheckMissingKeytabsStage(Cluster cluster, String clusterHostInfoJson, String hostParamsJson, ServiceComponentHostServerActionEvent event, Map<String, String> commandParameters, RoleCommandOrder roleCommandOrder, RequestStageContainer requestStageContainer, List<ServiceComponentHost> serviceComponentHosts) throws AmbariException {
+ void addCheckMissingKeytabsStage(Cluster cluster, String clusterHostInfoJson,
+ String hostParamsJson, Map<String, String> commandParameters,
+ RoleCommandOrder roleCommandOrder,
+ RequestStageContainer requestStageContainer,
+ List<String> hostsToInclude)
+ throws AmbariException {
Stage stage = createNewStage(requestStageContainer.getLastStageId(),
cluster,
requestStageContainer.getId(),
@@ -3430,20 +3426,13 @@ public class KerberosHelperImpl implements KerberosHelper {
StageUtils.getGson().toJson(commandParameters),
hostParamsJson);
- Collection<ServiceComponentHost> filteredComponents = filterServiceComponentHostsForHosts(
- new ArrayList<>(serviceComponentHosts), getHostsWithValidKerberosClient(cluster));
-
- if (!filteredComponents.isEmpty()) {
- List<String> hostsToUpdate = createUniqueHostList(filteredComponents, Collections.singleton(HostState.HEALTHY));
+ if (!hostsToInclude.isEmpty()) {
Map<String, String> requestParams = new HashMap<>();
- List<RequestResourceFilter> requestResourceFilters = new ArrayList<>();
- RequestResourceFilter reqResFilter = new RequestResourceFilter(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name(), hostsToUpdate);
- requestResourceFilters.add(reqResFilter);
ActionExecutionContext actionExecContext = new ActionExecutionContext(
cluster.getClusterName(),
CHECK_KEYTABS,
- requestResourceFilters,
+ createRequestResourceFilters(hostsToInclude),
requestParams);
customCommandExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage, requestParams, null);
}
@@ -3454,32 +3443,6 @@ public class KerberosHelperImpl implements KerberosHelper {
requestStageContainer.addStages(roleGraph.getStages());
}
- /**
- * Filter out ServiceComponentHosts that are on on hosts in the specified set of host names.
- * <p/>
- * It is expected that the supplied collection is modifiable. It will be modified inplace.
- *
- * @param serviceComponentHosts a collection of ServiceComponentHost items to test
- * @param hosts a set of host names indicating valid hosts
- * @return a collection of filtered ServiceComponentHost items
- */
- private Collection<ServiceComponentHost> filterServiceComponentHostsForHosts(Collection<ServiceComponentHost> serviceComponentHosts,
- Set<String> hosts) {
-
- if ((serviceComponentHosts != null) && (hosts != null)) {
- Iterator<ServiceComponentHost> iterator = serviceComponentHosts.iterator();
- while (iterator.hasNext()) {
- ServiceComponentHost sch = iterator.next();
-
- if (!hosts.contains(sch.getHostName())) {
- iterator.remove();
- }
- }
- }
-
- return serviceComponentHosts;
- }
-
void addDisableSecurityHookStage(Cluster cluster,
String clusterHostInfoJson,
String hostParamsJson,
@@ -3677,6 +3640,13 @@ public class KerberosHelperImpl implements KerberosHelper {
requestStageContainer.setClusterHostInfo(clusterHostInfoJson);
requestStageContainer.addStages(roleGraph.getStages());
}
+
+ private List<RequestResourceFilter> createRequestResourceFilters(List<String> hostsToInclude) {
+ List<RequestResourceFilter> requestResourceFilters = new ArrayList<>();
+ RequestResourceFilter reqResFilter = new RequestResourceFilter(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name(), hostsToInclude);
+ requestResourceFilters.add(reqResFilter);
+ return requestResourceFilters;
+ }
}
/**
@@ -3746,6 +3716,8 @@ public class KerberosHelperImpl implements KerberosHelper {
roleCommandOrder, requestStageContainer);
if (kerberosDetails.manageIdentities()) {
+ List<String> hostsToInclude = calculateHosts(cluster, serviceComponentHosts, hostsWithValidKerberosClient, false);
+
commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());
// *****************************************************************
@@ -3767,8 +3739,8 @@ public class KerberosHelperImpl implements KerberosHelper {
// *****************************************************************
// Create stage to distribute keytabs
- addDistributeKeytabFilesStage(cluster, serviceComponentHosts, clusterHostInfoJson, hostParamsJson,
- commandParameters, roleCommandOrder, requestStageContainer, hostsWithValidKerberosClient);
+ addDistributeKeytabFilesStage(cluster, clusterHostInfoJson, hostParamsJson, commandParameters,
+ roleCommandOrder, requestStageContainer, hostsToInclude);
}
// *****************************************************************
@@ -3885,10 +3857,11 @@ public class KerberosHelperImpl implements KerberosHelper {
*/
private class CreatePrincipalsAndKeytabsHandler extends Handler {
/**
- * A boolean value indicating whether to create keytabs for all principals (<code>true</code>)
- * or only the ones that are missing (<code>false</code>).
+ * The type of Kerberos operation being performed.
+ *
+ * @see org.apache.ambari.server.serveraction.kerberos.KerberosServerAction.OperationType
*/
- private boolean regenerateAllKeytabs;
+ private KerberosServerAction.OperationType operationType;
/**
* A boolean value indicating whether to update service configurations (<code>true</code>)
@@ -3897,6 +3870,14 @@ public class KerberosHelperImpl implements KerberosHelper {
private boolean updateConfigurations;
/**
+ * A boolean value indicating whether to include all hosts (<code>true</code>) when setting up
+ * agent-side tasks or to select only the hosts found to be relevant (<code>false</code>).
+ * <p>
+ * This is useful if we do not know beforehand, which hosts need to be involved in the operation.
+ */
+ private boolean forceAllHosts;
+
+ /**
* A boolean value indicating whether to include Ambari server identity (<code>true</code>)
* or ignore it (<code>false</code>).
*/
@@ -3906,17 +3887,20 @@ public class KerberosHelperImpl implements KerberosHelper {
* CreatePrincipalsAndKeytabsHandler constructor to set whether this instance should be used to
* regenerate all keytabs or just the ones that have not been distributed
*
- * @param regenerateAllKeytabs A boolean value indicating whether to create keytabs for all
- * principals (<code>true</code> or only the ones that are missing
- * (<code>false</code>)
- * @param updateConfigurations A boolean value indicating whether to update service configurations
- * (<code>true</code>) or ignore any potential configuration changes
- * (<code>false</code>)
+ * @param operationType The type of Kerberos operation being performed
+ * @param updateConfigurations A boolean value indicating whether to update service configurations
+ * (<code>true</code>) or ignore any potential configuration changes
+ * @param forceAllHosts A boolean value indicating whether to include all hosts (<code>true</code>)
+ * when setting up agent-side tasks or to select only the hosts found to be
+ * relevant (<code>false</code>)
+ * @param includeAmbariIdentity A boolean value indicating whether to include Ambari server
+ * identity (<code>true</code>) or ignore it (<code>false</code>)
*/
- public CreatePrincipalsAndKeytabsHandler(boolean regenerateAllKeytabs, boolean updateConfigurations,
- boolean includeAmbariIdentity) {
- this.regenerateAllKeytabs = regenerateAllKeytabs;
+ CreatePrincipalsAndKeytabsHandler(KerberosServerAction.OperationType operationType, boolean updateConfigurations,
+ boolean forceAllHosts, boolean includeAmbariIdentity) {
+ this.operationType = operationType;
this.updateConfigurations = updateConfigurations;
+ this.forceAllHosts = forceAllHosts;
this.includeAmbariIdentity = includeAmbariIdentity;
}
@@ -3947,6 +3931,7 @@ public class KerberosHelperImpl implements KerberosHelper {
}
+ boolean processAmbariIdentity = includeAmbariIdentity;
Map<String, String> commandParameters = new HashMap<>();
commandParameters.put(KerberosServerAction.AUTHENTICATED_USER_NAME, ambariManagementController.getAuthName());
commandParameters.put(KerberosServerAction.DEFAULT_REALM, kerberosDetails.getDefaultRealm());
@@ -3955,22 +3940,29 @@ public class KerberosHelperImpl implements KerberosHelper {
}
if (serviceComponentFilter != null) {
commandParameters.put(KerberosServerAction.SERVICE_COMPONENT_FILTER, StageUtils.getGson().toJson(serviceComponentFilter));
+
+ processAmbariIdentity = serviceComponentFilter.containsKey("AMBARI") &&
+ ((serviceComponentFilter.get("AMBARI") == null) || serviceComponentFilter.get("AMBARI").contains("*") || serviceComponentFilter.get("AMBARI").contains("AMBARI_SERVER"));
}
if (hostFilter != null) {
commandParameters.put(KerberosServerAction.HOST_FILTER, StageUtils.getGson().toJson(hostFilter));
+
+ processAmbariIdentity = hostFilter.contains("*") || hostFilter.contains(StageUtils.getHostName());
}
if (identityFilter != null) {
commandParameters.put(KerberosServerAction.IDENTITY_FILTER, StageUtils.getGson().toJson(identityFilter));
}
- commandParameters.put(KerberosServerAction.REGENERATE_ALL, (regenerateAllKeytabs) ? "true" : "false");
- commandParameters.put(KerberosServerAction.INCLUDE_AMBARI_IDENTITY, (includeAmbariIdentity) ? "true" : "false");
+ commandParameters.put(KerberosServerAction.OPERATION_TYPE, (operationType == null) ? KerberosServerAction.OperationType.DEFAULT.name() : operationType.name());
+ commandParameters.put(KerberosServerAction.INCLUDE_AMBARI_IDENTITY, (processAmbariIdentity) ? "true" : "false");
if (updateConfigurations) {
commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATION_NOTE, "Updated Kerberos-related configurations");
commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATIONS, "true");
}
+ List<String> hostsToInclude = calculateHosts(cluster, serviceComponentHosts, hostsWithValidKerberosClient, forceAllHosts);
+
// *****************************************************************
// Create stage to create principals
addPrepareKerberosIdentitiesStage(cluster, clusterHostInfoJson, hostParamsJson, event,
@@ -3979,9 +3971,9 @@ public class KerberosHelperImpl implements KerberosHelper {
if (kerberosDetails.manageIdentities()) {
commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());
- if (!regenerateAllKeytabs) {
- addCheckMissingKeytabsStage(cluster, clusterHostInfoJson, hostParamsJson, event,
- commandParameters, roleCommandOrder, requestStageContainer, serviceComponentHosts);
+ if (operationType != KerberosServerAction.OperationType.RECREATE_ALL) {
+ addCheckMissingKeytabsStage(cluster, clusterHostInfoJson, hostParamsJson,
+ commandParameters, roleCommandOrder, requestStageContainer, hostsToInclude);
}
// *****************************************************************
@@ -3996,15 +3988,15 @@ public class KerberosHelperImpl implements KerberosHelper {
// *****************************************************************
// Create stage to distribute and configure keytab for Ambari server and configure JAAS
- if (includeAmbariIdentity && kerberosDetails.createAmbariPrincipal()) {
+ if (processAmbariIdentity && kerberosDetails.createAmbariPrincipal()) {
addConfigureAmbariIdentityStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters,
roleCommandOrder, requestStageContainer);
}
// *****************************************************************
// Create stage to distribute keytabs
- addDistributeKeytabFilesStage(cluster, serviceComponentHosts, clusterHostInfoJson,
- hostParamsJson, commandParameters, roleCommandOrder, requestStageContainer, hostsWithValidKerberosClient);
+ addDistributeKeytabFilesStage(cluster, clusterHostInfoJson, hostParamsJson, commandParameters,
+ roleCommandOrder, requestStageContainer, hostsToInclude);
}
if (updateConfigurations) {
@@ -4019,6 +4011,74 @@ public class KerberosHelperImpl implements KerberosHelper {
}
/**
+ * Filter out ServiceComponentHosts that are on on hosts in the specified set of host names.
+ * <p/>
+ * It is expected that the supplied collection is modifiable. It will be modified inplace.
+ *
+ * @param serviceComponentHosts a collection of ServiceComponentHost items to test
+ * @param hosts a set of host names indicating valid hosts
+ * @return a collection of filtered ServiceComponentHost items
+ */
+ private Collection<ServiceComponentHost> filterServiceComponentHostsForHosts(Collection<ServiceComponentHost> serviceComponentHosts,
+ Set<String> hosts) {
+
+ if ((serviceComponentHosts != null) && (hosts != null)) {
+ Iterator<ServiceComponentHost> iterator = serviceComponentHosts.iterator();
+ while (iterator.hasNext()) {
+ ServiceComponentHost sch = iterator.next();
+
+ if (!hosts.contains(sch.getHostName())) {
+ iterator.remove();
+ }
+ }
+ }
+
+ return serviceComponentHosts;
+ }
+
+ /**
+ * Calculate the hosts to include when issuing agent-side commands.
+ * <p>
+ * If forcing all hosts, select only the healthy hosts in the cluster else select only the healthy
+ * hosts from the set of hosts specified in the collection of relevant {@link ServiceComponentHost}.
+ *
+ * @param cluster the cluster
+ * @param serviceComponentHosts a collction of {@link ServiceComponentHost}s that are
+ * relevant to the current operation
+ * @param hostsWithValidKerberosClient the collection of hosts know to have the Kerberos client
+ * component installed
+ * @param forceAllHosts true to process all hosts from the cluster rather than use
+ * the hosts parsed from the set of {@link ServiceComponentHost}s
+ * @return a filtered list of host names
+ * @throws AmbariException
+ */
+ private List<String> calculateHosts(Cluster cluster, List<ServiceComponentHost> serviceComponentHosts, Set<String> hostsWithValidKerberosClient, boolean forceAllHosts) throws AmbariException {
+ if(forceAllHosts) {
+ List<String> hosts = new ArrayList<>();
+ Collection<Host> clusterHosts = cluster.getHosts();
+ if(!CollectionUtils.isEmpty(clusterHosts)) {
+ for(Host host: clusterHosts) {
+ if(host.getState() == HostState.HEALTHY) {
+ hosts.add(host.getHostName());
+ }
+ }
+ }
+
+ return hosts;
+ }
+ else {
+ Collection<ServiceComponentHost> filteredComponents = filterServiceComponentHostsForHosts(
+ new ArrayList<>(serviceComponentHosts), hostsWithValidKerberosClient);
+
+ if (filteredComponents.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ return createUniqueHostList(filteredComponents, Collections.singleton(HostState.HEALTHY));
+ }
+ }
+ }
+
+ /**
* DeletePrincipalsAndKeytabsHandler is an implementation of the Handler interface used to delete
* principals and keytabs throughout the cluster.
* <p/>
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
index 66bf7b3..cd23e83 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
@@ -133,7 +133,7 @@ public class RemovableIdentities {
* Remove all identities which are not used by other services or components
*/
public void remove(KerberosHelper kerberosHelper) throws AmbariException, KerberosOperationException {
- Set<String> identitiesToRemove = skipUsed().stream().map(KerberosIdentityDescriptor::getName).collect(toSet());
+ Set<String> identitiesToRemove = skipUsed().stream().map(KerberosIdentityDescriptor::getPath).collect(toSet());
if (!identitiesToRemove.isEmpty()) {
kerberosHelper.deleteIdentities(cluster, components, identitiesToRemove);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/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 4396a2b..355f515 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
@@ -217,7 +217,7 @@ public class CreateKeytabFilesServerAction extends KerberosServerAction {
return commandReport;
}
- boolean regenerateKeytabs = "true".equalsIgnoreCase(getCommandParameterValue(getCommandParameters(), REGENERATE_ALL));
+ 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
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/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 069c821..1c0853b9 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
@@ -128,7 +128,7 @@ public class CreatePrincipalsServerAction extends KerberosServerAction {
seenPrincipals.add(evaluatedPrincipal);
boolean processPrincipal;
- boolean regenerateKeytabs = "true".equalsIgnoreCase(getCommandParameterValue(getCommandParameters(), REGENERATE_ALL));
+ boolean regenerateKeytabs = getOperationType(getCommandParameters()) == OperationType.RECREATE_ALL;
if (regenerateKeytabs) {
// do not process cached identities that can be passed as is(headless identities)
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/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 c86ffa3..1b0f4fb 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
@@ -36,6 +36,7 @@ import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.utils.StageUtils;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -108,31 +109,32 @@ public abstract class KerberosServerAction extends AbstractServerAction {
*/
public static final String DATA_DIRECTORY_PREFIX = ".ambari_";
- /*
+ /**
* Kerberos action shared data entry name for the principal-to-password map
*/
private static final String PRINCIPAL_PASSWORD_MAP = "principal_password_map";
- /*
+ /**
* Kerberos action shared data entry name for the principal-to-key_number map
*/
private static final String PRINCIPAL_KEY_NUMBER_MAP = "principal_key_number_map";
- /*
- * Key used in kerberosCommandParams in ExecutionCommand for base64 encoded keytab content
- */
+ /**
+ * Key used in kerberosCommandParams in ExecutionCommand for base64 encoded keytab content
+ */
public static final String KEYTAB_CONTENT_BASE64 = "keytab_content_base64";
- /*
- * Key used in kerberosCommandParams in ExecutionCommand to indicate whether to generate key keytabs
- * for all principals ("true") or only those that are missing ("false")
- */
- public static final String REGENERATE_ALL = "regenerate_all";
+ /**
+ * Key used in kerberosCommandParams in ExecutionCommand to indicate why type of creation operation to perform.
+ *
+ * @see OperationType
+ */
+ public static final String OPERATION_TYPE = "operation_type";
- /*
- * Key used in kerberosCommandParams in ExecutionCommand to indicate whether to include Ambari server indetity
- * ("true") or ignore it ("false")
- */
+ /**
+ * Key used in kerberosCommandParams in ExecutionCommand to indicate whether to include Ambari server indetity
+ * ("true") or ignore it ("false")
+ */
public static final String INCLUDE_AMBARI_IDENTITY = "include_ambari_identity";
/**
@@ -219,6 +221,22 @@ public abstract class KerberosServerAction extends AbstractServerAction {
}
/**
+ * Given a (command parameter) Map, attempts to safely retrieve the "operation_type" property.
+ *
+ * @param commandParameters a Map containing the dictionary of data to interrogate
+ * @return an OperationType
+ */
+ protected static OperationType getOperationType(Map<String, String> commandParameters) {
+ String value = getCommandParameterValue(commandParameters, OPERATION_TYPE);
+ if(StringUtils.isEmpty(value)) {
+ return OperationType.DEFAULT;
+ }
+ else {
+ return OperationType.valueOf(value.toUpperCase());
+ }
+ }
+
+ /**
* Sets the shared principal-to-password Map used to store principals and generated password for
* use within the current request context.
*
@@ -569,4 +587,29 @@ public abstract class KerberosServerAction extends AbstractServerAction {
}
}
}
+
+ /**
+ * A Kerberos operation type
+ * <ul>
+ * <li>RECREATE_ALL - regenerate keytabs for all principals</li>
+ * <li>CREATE_MISSING - generate keytabs for only those that are missing</li>
+ * <li>DEFAULT - generate needed keytabs for new components</li>
+ * </ul>
+ */
+ public enum OperationType {
+ /**
+ * Regenerate keytabs for all principals
+ */
+ RECREATE_ALL,
+
+ /**
+ * Generate keytabs for only those that are missing
+ */
+ CREATE_MISSING,
+
+ /**
+ * Generate needed keytabs for new components
+ */
+ DEFAULT
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
index f56e946..e1f8419 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
@@ -83,8 +83,7 @@ public class PrepareDisableKerberosServerAction extends AbstractPrepareKerberosS
List<ServiceComponentHost> schToProcess = kerberosHelper.getServiceComponentHostsToProcess(cluster,
kerberosDescriptor,
getServiceComponentFilter(),
- null, identityFilter,
- sch -> true);
+ null);
Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>();
Map<String, String> commandParameters = getCommandParameters();
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/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 3ec84fa..335451f 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
@@ -92,8 +92,11 @@ public class PrepareEnableKerberosServerAction extends PrepareKerberosIdentities
}
}
+ KerberosHelper kerberosHelper = getKerberosHelper();
+ Map<String, ? extends Collection<String>> serviceComponentFilter = getServiceComponentFilter();
+ Collection<String> hostFilter = getHostFilter();
Collection<String> identityFilter = getIdentityFilter();
- List<ServiceComponentHost> schToProcess = getServiceComponentHostsToProcess(cluster, kerberosDescriptor, identityFilter);
+ List<ServiceComponentHost> schToProcess = kerberosHelper.getServiceComponentHostsToProcess(cluster, kerberosDescriptor, serviceComponentFilter, hostFilter);
String dataDirectory = getCommandParameterValue(commandParameters, DATA_DIRECTORY);
Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>();
@@ -107,7 +110,6 @@ public class PrepareEnableKerberosServerAction extends PrepareKerberosIdentities
actionLog.writeStdOut(String.format("Processing %d components", schCount));
}
- KerberosHelper kerberosHelper = getKerberosHelper();
Map<String, Set<String>> propertiesToRemove = new HashMap<>();
Map<String, Set<String>> propertiesToIgnore = new HashMap<>();
Set<String> services = cluster.getServices().keySet();
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/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 49828cb..038d1b5 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
@@ -32,8 +32,12 @@ import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.controller.KerberosHelper;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.kerberos.KerberosComponentDescriptor;
import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
+import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
+import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,11 +71,22 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
throw new AmbariException("Missing cluster object");
}
+ KerberosHelper kerberosHelper = getKerberosHelper();
+
KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster, false);
+ Map<String, String> commandParameters = getCommandParameters();
+ OperationType operationType = getOperationType(getCommandParameters());
+
+ Map<String, ? extends Collection<String>> serviceComponentFilter = getServiceComponentFilter();
+ Collection<String> hostFilter = getHostFilter();
Collection<String> identityFilter = getIdentityFilter();
- List<ServiceComponentHost> schToProcess = getServiceComponentHostsToProcess(cluster, kerberosDescriptor, identityFilter);
+ // If the operationType is default, use the getServiceComponentHostsToProcess method to determine
+ // which ServiceComponentHosts to process based on the filters. However if we are regenerating
+ // keytabs for a specific set of components, build the identity filter below so we can
+ // customized what needs to be done.
+ List<ServiceComponentHost> schToProcess = kerberosHelper.getServiceComponentHostsToProcess(cluster, kerberosDescriptor,
+ (operationType == OperationType.DEFAULT) ? serviceComponentFilter : null, hostFilter);
- Map<String, String> commandParameters = getCommandParameters();
String dataDirectory = getCommandParameterValue(commandParameters, DATA_DIRECTORY);
Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>();
@@ -84,18 +99,32 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
actionLog.writeStdOut(String.format("Processing %d components", schCount));
}
- KerberosHelper kerberosHelper = getKerberosHelper();
Set<String> services = cluster.getServices().keySet();
Map<String, Set<String>> propertiesToRemove = new HashMap<>();
Map<String, Set<String>> propertiesToIgnore = new HashMap<>();
boolean includeAmbariIdentity = "true".equalsIgnoreCase(getCommandParameterValue(commandParameters, KerberosServerAction.INCLUDE_AMBARI_IDENTITY));
+ // If we are including the Ambari identity; then ensure that if a host filter is set, do not the Ambari service identity.
+ includeAmbariIdentity &= (hostFilter == null);
+
+ if (serviceComponentFilter != null) {
+ // If we are including the Ambari identity; then ensure that if a service/component filter is set,
+ // it contains the AMBARI/AMBARI_SERVER component; else do not include the Ambari service identity.
+ includeAmbariIdentity &= (serviceComponentFilter.get("AMBARI") != null) && serviceComponentFilter.get("AMBARI").contains("AMBARI_SERVER");
+
+ if((operationType != OperationType.DEFAULT)) {
+ // Update the identity filter, if necessary
+ identityFilter = updateIdentityFilter(kerberosDescriptor, identityFilter, serviceComponentFilter);
+ }
+ }
+
// Calculate the current host-specific configurations. These will be used to replace
// variables within the Kerberos descriptor data
Map<String, Map<String, String>> configurations = kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor, false, false);
processServiceComponentHosts(cluster, kerberosDescriptor, schToProcess, identityFilter, dataDirectory,
- configurations, kerberosConfigurations, includeAmbariIdentity, propertiesToIgnore, !CollectionUtils.isEmpty(getHostFilter()));
+ configurations, kerberosConfigurations, includeAmbariIdentity, propertiesToIgnore,
+ hostFilter != null);
kerberosHelper.applyStackAdvisorUpdates(cluster, services, configurations, kerberosConfigurations,
propertiesToIgnore, propertiesToRemove, true);
@@ -119,35 +148,6 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
}
/**
- * Calls {@link KerberosHelper#getServiceComponentHostsToProcess(Cluster, KerberosDescriptor, Map, Collection, Collection, KerberosHelper.Command)}
- * with no filter on ServiceComponentHosts
- * <p/>
- * The <code>shouldProcessCommand</code> implementation passed to KerberosHelper#getServiceComponentHostsToProcess
- * always returns true, indicating to process all ServiceComponentHosts.
- *
- * @param cluster the cluster
- * @param kerberosDescriptor the current Kerberos descriptor
- * @param identityFilter a list of identities to include, or all if null @return the list of ServiceComponentHosts to process
- * @throws AmbariException
- * @see KerberosHelper#getServiceComponentHostsToProcess(Cluster, KerberosDescriptor, Map, Collection, Collection, KerberosHelper.Command)
- */
- protected List<ServiceComponentHost> getServiceComponentHostsToProcess(Cluster cluster,
- KerberosDescriptor kerberosDescriptor,
- Collection<String> identityFilter)
- throws AmbariException {
- return getKerberosHelper().getServiceComponentHostsToProcess(cluster,
- kerberosDescriptor,
- getServiceComponentFilter(),
- getHostFilter(), identityFilter,
- new KerberosHelper.Command<Boolean, ServiceComponentHost>() {
- @Override
- public Boolean invoke(ServiceComponentHost sch) throws AmbariException {
- return true;
- }
- });
- }
-
- /**
* Calls {@link KerberosHelper#getKerberosDescriptor(Cluster, boolean)}
*
* @param cluster cluster instance
@@ -200,5 +200,81 @@ public class PrepareKerberosIdentitiesServerAction extends AbstractPrepareKerber
calculatedConfiguration, kerberosConfigurations, includePreconfiguredData);
}
}
+
+ /**
+ * Iterate through the identities in the Kerberos descriptor to find the relevant identities to
+ * add to the identity filter.
+ * <p>
+ * The set of identities to include in the filter are determined by whether they are explicit
+ * identities set in a component or service in the supplied service/component filter.
+ *
+ * @param kerberosDescriptor the Kerberos descriptor
+ * @param identityFilter the existing identity filter
+ * @param serviceComponentFilter the service/component filter
+ * @return a new collection of paths (including any existing paths) to act as the updated identity filter
+ */
+ private Collection<String> updateIdentityFilter(KerberosDescriptor kerberosDescriptor,
+ Collection<String> identityFilter,
+ Map<String, ? extends Collection<String>> serviceComponentFilter) {
+
+ Set<String> updatedFilter = (identityFilter == null) ? new HashSet<>() : new HashSet<>(identityFilter);
+
+ Map<String, KerberosServiceDescriptor> serviceDescriptors = kerberosDescriptor.getServices();
+
+ if (serviceDescriptors != null) {
+ for (KerberosServiceDescriptor serviceDescriptor : serviceDescriptors.values()) {
+ String serviceName = serviceDescriptor.getName();
+
+ if (serviceComponentFilter.containsKey("*") || serviceComponentFilter.containsKey(serviceName)) {
+ Collection<String> componentFilter = serviceComponentFilter.get(serviceName);
+ boolean anyComponent = ((componentFilter == null) || componentFilter.contains("*"));
+
+ // Only include the service-wide identities if the component filter is null contains "*", which indicates
+ // that all component for the given service are to be processed.
+ if (anyComponent) {
+ addIdentitiesToFilter(serviceDescriptor.getIdentities(), updatedFilter, true);
+ }
+
+ Map<String, KerberosComponentDescriptor> componentDescriptors = serviceDescriptor.getComponents();
+ if (componentDescriptors != null) {
+ for (KerberosComponentDescriptor componentDescriptor : componentDescriptors.values()) {
+ String componentName = componentDescriptor.getName();
+ if (anyComponent || (componentFilter.contains(componentName))) {
+ addIdentitiesToFilter(componentDescriptor.getIdentities(), updatedFilter, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return updatedFilter;
+ }
+
+ /**
+ * Add the path of each identity in the collection of identities to the supplied identity filter
+ * if that identity is not a reference to another identity or if references are allowed.
+ * @param identityDescriptors the collection of identity descriptors to process
+ * @param identityFilter the identity filter to modify
+ * @param skipReferences
+ */
+ private void addIdentitiesToFilter(List<KerberosIdentityDescriptor> identityDescriptors,
+ Collection<String> identityFilter, boolean skipReferences) {
+ if (!CollectionUtils.isEmpty(identityDescriptors)) {
+ for (KerberosIdentityDescriptor identityDescriptor : identityDescriptors) {
+ if (!skipReferences || !identityDescriptor.isReference()) {
+ String identityPath = identityDescriptor.getPath();
+
+ if (!StringUtils.isEmpty(identityPath)) {
+ identityFilter.add(identityPath);
+
+ // Find and add the references TO this identity to ensure the new/updated keytab file is
+ // sent to the appropriate host(s)
+ addIdentitiesToFilter(identityDescriptor.findReferences(), identityFilter, false);
+ }
+ }
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
index b496942..3a1eb4a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
@@ -259,6 +259,31 @@ public abstract class AbstractKerberosDescriptor {
}
/**
+ * Calculate the path to this identity descriptor for logging purposes.
+ * Examples:
+ * <ul>
+ * <li>/</li>
+ * <li>/SERVICE</li>
+ * <li>/SERVICE/COMPONENT</li>
+ * <li>/SERVICE/COMPONENT/identity_name</li>
+ * </ul>
+ *
+ * @return a path
+ */
+ public String getPath() {
+ //
+ StringBuilder path = new StringBuilder();
+ AbstractKerberosDescriptor current = this;
+ while (current != null && (current.getName() != null)) {
+ path.insert(0, current.getName());
+ path.insert(0, '/');
+ current = current.getParent();
+ }
+
+ return path.toString();
+ }
+
+ /**
* An enumeration of the different Kerberos (sub)descriptors for internal use.
*/
public enum Type {
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
index 9ddb941..73550f4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
@@ -862,22 +862,9 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
referencedIdentity = getReferencedIdentityDescriptor(identity.getName());
if(referencedIdentity != null) {
- // Calculate the path to this identity descriptor for logging purposes.
- // Examples:
- // /
- // /SERVICE
- // /SERVICE/COMPONENT
- StringBuilder path = new StringBuilder();
- AbstractKerberosDescriptor parent = identity.getParent();
- while(parent != null && (parent.getName() != null)) {
- path.insert(0, parent.getName());
- path.insert(0, '/');
- parent = parent.getParent();
- }
-
// Log this since it is deprecated...
LOG.warn("Referenced identities should be declared using the identity's \"reference\" attribute, not the identity's \"name\" attribute." +
- " This is a deprecated feature. Problems may occur in the future unless this is corrected: {}:{}", path, identity.getName());
+ " This is a deprecated feature. Problems may occur in the future unless this is corrected: {}:{}", identity.getPath(), identity.getName());
}
}
} catch (AmbariException e) {
@@ -896,6 +883,9 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
} else {
dereferencedIdentity = new KerberosIdentityDescriptor(identity.toMap());
}
+
+ // Force the path for this identity descriptor to be the same as the original identity descriptor's.
+ dereferencedIdentity.setPath(identity.getPath());
}
return dereferencedIdentity;
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
index ef45343..200a069 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
@@ -17,10 +17,15 @@
*/
package org.apache.ambari.server.state.kerberos;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.Map;
import org.apache.ambari.server.collections.Predicate;
import org.apache.ambari.server.collections.PredicateUtils;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
import com.google.common.base.Optional;
@@ -94,6 +99,8 @@ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor {
*/
private Predicate when = null;
+ private String path = null;
+
/**
* Creates a new KerberosIdentityDescriptor
*
@@ -157,6 +164,47 @@ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor {
}
/**
+ * Gets the absolute path to the referenced Kerberos identity definition
+ *
+ * @return the path to the referenced Kerberos identity definition or <code>null</code> if not set
+ */
+ public String getReferenceAbsolutePath() {
+ String absolutePath;
+ if(StringUtils.isEmpty(reference)) {
+ absolutePath = getName();
+ }
+ else {
+ absolutePath = reference;
+ }
+
+ if(!StringUtils.isEmpty(absolutePath) && !absolutePath.startsWith("/")) {
+ String path = getPath();
+ if(path == null) {
+ path = "";
+ }
+
+ if(absolutePath.startsWith("..")) {
+ AbstractKerberosDescriptor parent = getParent();
+ if(parent != null) {
+ parent = parent.getParent();
+
+ if(parent != null) {
+ absolutePath = absolutePath.replace("..", parent.getPath());
+ }
+ }
+ }
+ else if(absolutePath.startsWith(".")) {
+ AbstractKerberosDescriptor parent = getParent();
+ if (parent != null) {
+ absolutePath = absolutePath.replace(".", parent.getPath());
+ }
+ }
+ }
+
+ return absolutePath;
+ }
+
+ /**
* Sets the path to the referenced Kerberos identity definition
*
* @param reference the path to the referenced Kerberos identity definition or <code>null</code>
@@ -356,6 +404,59 @@ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor {
}
}
+ /**
+ * Determines whether this {@link KerberosIdentityDescriptor} indicates it is a refrence to some
+ * other {@link KerberosIdentityDescriptor}.
+ * <p>
+ * A KerberosIdentityDescriptor is a reference if it's <code>reference</code> attibute is set
+ * or if (for backwards compatibility), its name indicates a path. For exmaple:
+ * <ul>
+ * <li><code>SERVICE/COMPONENT/identitiy_name</code></li>
+ * <li><code>/identity_name</code></li>
+ * <li><code>./identity_name</code></li>
+ * </ul>
+ *
+ * @return true if this {@link KerberosIdentityDescriptor} indicates a reference; otherwise false
+ */
+ public boolean isReference() {
+ String name = getName();
+ return !StringUtils.isEmpty(reference) ||
+ (!StringUtils.isEmpty(name) && (name.startsWith("/") || name.startsWith("./")));
+ }
+
+ /**
+ * Calculate the path to this identity descriptor for logging purposes.
+ * Examples:
+ * /
+ * /SERVICE
+ * /SERVICE/COMPONENT
+ * /SERVICE/COMPONENT/identity_name
+ * <p>
+ * This implementation calculates and caches the path if the path has not been previously set.
+ *
+ * @return a path
+ */
+ @Override
+ public String getPath() {
+ if (path == null) {
+ path = super.getPath();
+ }
+
+ return path;
+ }
+
+ /**
+ * Explicitly set the path to this {@link KerberosIdentityDescriptor}.
+ * <p>
+ * This is useful when creating detached identity descriptors while dereferencing identity references
+ * so that the path information is not lost.
+ *
+ * @param path a path
+ */
+ void setPath(String path) {
+ this.path = path;
+ }
+
@Override
public int hashCode() {
return super.hashCode() +
@@ -406,4 +507,63 @@ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor {
return false;
}
}
+
+ /**
+ * Find all of the {@link KerberosIdentityDescriptor}s that reference this {@link KerberosIdentityDescriptor}
+ *
+ * @return a list of {@link KerberosIdentityDescriptor}s
+ */
+ public List<KerberosIdentityDescriptor> findReferences() {
+ AbstractKerberosDescriptor root = getRoot();
+ if(root instanceof AbstractKerberosDescriptorContainer) {
+ return findIdentityReferences((AbstractKerberosDescriptorContainer)root, getPath());
+ }
+ else {
+ return null;
+ }
+ }
+
+ /**
+ * Given a root, recursively traverse the tree of {@link AbstractKerberosDescriptorContainer}s looking for
+ * {@link KerberosIdentityDescriptor}s that declare the given path as the referenced Kerberos identity.
+ *
+ * @param root the starting point
+ * @param path the path to the referenced {@link KerberosIdentityDescriptor} in the {@link KerberosDescriptor}
+ * @return a list of {@link KerberosIdentityDescriptor}s
+ */
+ private List<KerberosIdentityDescriptor> findIdentityReferences(AbstractKerberosDescriptorContainer root, String path) {
+ if (root == null) {
+ return null;
+ }
+
+ List<KerberosIdentityDescriptor> references = new ArrayList<>();
+
+ // Process the KerberosIdentityDescriptors found in this node.
+ List<KerberosIdentityDescriptor> identityDescriptors = root.getIdentities();
+ if (identityDescriptors != null) {
+ for (KerberosIdentityDescriptor identityDescriptor : identityDescriptors) {
+ if (identityDescriptor.isReference()) {
+ String reference = identityDescriptor.getReferenceAbsolutePath();
+
+ if (!StringUtils.isEmpty(reference) && path.equals(reference)) {
+ references.add(identityDescriptor);
+ }
+ }
+ }
+ }
+
+ // Process the children of the node
+ Collection<? extends AbstractKerberosDescriptorContainer> children = root.getChildContainers();
+ if(!CollectionUtils.isEmpty(children)) {
+ for (AbstractKerberosDescriptorContainer child : children) {
+ Collection<KerberosIdentityDescriptor> childReferences = findIdentityReferences(child, path);
+ if (!CollectionUtils.isEmpty(childReferences)) {
+ // If references were found in the current child, add them to this node's list of references.
+ references.addAll(childReferences);
+ }
+ }
+ }
+
+ return references;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
index 60d7fd9..7ed52d2 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
@@ -1441,11 +1441,6 @@ public class KerberosHelperTest extends EasyMockSupport {
.andReturn(Collections.singletonList(schKerberosClient))
.once();
- final Clusters clusters = injector.getInstance(Clusters.class);
- expect(clusters.getHost("host1"))
- .andReturn(host)
- .once();
-
final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null))
.andReturn(Collections.emptyMap())
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
index 663934f..2518da9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/utilities/KerberosIdentityCleanerTest.java
@@ -77,7 +77,7 @@ public class KerberosIdentityCleanerTest extends EasyMockSupport {
@Test
public void removesAllKerberosIdentitesOfComponentAfterComponentWasUninstalled() throws Exception {
installComponent(OOZIE, OOZIE_SERVER, HOST);
- kerberosHelper.deleteIdentities(cluster, singletonList(new Component(HOST, OOZIE, OOZIE_SERVER)), newHashSet("oozie_server1", "oozie_server2"));
+ kerberosHelper.deleteIdentities(cluster, singletonList(new Component(HOST, OOZIE, OOZIE_SERVER)), newHashSet("/OOZIE/OOZIE_SERVER/oozie_server1", "/OOZIE/OOZIE_SERVER/oozie_server2"));
expectLastCall().once();
replayAll();
uninstallComponent(OOZIE, OOZIE_SERVER, HOST);
@@ -95,7 +95,7 @@ public class KerberosIdentityCleanerTest extends EasyMockSupport {
public void skipsRemovingIdentityThatIsSharedByPrincipalName() throws Exception {
installComponent(OOZIE, OOZIE_SERVER, HOST);
installComponent(OOZIE_2, OOZIE_SERVER_2, HOST);
- kerberosHelper.deleteIdentities(cluster, singletonList(new Component(HOST, OOZIE, OOZIE_SERVER)), newHashSet("oozie_server1"));
+ kerberosHelper.deleteIdentities(cluster, singletonList(new Component(HOST, OOZIE, OOZIE_SERVER)), newHashSet("/OOZIE/OOZIE_SERVER/oozie_server1"));
expectLastCall().once();
replayAll();
uninstallComponent(OOZIE, OOZIE_SERVER, HOST);
@@ -106,7 +106,7 @@ public class KerberosIdentityCleanerTest extends EasyMockSupport {
public void skipsRemovingIdentityThatIsSharedByKeyTabFilePath() throws Exception {
installComponent(YARN, RESOURCE_MANAGER, HOST);
installComponent(YARN_2, RESOURCE_MANAGER_2, HOST);
- kerberosHelper.deleteIdentities(cluster, singletonList(new Component(HOST, YARN, RESOURCE_MANAGER)), newHashSet("rm_unique"));
+ kerberosHelper.deleteIdentities(cluster, singletonList(new Component(HOST, YARN, RESOURCE_MANAGER)), newHashSet("/YARN/RESOURCE_MANAGER/rm_unique"));
expectLastCall().once();
replayAll();
uninstallComponent(YARN, RESOURCE_MANAGER, HOST);
@@ -133,7 +133,7 @@ public class KerberosIdentityCleanerTest extends EasyMockSupport {
@Test
public void removesServiceIdentitiesSkipComponentIdentitiesAfterServiceWasUninstalled() throws Exception {
installComponent(OOZIE, OOZIE_SERVER, HOST);
- kerberosHelper.deleteIdentities(cluster, hdfsComponents(), newHashSet("hdfs-service"));
+ kerberosHelper.deleteIdentities(cluster, hdfsComponents(), newHashSet("/HDFS/hdfs-service"));
expectLastCall().once();
replayAll();
uninstallService(HDFS, hdfsComponents());
http://git-wip-us.apache.org/repos/asf/ambari/blob/5af1e539/ambari-server/src/test/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorTest.java
index d6bef02..079096d 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorTest.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -79,6 +80,9 @@ public class KerberosDescriptorTest {
" {" +
" \"name\": \"service1_spnego\"," +
" \"reference\": \"/spnego\"" +
+ " }," +
+ " {" +
+ " \"name\": \"service1_identity\"" +
" }" +
" ]," +
" \"name\": \"SERVICE1\"" +
@@ -87,6 +91,39 @@ public class KerberosDescriptorTest {
" \"identities\": [" +
" {" +
" \"name\": \"/spnego\"" +
+ " }," +
+ " {" +
+ " \"name\": \"service2_identity\"" +
+ " }" +
+ " ]," +
+ " \"components\": [" +
+ " {" +
+ " \"identities\": [" +
+ " {" +
+ " \"name\": \"component1_identity\"" +
+ " }," +
+ " {" +
+ " \"name\": \"service2_component1_service1_identity\"," +
+ " \"reference\": \"/SERVICE1/service1_identity\"" +
+ " }," +
+ " {" +
+ " \"name\": \"service2_component1_component1_identity\"," +
+ " \"reference\": \"./component1_identity\"" +
+ " }," +
+ " {" +
+ " \"name\": \"service2_component1_service2_identity\"," +
+ " \"reference\": \"../service2_identity\"" +
+ " }" +
+ " ]," +
+ " \"name\": \"COMPONENT21\"" +
+ " }," +
+ " {" +
+ " \"identities\": [" +
+ " {" +
+ " \"name\": \"component2_identity\"" +
+ " }" +
+ " ]," +
+ " \"name\": \"COMPONENT22\"" +
" }" +
" ]," +
" \"name\": \"SERVICE2\"" +
@@ -547,15 +584,118 @@ public class KerberosDescriptorTest {
// Reference is determined using the "reference" attribute
serviceDescriptor = kerberosDescriptor.getService("SERVICE1");
identities = serviceDescriptor.getIdentities(true, null);
- Assert.assertEquals(1, identities.size());
- Assert.assertEquals("service1_spnego", identities.get(0).getName());
- Assert.assertEquals("/spnego", identities.get(0).getReference());
+ Assert.assertEquals(2, identities.size());
+ for (KerberosIdentityDescriptor identity : identities) {
+ if (identity.isReference()) {
+ Assert.assertEquals("service1_spnego", identity.getName());
+ Assert.assertEquals("/spnego", identity.getReference());
+ } else {
+ Assert.assertEquals("service1_identity", identity.getName());
+ Assert.assertNull(identity.getReference());
+ }
+ }
+
+ Assert.assertEquals("service1_identity", identities.get(1).getName());
+ Assert.assertNull(identities.get(1).getReference());
// Reference is determined using the "name" attribute
serviceDescriptor = kerberosDescriptor.getService("SERVICE2");
identities = serviceDescriptor.getIdentities(true, null);
+ Assert.assertEquals(2, identities.size());
+ for (KerberosIdentityDescriptor identity : identities) {
+ if (identity.isReference()) {
+ Assert.assertEquals("/spnego", identity.getName());
+ Assert.assertNull(identity.getReference());
+ } else {
+ Assert.assertEquals("service2_identity", identity.getName());
+ Assert.assertNull(identity.getReference());
+ }
+ }
+ }
+
+ @Test
+ public void testGetPath() throws Exception {
+ KerberosDescriptor kerberosDescriptor;
+ KerberosServiceDescriptor serviceDescriptor;
+ List<KerberosIdentityDescriptor> identities;
+
+ kerberosDescriptor = KERBEROS_DESCRIPTOR_FACTORY.createInstance(JSON_VALUE);
+
+ serviceDescriptor = kerberosDescriptor.getService("SERVICE_NAME");
+ identities = serviceDescriptor.getIdentities(false, null);
+ Assert.assertEquals(1, identities.size());
+ Assert.assertEquals("/SERVICE_NAME/identity_1", identities.get(0).getPath());
+
+ KerberosComponentDescriptor componentDescriptor = serviceDescriptor.getComponent("COMPONENT_NAME");
+ identities = componentDescriptor.getIdentities(false, null);
Assert.assertEquals(1, identities.size());
- Assert.assertEquals("/spnego", identities.get(0).getName());
- Assert.assertNull(identities.get(0).getReference());
+ Assert.assertEquals("/SERVICE_NAME/COMPONENT_NAME/identity_1", identities.get(0).getPath());
+
+
+ kerberosDescriptor = KERBEROS_DESCRIPTOR_FACTORY.createInstance(JSON_VALUE_IDENTITY_REFERENCES);
+
+ serviceDescriptor = kerberosDescriptor.getService("SERVICE1");
+ identities = serviceDescriptor.getIdentities(true, null);
+ Assert.assertEquals(2, identities.size());
+ Assert.assertEquals("/SERVICE1/service1_spnego", identities.get(0).getPath());
+ Assert.assertEquals("/SERVICE1/service1_identity", identities.get(1).getPath());
+ }
+
+ @Test
+ public void testGetReferences() throws Exception {
+ KerberosDescriptor kerberosDescriptor = KERBEROS_DESCRIPTOR_FACTORY.createInstance(JSON_VALUE_IDENTITY_REFERENCES);
+ KerberosIdentityDescriptor identity;
+ List<KerberosIdentityDescriptor> references;
+ Set<String> paths;
+
+ // Find all references to /spnego
+ identity = kerberosDescriptor.getIdentity("spnego");
+ references = identity.findReferences();
+
+ Assert.assertNotNull(references);
+ Assert.assertEquals(2, references.size());
+
+ paths = collectPaths(references);
+ Assert.assertTrue(paths.contains("/SERVICE1/service1_spnego"));
+ Assert.assertTrue(paths.contains("/SERVICE2//spnego"));
+
+ // Find all references to /SERVICE1/service1_identity
+ identity = kerberosDescriptor.getService("SERVICE1").getIdentity("service1_identity");
+ references = identity.findReferences();
+
+ Assert.assertNotNull(references);
+ Assert.assertEquals(1, references.size());
+
+ paths = collectPaths(references);
+ Assert.assertTrue(paths.contains("/SERVICE2/COMPONENT21/service2_component1_service1_identity"));
+
+ // Find all references to /SERVICE2/COMPONENT21/component1_identity (testing ./)
+ identity = kerberosDescriptor.getService("SERVICE2").getComponent("COMPONENT21").getIdentity("component1_identity");
+ references = identity.findReferences();
+
+ Assert.assertNotNull(references);
+ Assert.assertEquals(1, references.size());
+
+ paths = collectPaths(references);
+ Assert.assertTrue(paths.contains("/SERVICE2/COMPONENT21/service2_component1_component1_identity"));
+
+ // Find all references to /SERVICE2/component2_identity (testing ../)
+ identity = kerberosDescriptor.getService("SERVICE2").getIdentity("service2_identity");
+ references = identity.findReferences();
+
+ Assert.assertNotNull(references);
+ Assert.assertEquals(1, references.size());
+
+ paths = collectPaths(references);
+ Assert.assertTrue(paths.contains("/SERVICE2/COMPONENT21/service2_component1_service2_identity"));
+ }
+
+ private Set<String> collectPaths(List<KerberosIdentityDescriptor> identityDescriptors) {
+ Set<String> paths = new HashSet<>();
+ for (KerberosIdentityDescriptor identityDescriptor : identityDescriptors) {
+ paths.add(identityDescriptor.getPath());
+ }
+ return paths;
}
+
}
\ No newline at end of file