You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2015/10/07 17:17:56 UTC
[2/2] ambari git commit: AMBARI-13292. Kerberos: Retain KDC admin
credentials (rlevas)
AMBARI-13292. Kerberos: Retain KDC admin credentials (rlevas)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/44c26466
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/44c26466
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/44c26466
Branch: refs/heads/trunk
Commit: 44c2646668f29c7e79c8ffb3ff290bed1f53ed0d
Parents: 78e49db
Author: Robert Levas <rl...@hortonworks.com>
Authored: Wed Oct 7 08:17:41 2015 -0700
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Wed Oct 7 08:17:45 2015 -0700
----------------------------------------------------------------------
.../AmbariManagementControllerImpl.java | 12 +-
.../server/controller/KerberosHelper.java | 33 +-
.../server/controller/KerberosHelperImpl.java | 183 +++--------
.../kerberos/ADKerberosOperationHandler.java | 28 +-
.../kerberos/KerberosCredential.java | 303 -------------------
.../kerberos/KerberosOperationHandler.java | 79 +++--
.../kerberos/KerberosServerAction.java | 3 +-
.../kerberos/MITKerberosOperationHandler.java | 182 +++++------
.../server/controller/KerberosHelperTest.java | 196 +++++++-----
.../ADKerberosOperationHandlerTest.java | 19 +-
.../kerberos/KerberosCredentialTest.java | 103 -------
.../kerberos/KerberosOperationHandlerTest.java | 31 +-
.../kerberos/KerberosServerActionTest.java | 10 +-
.../MITKerberosOperationHandlerTest.java | 25 +-
14 files changed, 343 insertions(+), 864 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 436fa3c..de0ae28 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -114,12 +114,12 @@ import org.apache.ambari.server.security.authorization.AuthorizationHelper;
import org.apache.ambari.server.security.authorization.Group;
import org.apache.ambari.server.security.authorization.User;
import org.apache.ambari.server.security.authorization.Users;
+import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.security.encryption.CredentialStoreService;
import org.apache.ambari.server.security.encryption.CredentialStoreType;
import org.apache.ambari.server.security.ldap.AmbariLdapDataPopulator;
import org.apache.ambari.server.security.ldap.LdapBatchDto;
import org.apache.ambari.server.security.ldap.LdapSyncDto;
-import org.apache.ambari.server.serveraction.kerberos.KerberosCredential;
import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
import org.apache.ambari.server.serveraction.kerberos.KerberosOperationException;
import org.apache.ambari.server.stageplanner.RoleGraph;
@@ -1266,9 +1266,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
Map<String, Object> sessionAttributes = request.getSessionAttributes();
- // TODO: Create REST API entry point to securely set credentials in the CredentialProvider then
- // TODO: remove this block to _clean_ the session attributes and store any KDC administrator
- // TODO: credentials in the secure credential provider facility.
+ // TODO: Once the UI uses the Credential Resource API, remove this block to _clean_ the
+ // TODO: session attributes and store any KDC administrator credentials in the secure
+ // TODO: credential provider facility.
// For now, to keep things backwards compatible, get and remove the KDC administrator credentials
// from the session attributes and store them in the CredentialsProvider. The KDC administrator
// credentials are prefixed with kdc_admin/. The following attributes are expected, if setting
@@ -1300,7 +1300,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
if(principal != null) {
// The KDC admin principal exists... set the credentials in the credentials store
- kerberosHelper.setKDCCredentials(new KerberosCredential(principal, password, null));
+ credentialStoreService.setCredential(cluster.getClusterName(),
+ KerberosHelper.KDC_ADMINISTRATOR_CREDENTIAL_ALIAS,
+ new PrincipalKeyCredential(principal, password), CredentialStoreType.TEMPORARY);
}
sessionAttributes = cleanedSessionAttributes;
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/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 c39485b..f87fb04 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
@@ -20,8 +20,8 @@ package org.apache.ambari.server.controller;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.controller.internal.RequestStageContainer;
+import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.serveraction.kerberos.KerberosAdminAuthenticationException;
-import org.apache.ambari.server.serveraction.kerberos.KerberosCredential;
import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileWriter;
import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
import org.apache.ambari.server.serveraction.kerberos.KerberosMissingAdminCredentialsException;
@@ -52,6 +52,10 @@ public interface KerberosHelper {
* name of property which states whether kerberos is enabled
*/
String SECURITY_ENABLED_PROPERTY_NAME = "security_enabled";
+ /**
+ * The alias to assign to the KDC administrator credential Keystore item
+ */
+ String KDC_ADMINISTRATOR_CREDENTIAL_ALIAS = "kdc.admin.credential";
/**
* Toggles Kerberos security to enable it or remove it depending on the state of the cluster.
@@ -417,33 +421,14 @@ public interface KerberosHelper {
throws AmbariException;
/**
- * Sets the KDC administrator credentials.
- * <p/>
- * It is up to the implementation to determine how to store
- * these credentials and for how long.
- *
- * @param credentials the KDC administrator credentials
- * @throws AmbariException if an error occurs while storing the credentials
- */
- void setKDCCredentials(KerberosCredential credentials) throws AmbariException;
-
- /**
- * Removes the previously set KDC administrator credentials.
- *
- * @throws AmbariException if an error occurs while removing the credentials
- * @see KerberosHelper#setKDCCredentials(KerberosCredential)
- */
- void removeKDCCredentials() throws AmbariException;
-
- /**
- * Gets the previously stored KDC administrator credentials.
+ * Sets the previously stored KDC administrator credentials.
*
- * @return a KerberosCredential or null, if the KDC administrator credentials have not be set or
+ * @return a PrincipalKeyCredential or null, if the KDC administrator credentials have not be set or
* have been removed
* @throws AmbariException if an error occurs while retrieving the credentials
- * @see KerberosHelper#setKDCCredentials(KerberosCredential)
+ * @param clusterName
*/
- KerberosCredential getKDCCredentials() throws AmbariException;
+ PrincipalKeyCredential getKDCAdministratorCredentials(String clusterName) throws AmbariException;
/**
* Command to invoke against the Ambari backend.
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/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 d428174..dbb59bd 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
@@ -31,7 +31,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -63,8 +62,7 @@ import org.apache.ambari.server.metadata.RoleCommandOrder;
import org.apache.ambari.server.security.SecurePasswordHelper;
import org.apache.ambari.server.security.credential.Credential;
import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
-import org.apache.ambari.server.security.encryption.InMemoryCredentialStore;
-import org.apache.ambari.server.security.encryption.MasterKeyServiceImpl;
+import org.apache.ambari.server.security.encryption.CredentialStoreService;
import org.apache.ambari.server.serveraction.ServerAction;
import org.apache.ambari.server.serveraction.kerberos.CleanupServerAction;
import org.apache.ambari.server.serveraction.kerberos.CreateKeytabFilesServerAction;
@@ -73,7 +71,6 @@ import org.apache.ambari.server.serveraction.kerberos.DestroyPrincipalsServerAct
import org.apache.ambari.server.serveraction.kerberos.FinalizeKerberosServerAction;
import org.apache.ambari.server.serveraction.kerberos.KDCType;
import org.apache.ambari.server.serveraction.kerberos.KerberosAdminAuthenticationException;
-import org.apache.ambari.server.serveraction.kerberos.KerberosCredential;
import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileWriter;
import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileWriterFactory;
import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
@@ -131,17 +128,6 @@ public class KerberosHelperImpl implements KerberosHelper {
private static final Logger LOG = LoggerFactory.getLogger(KerberosHelperImpl.class);
/**
- * The alias to assign to the KDC administrator credential Keystore item
- */
- public static final String KDC_ADMINISTRATOR_CREDENTIAL_ALIAS = "kdc_admin";
-
- /**
- * The default length of time (in minutes) to store the KDC administrator credentials before
- * automatically removing them.
- */
- private static final long DEFAULT_KDC_ADMINISTRATOR_CREDENTIALS_RETENTION_MINUTES = 90;
-
- /**
* Regular expression pattern used to parse auth_to_local property specifications into the following
* parts:
* <ul>
@@ -198,24 +184,17 @@ public class KerberosHelperImpl implements KerberosHelper {
private SecurePasswordHelper securePasswordHelper;
/**
- * Used to get kerberos descriptors associated with the cluster or stack.
- * Currently not available via injection.
+ * The secure storage facility to use to store KDC administrator credential.
*/
- private static ClusterController clusterController = null;
+ @Inject
+ private CredentialStoreService credentialStoreService;
/**
- * The secure storage facility to use to store KDC administrator credentials. This implementation
- * is uses an InMemoryCredentialStore to keep the credentials in memory rather than
- * storing them on disk.
+ * Used to get kerberos descriptors associated with the cluster or stack.
+ * Currently not available via injection.
*/
- private final InMemoryCredentialStore kdcCredentialStoreService;
+ private static ClusterController clusterController = null;
- /**
- * Default KerberosHelperImpl constructor
- */
- public KerberosHelperImpl() {
- kdcCredentialStoreService = new InMemoryCredentialStore(DEFAULT_KDC_ADMINISTRATOR_CREDENTIALS_RETENTION_MINUTES, TimeUnit.MINUTES, true);
- }
@Override
public RequestStageContainer toggleKerberos(Cluster cluster, SecurityType securityType,
@@ -442,12 +421,12 @@ public class KerberosHelperImpl implements KerberosHelper {
for (String authToLocalProperty : authToLocalPropertiesToSet) {
Matcher m = AUTH_TO_LOCAL_PROPERTY_SPECIFICATION_PATTERN.matcher(authToLocalProperty);
- if(m.matches()) {
+ if (m.matches()) {
AuthToLocalBuilder builder = authToLocalBuilder.copy();
String configType = m.group(1);
String propertyName = m.group(2);
- if(configType == null) {
+ if (configType == null) {
configType = "";
}
@@ -916,62 +895,23 @@ public class KerberosHelperImpl implements KerberosHelper {
}
/**
- * Sets the KDC administrator credentials.
- * <p/>
- * This implementation stores the credentials in a secure CredentialStoreService implementation and
- * sets a timer to remove the stored credentials after the retention period expires.
- * <p/>
- * If existing credentials are stored when setting new credentials, the previously stored data will
- * be cleared out. Each time credentials are set, a new master key is generated and used to encrypt
- * the data.
- *
- * @param credentials the KDC administrator credentials
- * @throws AmbariException if an error occurs while storing the credentials
- */
- @Override
- public void setKDCCredentials(KerberosCredential credentials) throws AmbariException {
- kdcCredentialStoreService.removeCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS);
-
- if (credentials != null) {
- kdcCredentialStoreService.setMasterKeyService(new MasterKeyServiceImpl(securePasswordHelper.createSecurePassword()));
- kdcCredentialStoreService.addCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS, new PrincipalKeyCredential(credentials.getPrincipal(), credentials.getPassword()));
- }
- }
-
- /**
- * Removes the previously set KDC administrator credentials.
- * <p/>
- * This implementation clears the secure CredentialsStoreService instance, removing the previously
- * generated master key and credentials data. The configured timer to enforce retention time is
- * cleared and set to null.
- *
- * @throws AmbariException if an error occurs while removing the credentials
- * @see KerberosHelper#setKDCCredentials(KerberosCredential)
- */
- @Override
- public void removeKDCCredentials() throws AmbariException {
- kdcCredentialStoreService.removeCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS);
- }
-
- /**
- * Gets the previously stored KDC administrator credentials.
+ * Sets the previously stored KDC administrator credential.
* <p/>
* This implementation accesses the secure CredentialStoreService instance to get the data.
*
- * @return a KerberosCredential or null, if the KDC administrator credentials have not be set or
- * have been removed
+ * @param clusterName the name of the relevant cluster
+ * @return a PrincipalKeyCredential or null, if the KDC administrator credential is not available
* @throws AmbariException if an error occurs while retrieving the credentials
- * @see KerberosHelper#setKDCCredentials(KerberosCredential)
*/
@Override
- public KerberosCredential getKDCCredentials() throws AmbariException {
- Credential credentials = kdcCredentialStoreService.getCredential(KDC_ADMINISTRATOR_CREDENTIAL_ALIAS);
+ public PrincipalKeyCredential getKDCAdministratorCredentials(String clusterName) throws AmbariException {
+ Credential credentials = credentialStoreService.getCredential(clusterName, KDC_ADMINISTRATOR_CREDENTIAL_ALIAS);
if (credentials instanceof PrincipalKeyCredential) {
- PrincipalKeyCredential principalKeyCredential = (PrincipalKeyCredential) credentials;
- return new KerberosCredential(principalKeyCredential.getPrincipal(), principalKeyCredential.getKey(), null);
- } else
+ return (PrincipalKeyCredential) credentials;
+ } else {
return null;
+ }
}
/**
@@ -993,15 +933,15 @@ public class KerberosHelperImpl implements KerberosHelper {
}
if (kerberosDetails.manageIdentities()) {
- KerberosCredential kerberosCredentials = getKDCCredentials();
- if (kerberosCredentials == null) {
+ PrincipalKeyCredential credentials = getKDCAdministratorCredentials(cluster.getClusterName());
+ if (credentials == null) {
throw new KerberosMissingAdminCredentialsException(
"Missing KDC administrator credentials.\n" +
- "The KDC administrator credentials must be set in session by updating the relevant Cluster resource." +
- "This may be done by issuing a PUT to the api/v1/clusters/(cluster name) API entry point with the following payload:\n" +
+ "The KDC administrator credentials must be set as a persisted or temporary credential resource." +
+ "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" +
"{\n" +
- " \"session_attributes\" : {\n" +
- " \"kerberos_admin\" : {\"principal\" : \"(PRINCIPAL)\", \"password\" : \"(PASSWORD)\"}\n" +
+ " \"Credential\" : {\n" +
+ " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" +
" }\n" +
"}"
);
@@ -1013,17 +953,17 @@ public class KerberosHelperImpl implements KerberosHelper {
} else {
boolean missingCredentials = false;
try {
- operationHandler.open(kerberosCredentials, kerberosDetails.getDefaultRealm(), kerberosDetails.getKerberosEnvProperties());
+ operationHandler.open(credentials, kerberosDetails.getDefaultRealm(), kerberosDetails.getKerberosEnvProperties());
// todo: this is really odd that open doesn't throw an exception if the credentials are missing
missingCredentials = !operationHandler.testAdministratorCredentials();
} catch (KerberosAdminAuthenticationException e) {
throw new KerberosAdminAuthenticationException(
"Invalid KDC administrator credentials.\n" +
- "The KDC administrator credentials must be set in session by updating the relevant Cluster resource." +
- "This may be done by issuing a PUT to the api/v1/clusters/(cluster name) API entry point with the following payload:\n" +
+ "The KDC administrator credentials must be set as a persisted or temporary credential resource." +
+ "This may be done by issuing a POST (or PUT for updating) to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" +
"{\n" +
- " \"session_attributes\" : {\n" +
- " \"kerberos_admin\" : {\"principal\" : \"(PRINCIPAL)\", \"password\" : \"(PASSWORD)\"}\n" +
+ " \"Credential\" : {\n" +
+ " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" +
" }\n" +
"}", e);
} catch (KerberosKDCConnectionException e) {
@@ -1055,11 +995,11 @@ public class KerberosHelperImpl implements KerberosHelper {
if (missingCredentials) {
throw new KerberosMissingAdminCredentialsException(
"Invalid KDC administrator credentials.\n" +
- "The KDC administrator credentials must be set in session by updating the relevant Cluster resource." +
- "This may be done by issuing a PUT to the api/v1/clusters/(cluster name) API entry point with the following payload:\n" +
+ "The KDC administrator credentials must be set as a persisted or temporary credential resource." +
+ "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" +
"{\n" +
- " \"session_attributes\" : {\n" +
- " \"kerberos_admin\" : {\"principal\" : \"(PRINCIPAL)\", \"password\" : \"(PASSWORD)\"}\n" +
+ " \"Credential\" : {\n" +
+ " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" +
" }\n" +
"}"
);
@@ -1220,25 +1160,6 @@ public class KerberosHelperImpl implements KerberosHelper {
return requestStageContainer;
}
- private int filteredIdentitiesCount(List<KerberosIdentityDescriptor> identities, Collection<String> identityFilter) {
-
- if ((identities == null) || identities.isEmpty()) {
- return 0;
- } else if (identityFilter == null) {
- return identities.size();
- } else {
- int count = 0;
-
- for (KerberosIdentityDescriptor identity : identities) {
- if (identityFilter.contains(identity.getName())) {
- count++;
- }
- }
-
- return count;
- }
- }
-
/**
* Performs operations needed to process Kerberos related tasks to manage a (unique) test identity
@@ -1399,7 +1320,7 @@ public class KerberosHelperImpl implements KerberosHelper {
}
}
- // If there are ServiceComponentHosts to process, make sure the administrator credentials
+ // If there are ServiceComponentHosts to process, make sure the administrator credential
// are available
if (!serviceComponentHostsToProcess.isEmpty()) {
try {
@@ -1743,40 +1664,6 @@ public class KerberosHelperImpl implements KerberosHelper {
}
/**
- * Using the session data from the relevant Cluster object, creates a KerberosCredential,
- * serializes, and than encrypts it.
- * <p/>
- * Since the relevant data is stored in the HTTPSession (which relies on ThreadLocalStorage),
- * it needs to be retrieved now and placed in the action's command parameters so it will be
- * available when needed. Because command parameters are stored in plaintext in the Ambari database,
- * this (sensitive) data needs to be encrypted, however it needs to be done using a key the can be
- * recreated sometime later when the data needs to be access. Since it is expected that the Cluster
- * object will be able now and later, the hashcode of this object is used to build the key - it
- * is expected that the same instance will be retrieved from the Clusters instance, thus yielding
- * the same hashcode value.
- * <p/>
- * If the Ambari server architecture changes, this will need to be revisited.
- *
- * @param cluster the relevant Cluster
- * @return a serialized and encrypted KerberosCredential, or null if administrator data is not found
- * @throws AmbariException
- */
- private String getEncryptedAdministratorCredentials(Cluster cluster) throws AmbariException {
- String encryptedAdministratorCredentials = null;
-
- Map<String, Object> sessionAttributes = cluster.getSessionAttributes();
- if (sessionAttributes != null) {
- KerberosCredential credential = KerberosCredential.fromMap(sessionAttributes, "kerberos_admin/");
- if (credential != null) {
- byte[] key = Integer.toHexString(cluster.hashCode()).getBytes();
- encryptedAdministratorCredentials = credential.encrypt(key);
- }
- }
-
- return encryptedAdministratorCredentials;
- }
-
- /**
* Given a Collection of ServiceComponentHosts generates a unique list of hosts.
*
* @param serviceComponentHosts a Collection of ServiceComponentHosts from which to to retrieve host names
@@ -2690,7 +2577,7 @@ public class KerberosHelperImpl implements KerberosHelper {
commandParameters.put(KerberosServerAction.REGENERATE_ALL, (regenerateAllKeytabs) ? "true" : "false");
- if(updateConfigurations) {
+ if (updateConfigurations) {
commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATION_NOTE, "Updated Kerberos-related configurations");
commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATIONS, "true");
}
@@ -2719,7 +2606,7 @@ public class KerberosHelperImpl implements KerberosHelper {
hostParamsJson, commandParameters, roleCommandOrder, requestStageContainer, hostsWithValidKerberosClient);
}
- if(updateConfigurations) {
+ if (updateConfigurations) {
// *****************************************************************
// Create stage to update configurations of services
addUpdateConfigurationsStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters,
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java
index fb21883..a1e1544 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java
@@ -21,7 +21,9 @@ package org.apache.ambari.server.serveraction.kerberos;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
+import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
@@ -116,25 +118,25 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
* <li>container_dn - DN of the container in ldap back end where principals would be created</li>
* </il>
*
- * @param administratorCredentials a KerberosCredential containing the administrative credentials
- * for the relevant KDC
- * @param realm a String declaring the default Kerberos realm (or domain)
- * @param kerberosConfiguration a Map of key/value pairs containing data from the kerberos-env configuration set
+ * @param administratorCredential a PrincipalKeyCredential containing the administrative credential
+ * for the relevant KDC
+ * @param realm a String declaring the default Kerberos realm (or domain)
+ * @param kerberosConfiguration a Map of key/value pairs containing data from the kerberos-env configuration set
* @throws KerberosKDCConnectionException if a connection to the KDC cannot be made
* @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate
* @throws KerberosRealmException if the realm does not map to a KDC
* @throws KerberosOperationException if an unexpected error occurred
*/
@Override
- public void open(KerberosCredential administratorCredentials, String realm,
+ public void open(PrincipalKeyCredential administratorCredential, String realm,
Map<String, String> kerberosConfiguration) throws KerberosOperationException {
if (isOpen()) {
close();
}
- if (administratorCredentials == null) {
- throw new KerberosAdminAuthenticationException("administrator credentials not provided");
+ if (administratorCredential == null) {
+ throw new KerberosAdminAuthenticationException("administrator credential not provided");
}
if (realm == null) {
throw new KerberosRealmException("realm not provided");
@@ -159,7 +161,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
throw new KerberosLDAPContainerException("principalContainerDn is not a valid LDAP name", e);
}
- setAdministratorCredentials(administratorCredentials);
+ setAdministratorCredential(administratorCredential);
setDefaultRealm(realm);
setKeyEncryptionTypes(translateEncryptionTypes(kerberosConfiguration.get(KERBEROS_ENV_ENCRYPTION_TYPES), "\\s+"));
@@ -422,13 +424,13 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
* @throws KerberosOperationException if an unexpected error occurred
*/
protected LdapContext createLdapContext() throws KerberosOperationException {
- KerberosCredential administratorCredentials = getAdministratorCredentials();
+ PrincipalKeyCredential administratorCredential = getAdministratorCredential();
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_CONTEXT_FACTORY_CLASS);
properties.put(Context.PROVIDER_URL, ldapUrl);
- properties.put(Context.SECURITY_PRINCIPAL, administratorCredentials.getPrincipal());
- properties.put(Context.SECURITY_CREDENTIALS, administratorCredentials.getPassword());
+ properties.put(Context.SECURITY_PRINCIPAL, administratorCredential.getPrincipal());
+ properties.put(Context.SECURITY_CREDENTIALS, String.valueOf(administratorCredential.getKey()));
properties.put(Context.SECURITY_AUTHENTICATION, "simple");
properties.put(Context.REFERRAL, "follow");
properties.put("java.naming.ldap.factory.socket", TrustingSSLSocketFactory.class.getName());
@@ -446,7 +448,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
} catch (NamingException e) {
String error = e.getMessage();
- if ((error != null) && !error.isEmpty()) {
+ if (StringUtils.isEmpty(error)) {
String message = String.format("Failed to communicate with the Active Directory at %s: %s", ldapUrl, e.getMessage());
LOG.warn(message, e);
@@ -511,7 +513,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler {
String template;
StringWriter stringWriter = new StringWriter();
- if ((createTemplate == null) || createTemplate.isEmpty()) {
+ if (StringUtils.isEmpty(createTemplate)) {
template = "{" +
"\"objectClass\": [\"top\", \"person\", \"organizationalPerson\", \"user\"]," +
"\"cn\": \"$principal_name\"," +
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java
deleted file mode 100644
index a173e08..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosCredential.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.ambari.server.serveraction.kerberos;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonSyntaxException;
-import org.apache.ambari.server.AmbariException;
-import org.apache.commons.codec.binary.Base64;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.spec.SecretKeySpec;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.Map;
-
-/**
- * KerberosCredential encapsulates data needed to authenticate an identity to a KDC.
- * <p/>
- * This class has the ability to encrypt and decrypt itself using the AES encryption algorithm.
- */
-public class KerberosCredential {
-
- /**
- * A property name used to hold the KDC administrator's principal value.
- */
- public static final String KEY_NAME_PRINCIPAL = "principal";
- /**
- * A property name used to hold the KDC administrator's password value.
- */
- public static final String KEY_NAME_PASSWORD = "password";
- /**
- * A property name used to hold the KDC administrator's (base64-encoded) keytab
- * value.
- */
- public static final String KEY_NAME_KEYTAB = "keytab";
-
- /**
- * This principal value
- */
- private String principal = null;
-
- /**
- * The plaintext password value
- */
- private char[] password = null;
-
- /**
- * A base64-encoded keytab
- */
- private String keytab = null;
-
- /**
- * Given a Map of attributes, attempts to safely retrieve the data needed to create a
- * KerberosCredential representing a KDC administrator.
- * <p/>
- * It is expected that the following properties exist in the Map:
- * <ul>
- * <li>principal</li>
- * <li>password (optional)</li>
- * <li>keytab (optional)</li>
- * </ul>
- * <p/>
- * Each of these properties may be prefixed with some prefix value to generate a relevant key value.
- * If prefix was "kerberos_admin/", then the key representing the principal would be computed
- * to be "kerberos_admin/principal".
- *
- * @param map a Map of attributes containing the values needed to create a new KerberosCredential
- * @param prefix a String containing the prefix to used along with the base key name (principal, etc...)
- * to create the relevant key name ([prefix]base_key. etc...)
- * @return a KerberosCredential or null if commandParameters is null
- */
- public static KerberosCredential fromMap(Map<String, Object> map, String prefix) {
- KerberosCredential credential = null;
-
- if (map != null) {
- Object attribute;
- String principal;
- char[] password;
- String keytab;
-
- if (prefix == null) {
- prefix = "";
- }
-
- attribute = map.get(prefix + KEY_NAME_PRINCIPAL);
- principal = (attribute == null) ? null : attribute.toString();
-
- attribute = map.get(prefix + KEY_NAME_PASSWORD);
- if (attribute instanceof char[]) {
- password = (char[]) attribute;
- } else if (attribute instanceof String) {
- password = ((String) attribute).toCharArray();
- } else {
- password = null;
- }
-
- attribute = map.get(prefix + KEY_NAME_KEYTAB);
- keytab = (attribute == null) ? null : attribute.toString();
-
- if (((principal != null) && !principal.isEmpty()) ||
- ((password != null) && (password.length > 0)) ||
- ((keytab != null) && !keytab.isEmpty())) {
- credential = new KerberosCredential(principal, password, keytab);
- }
- }
-
- return credential;
- }
-
- /**
- * Decrypts a String containing base64-encoded encrypted data into a new KerberosCredential.
- * <p/>
- * Given a key and a base64-encoded set of bytes containing encrypted data (ideally obtained from
- * {@link #encrypt(KerberosCredential, byte[])} or {@link #encrypt(byte[])}, decodes and decrypts
- * into a new KerberosCredential.
- *
- * @param cipherText a String containing base64-encoded encrypted data
- * @param key an array of bytes used to decrypt the encrypted data
- * @return a new KerberosCredential
- * @throws AmbariException if an error occurs while decrypting the data
- */
- public static KerberosCredential decrypt(String cipherText, byte[] key) throws AmbariException {
- if (cipherText == null) {
- return null;
- } else {
- try {
- SecretKeySpec secretKey = new SecretKeySpec(Arrays.copyOf(key, 16), "AES");
- Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
- cipher.init(Cipher.DECRYPT_MODE, secretKey);
- byte[] plaintext = cipher.doFinal(Base64.decodeBase64(cipherText));
- return fromJSON(new String(plaintext));
- } catch (NoSuchAlgorithmException e) {
- throw new AmbariException("Failed to decrypt cipher text due to invalid encryption algorithm", e);
- } catch (NoSuchPaddingException e) {
- throw new AmbariException("Failed to decrypt cipher text due to invalid padding scheme algorithm", e);
- } catch (IllegalBlockSizeException e) {
- throw new AmbariException("Failed to decrypt cipher text due to invalid block size", e);
- } catch (BadPaddingException e) {
- throw new AmbariException("Failed to decrypt cipher text due to invalid padding", e);
- } catch (InvalidKeyException e) {
- throw new AmbariException("Failed to decrypt cipher text due to invalid key", e);
- } catch (JsonSyntaxException e) {
- throw new AmbariException("Failed to decrypt cipher, cannot parse data into a KerberosCredential", e);
- }
- }
- }
-
- /**
- * Encrypts a KerberosCredential into a base64-encoded set of bytes.
- * <p/>
- * Given a KerberosCredential and a key, serializes the data into a JSON-formatted string and
- * encrypts it.
- *
- * @param kerberosCredential the KerberosCredential to encrypt
- * @param key an array of bytes used to decrypt the encrypted data
- * @return a String containing base64-encoded encrypted data
- * @throws AmbariException if an error occurs while encrypting the KerberosCredential
- */
- public static String encrypt(KerberosCredential kerberosCredential, byte[] key) throws AmbariException {
- if (kerberosCredential == null) {
- return null;
- } else {
- try {
- SecretKeySpec secretKey = new SecretKeySpec(Arrays.copyOf(key, 16), "AES");
- Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, secretKey);
- String plaintext = new Gson().toJson(kerberosCredential);
- return Base64.encodeBase64String(cipher.doFinal(plaintext.getBytes()));
- } catch (NoSuchAlgorithmException e) {
- throw new AmbariException("Failed to encrypt plaintext due to invalid encryption algorithm", e);
- } catch (NoSuchPaddingException e) {
- throw new AmbariException("Failed to encrypt plaintext due to invalid padding scheme algorithm", e);
- } catch (IllegalBlockSizeException e) {
- throw new AmbariException("The encryption algorithm is unable to process the input data provided.", e);
- } catch (BadPaddingException e) {
- throw new AmbariException("Failed to encrypt plaintext due to unexpected reasons", e);
- } catch (InvalidKeyException e) {
- throw new AmbariException("Failed to encrypt plaintext due to invalid key", e);
- }
- }
- }
-
- /**
- * Creates an empty KerberosCredential
- */
- public KerberosCredential() {
- principal = null;
- password = null;
- keytab = null;
- }
-
- /**
- * Creates a new KerberosCredential
- *
- * @param principal a String containing the principal name for this Kerberos credential
- * @param password a char array containing the password for this Kerberos credential
- * @param keytab a String containing the base64 encoded keytab for this Kerberos credential
- */
- public KerberosCredential(String principal, char[] password, String keytab) {
- this.principal = principal;
- this.password = password;
- this.keytab = keytab;
- }
-
- /**
- * @return a String containing the principal name for this Kerberos credential
- */
- public String getPrincipal() {
- return principal;
- }
-
- /**
- * @param principal a String containing the principal name for this Kerberos credential
- */
- public void setPrincipal(String principal) {
- this.principal = principal;
- }
-
- /**
- * @return a char array containing the password for this Kerberos credential
- */
- public char[] getPassword() {
- return password;
- }
-
- /**
- * @param password a char array containing the password for this Kerberos credential
- */
- public void setPassword(char[] password) {
- this.password = password;
- }
-
- /**
- * @return a String containing the base64 encoded keytab for this Kerberos credential
- */
- public String getKeytab() {
- return keytab;
- }
-
- /**
- * @param keytab a String containing the base64 encoded keytab for this Kerberos credential
- */
- public void setKeytab(String keytab) {
- this.keytab = keytab;
- }
-
- /**
- * Encrypts this KerberosCredential into a base64-encoded set of bytes.
- * <p/>
- * Serializes this KerberosCredential into a JSON-formatted string and
- * encrypts it using the supplied key.
- *
- * @param key an array of bytes used to decrypt the encrypted data
- * @return a String containing base64-encoded encrypted data
- * @throws AmbariException if an error occurs while encrypting the KerberosCredential
- */
- public String encrypt(byte[] key) throws AmbariException {
- return encrypt(this, key);
- }
-
- /**
- * Returns a JSON representation of this KerberosCredential
- *
- * @return a String containing the JSON representation of this KerberosCredential
- */
- public String toJSON() {
- return new Gson().toJson(this);
- }
-
- /**
- * Renders a new KerberosCredential from its JSON representation
- *
- * @param json a string containing a JSON representation of a KerberosCredential
- * @return a new KerberosCredential or null if a new KerberosCredential cannot be created
- */
- public static KerberosCredential fromJSON(String json) {
- try {
- return ((json == null) || json.isEmpty()) ? null : new Gson().fromJson(json, KerberosCredential.class);
- }
- catch(JsonSyntaxException e) {
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
index c8b8ca6..4cd050e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java
@@ -18,8 +18,11 @@
package org.apache.ambari.server.serveraction.kerberos;
+import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.utils.ShellCommandUtil;
import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.directory.server.kerberos.shared.crypto.encryption.KerberosKeyFactory;
import org.apache.directory.server.kerberos.shared.keytab.Keytab;
import org.apache.directory.server.kerberos.shared.keytab.KeytabEntry;
@@ -188,7 +191,7 @@ public abstract class KerberosOperationHandler {
add(EncryptionType.AES256_CTS_HMAC_SHA1_96);
}});
- private KerberosCredential administratorCredentials = null;
+ private PrincipalKeyCredential administratorCredential = null;
private String defaultRealm = null;
private Set<EncryptionType> keyEncryptionTypes = new HashSet<EncryptionType>(DEFAULT_CIPHERS);
private boolean open = false;
@@ -202,18 +205,15 @@ public abstract class KerberosOperationHandler {
/**
* Prepares and creates resources to be used by this KerberosOperationHandler.
- * Implementation in this class is ignoring parameters ldapUrl and principalContainerDn and delegate to
- * <code>open(KerberosCredential administratorCredentials, String defaultRealm)</code>
- * Subclasses that want to use these parameters need to override this method.
* <p/>
* It is expected that this KerberosOperationHandler will not be used before this call.
*
- * @param administratorCredentials a KerberosCredential containing the administrative credentials
- * for the relevant KDC
- * @param defaultRealm a String declaring the default Kerberos realm (or domain)
- * @param kerberosConfiguration a Map of key/value pairs containing data from the kerberos-env configuration set
+ * @param administratorCredential a PrincipalKeyCredential containing the administrative credential
+ * for the relevant KDC
+ * @param defaultRealm a String declaring the default Kerberos realm (or domain)
+ * @param kerberosConfiguration a Map of key/value pairs containing data from the kerberos-env configuration set
*/
- public abstract void open(KerberosCredential administratorCredentials, String defaultRealm, Map<String, String> kerberosConfiguration)
+ public abstract void open(PrincipalKeyCredential administratorCredential, String defaultRealm, Map<String, String> kerberosConfiguration)
throws KerberosOperationException;
/**
@@ -288,11 +288,11 @@ public abstract class KerberosOperationHandler {
throw new KerberosOperationException("This operation handler has not been opened");
}
- KerberosCredential credentials = getAdministratorCredentials();
- if (credentials == null) {
- throw new KerberosOperationException("Missing KDC administrator credentials");
+ PrincipalKeyCredential credential = getAdministratorCredential();
+ if (credential == null) {
+ throw new KerberosOperationException("Missing KDC administrator credential");
} else {
- return principalExists(credentials.getPrincipal());
+ return principalExists(credential.getPrincipal());
}
}
@@ -308,7 +308,7 @@ public abstract class KerberosOperationHandler {
protected Keytab createKeytab(String principal, String password, Integer keyNumber)
throws KerberosOperationException {
- if ((principal == null) || principal.isEmpty()) {
+ if (StringUtils.isEmpty(principal)) {
throw new KerberosOperationException("Failed to create keytab file, missing principal");
}
@@ -478,48 +478,47 @@ public abstract class KerberosOperationHandler {
return keytab;
}
- public KerberosCredential getAdministratorCredentials() {
- return administratorCredentials;
+ /**
+ * Sets the KDC administrator credential.
+ *
+ * @return a credential
+ */
+ public PrincipalKeyCredential getAdministratorCredential() {
+ return administratorCredential;
}
/**
* Sets the administrator credentials for this KerberosOperationHandler.
* <p/>
- * If the supplied {@link KerberosCredential} is not <code>null</code>, validates that the administrator
- * principal is not <code>null</code> or empty and that either the password or the keytab value
- * is not <code>null</code> or empty. If the credential value does not validate, then a
- * {@link KerberosAdminAuthenticationException} will be thrown.
+ * If the supplied {@link PrincipalKeyCredential} is not <code>null</code>, validates that the administrator
+ * principal and values are not <code>null</code> or empty. If the credential value does not
+ * validate, then a {@link KerberosAdminAuthenticationException} will be thrown.
*
- * @param administratorCredentials the relevant KerberosCredential
- * @throws KerberosAdminAuthenticationException if the non-null KerberosCredential fails contain
- * a non-empty principal and a non-empty password or
- * keytab value.
+ * @param administratorCredential the KDC administrator credential
+ * @throws KerberosAdminAuthenticationException if the non-null Credential fails to contain
+ * a non-empty principal and password values.
*/
- public void setAdministratorCredentials(KerberosCredential administratorCredentials)
+ public void setAdministratorCredential(PrincipalKeyCredential administratorCredential)
throws KerberosAdminAuthenticationException {
- // Ensure the KerberosCredential is not null
- if (administratorCredentials == null) {
+ // Ensure the credential is not null
+ if (administratorCredential == null) {
throw new KerberosAdminAuthenticationException("The administrator credential must not be null");
}
// Ensure the principal is not null or empty
- String principal = administratorCredentials.getPrincipal();
- if ((principal == null) || principal.isEmpty()) {
+ String principal = administratorCredential.getPrincipal();
+ if (StringUtils.isEmpty(principal)) {
throw new KerberosAdminAuthenticationException("Must specify a principal but it is null or empty");
}
// Ensure either the password or the keytab value is not null or empty
- char[] password = administratorCredentials.getPassword();
- if ((password == null) || (password.length == 0)) {
- String keytab = administratorCredentials.getKeytab();
-
- if ((keytab == null) || keytab.isEmpty()) {
- throw new KerberosAdminAuthenticationException("Must specify either a password or a keytab but both are null or empty");
- }
+ char[] password = administratorCredential.getKey();
+ if (ArrayUtils.isEmpty(password)) {
+ throw new KerberosAdminAuthenticationException("Must specify a password but it is null or empty");
}
- this.administratorCredentials = administratorCredentials;
+ this.administratorCredential = administratorCredential;
}
public String getDefaultRealm() {
@@ -749,7 +748,7 @@ public abstract class KerberosOperationHandler {
protected Set<EncryptionType> translateEncryptionType(String name) {
Set<EncryptionType> encryptionTypes = null;
- if ((name != null) && !name.isEmpty()) {
+ if (!StringUtils.isEmpty(name)) {
encryptionTypes = ENCRYPTION_TYPE_TRANSLATION_MAP.get(name.toLowerCase());
}
@@ -767,7 +766,7 @@ public abstract class KerberosOperationHandler {
protected Set<EncryptionType> translateEncryptionTypes(String names, String delimiter) {
Set<EncryptionType> encryptionTypes = new HashSet<EncryptionType>();
- if ((names != null) && !names.isEmpty()) {
+ if (!StringUtils.isEmpty(names)) {
for (String name : names.split((delimiter == null) ? "\\s+" : delimiter)) {
encryptionTypes.addAll(translateEncryptionType(name.trim()));
}
@@ -785,7 +784,7 @@ public abstract class KerberosOperationHandler {
* @return the string with escaped characters
*/
protected String escapeCharacters(String string, Set<Character> charactersToEscape, Character escapeCharacter) {
- if ((string == null) || string.isEmpty() || (charactersToEscape == null) || charactersToEscape.isEmpty()) {
+ if (StringUtils.isEmpty(string) || (charactersToEscape == null) || charactersToEscape.isEmpty()) {
return string;
} else {
StringBuilder builder = new StringBuilder();
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/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 c861b45..901a80f 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
@@ -24,6 +24,7 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.agent.ExecutionCommand;
import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.serveraction.AbstractServerAction;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
@@ -341,7 +342,7 @@ public abstract class KerberosServerAction extends AbstractServerAction {
if (commandParameters != null) {
// Grab the relevant data from this action's command parameters map
- KerberosCredential administratorCredential = kerberosHelper.getKDCCredentials();
+ PrincipalKeyCredential administratorCredential = kerberosHelper.getKDCAdministratorCredentials(getClusterName());
String defaultRealm = getDefaultRealm(commandParameters);
KDCType kdcType = getKDCType(commandParameters);
String dataDirectoryPath = getDataDirectoryPath(commandParameters);
http://git-wip-us.apache.org/repos/asf/ambari/blob/44c26466/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
index 6f36bf5..90858fb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
@@ -18,11 +18,13 @@
package org.apache.ambari.server.serveraction.kerberos;
+import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
import org.apache.ambari.server.utils.ShellCommandUtil;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
@@ -73,7 +75,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
* <p/>
* The kerberosConfiguration Map is not being used.
*
- * @param administratorCredentials a KerberosCredential containing the administrative credentials
+ * @param administratorCredentials a PrincipalKeyCredential containing the administrative credential
* for the relevant KDC
* @param realm a String declaring the default Kerberos realm (or domain)
* @param kerberosConfiguration a Map of key/value pairs containing data from the kerberos-env configuration set
@@ -83,11 +85,11 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
* @throws KerberosOperationException if an unexpected error occurred
*/
@Override
- public void open(KerberosCredential administratorCredentials, String realm,
+ public void open(PrincipalKeyCredential administratorCredentials, String realm,
Map<String, String> kerberosConfiguration)
throws KerberosOperationException {
- setAdministratorCredentials(administratorCredentials);
+ setAdministratorCredential(administratorCredentials);
setDefaultRealm(realm);
if (kerberosConfiguration != null) {
@@ -176,9 +178,9 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
throw new KerberosOperationException("This operation handler has not been opened");
}
- if ((principal == null) || principal.isEmpty()) {
+ if (StringUtils.isEmpty(principal)) {
throw new KerberosOperationException("Failed to create new principal - no principal specified");
- } else if ((password == null) || password.isEmpty()) {
+ } else if (StringUtils.isEmpty(password)) {
throw new KerberosOperationException("Failed to create new principal - no password specified");
} else {
String createAttributes = getCreateAttributes();
@@ -220,9 +222,9 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
throw new KerberosOperationException("This operation handler has not been opened");
}
- if ((principal == null) || principal.isEmpty()) {
+ if (StringUtils.isEmpty(principal)) {
throw new KerberosOperationException("Failed to set password - no principal specified");
- } else if ((password == null) || password.isEmpty()) {
+ } else if (StringUtils.isEmpty(password)) {
throw new KerberosOperationException("Failed to set password - no password specified");
} else {
// Create the kdamin query: change_password <-randkey|-pw <password>> <principal>
@@ -250,7 +252,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
throw new KerberosOperationException("This operation handler has not been opened");
}
- if ((principal == null) || principal.isEmpty()) {
+ if (StringUtils.isEmpty(principal)) {
throw new KerberosOperationException("Failed to remove new principal - no principal specified");
} else {
ShellCommandUtil.Result result = invokeKAdmin(String.format("delete_principal -force %s", principal));
@@ -313,7 +315,7 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
throw new KerberosOperationException("This operation handler has not been opened");
}
- if ((principal == null) || principal.isEmpty()) {
+ if (StringUtils.isEmpty(principal)) {
throw new KerberosOperationException("Failed to get key number for principal - no principal specified");
} else {
// Create the kdamin query: get_principal <principal>
@@ -363,115 +365,95 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler {
*/
protected ShellCommandUtil.Result invokeKAdmin(String query)
throws KerberosOperationException {
- ShellCommandUtil.Result result = null;
-
- if ((query == null) || query.isEmpty()) {
+ if (StringUtils.isEmpty(query)) {
throw new KerberosOperationException("Missing kadmin query");
}
- KerberosCredential administratorCredentials = getAdministratorCredentials();
+
+ ShellCommandUtil.Result result;
+ PrincipalKeyCredential administratorCredential = getAdministratorCredential();
String defaultRealm = getDefaultRealm();
List<String> command = new ArrayList<String>();
- File tempKeytabFile = null;
-
- try {
- String adminPrincipal = (administratorCredentials == null)
- ? null
- : administratorCredentials.getPrincipal();
- if ((adminPrincipal == null) || adminPrincipal.isEmpty()) {
- // Set the kdamin interface to be kadmin.local
- if((executableKadminLocal == null) || executableKadminLocal.isEmpty()) {
- throw new KerberosOperationException("No path for kadmin.local is available - this KerberosOperationHandler may not have been opened.");
- }
+ String adminPrincipal = (administratorCredential == null)
+ ? null
+ : administratorCredential.getPrincipal();
- command.add(executableKadminLocal);
- } else {
- if((executableKadmin == null) || executableKadmin.isEmpty()) {
- throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened.");
- }
- char[] adminPassword = administratorCredentials.getPassword();
- String adminKeyTab = administratorCredentials.getKeytab();
+ if (StringUtils.isEmpty(adminPrincipal)) {
+ // Set the kdamin interface to be kadmin.local
+ if (StringUtils.isEmpty(executableKadminLocal)) {
+ throw new KerberosOperationException("No path for kadmin.local is available - this KerberosOperationHandler may not have been opened.");
+ }
- // Set the kdamin interface to be kadmin
- command.add(executableKadmin);
+ command.add(executableKadminLocal);
+ } else {
+ if (StringUtils.isEmpty(executableKadmin)) {
+ throw new KerberosOperationException("No path for kadmin is available - this KerberosOperationHandler may not have been opened.");
+ }
+ char[] adminPassword = administratorCredential.getKey();
- // Add explicit KDC admin host, if available
- if (getAdminServerHost() != null) {
- command.add("-s");
- command.add(getAdminServerHost());
- }
+ // Set the kdamin interface to be kadmin
+ command.add(executableKadmin);
- // Add the administrative principal
- command.add("-p");
- command.add(adminPrincipal);
-
- if ((adminKeyTab != null) && !adminKeyTab.isEmpty()) {
- tempKeytabFile = createKeytabFile(adminKeyTab);
-
- if (tempKeytabFile != null) {
- // Add keytab file administrative principal
- command.add("-k");
- command.add("-t");
- command.add(tempKeytabFile.getAbsolutePath());
- }
- } else if (adminPassword != null) {
- // Add password for administrative principal
- command.add("-w");
- command.add(String.valueOf(adminPassword));
- }
+ // Add explicit KDC admin host, if available
+ if (getAdminServerHost() != null) {
+ command.add("-s");
+ command.add(getAdminServerHost());
}
- if ((defaultRealm != null) && !defaultRealm.isEmpty()) {
- // Add default realm clause
- command.add("-r");
- command.add(defaultRealm);
+ // Add the administrative principal
+ command.add("-p");
+ command.add(adminPrincipal);
+
+ if (!ArrayUtils.isEmpty(adminPassword)) {
+ // Add password for administrative principal
+ command.add("-w");
+ command.add(String.valueOf(adminPassword));
}
+ }
- // Add kadmin query
- command.add("-q");
- command.add(query);
+ if (!StringUtils.isEmpty(defaultRealm)) {
+ // Add default realm clause
+ command.add("-r");
+ command.add(defaultRealm);
+ }
- if(LOG.isDebugEnabled()) {
- LOG.debug(String.format("Executing: %s", createCleanCommand(command)));
- }
+ // Add kadmin query
+ command.add("-q");
+ command.add(query);
- result = executeCommand(command.toArray(new String[command.size()]));
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(String.format("Executing: %s", createCleanCommand(command)));
+ }
- if (!result.isSuccessful()) {
- String message = String.format("Failed to execute kadmin:\n\tCommand: %s\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s",
- createCleanCommand(command), result.getExitCode(), result.getStdout(), result.getStderr());
- LOG.warn(message);
+ result = executeCommand(command.toArray(new String[command.size()]));
- // Test STDERR to see of any "expected" error conditions were encountered...
- String stdErr = result.getStderr();
- // Did admin credentials fail?
- if (stdErr.contains("Client not found in Kerberos database")) {
- throw new KerberosAdminAuthenticationException(stdErr);
- } else if (stdErr.contains("Incorrect password while initializing")) {
- throw new KerberosAdminAuthenticationException(stdErr);
- }
- // Did we fail to connect to the KDC?
- else if (stdErr.contains("Cannot contact any KDC")) {
- throw new KerberosKDCConnectionException(stdErr);
- } else if (stdErr.contains("Cannot resolve network address for admin server in requested realm while initializing kadmin interface")) {
- throw new KerberosKDCConnectionException(stdErr);
- }
- // Was the realm invalid?
- else if (stdErr.contains("Missing parameters in krb5.conf required for kadmin client")) {
- throw new KerberosRealmException(stdErr);
- } else if (stdErr.contains("Cannot find KDC for requested realm while initializing kadmin interface")) {
- throw new KerberosRealmException(stdErr);
- } else {
- throw new KerberosOperationException("Unexpected error condition executing the kadmin command");
- }
+ if (!result.isSuccessful()) {
+ String message = String.format("Failed to execute kadmin:\n\tCommand: %s\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s",
+ createCleanCommand(command), result.getExitCode(), result.getStdout(), result.getStderr());
+ LOG.warn(message);
+
+ // Test STDERR to see of any "expected" error conditions were encountered...
+ String stdErr = result.getStderr();
+ // Did admin credentials fail?
+ if (stdErr.contains("Client not found in Kerberos database")) {
+ throw new KerberosAdminAuthenticationException(stdErr);
+ } else if (stdErr.contains("Incorrect password while initializing")) {
+ throw new KerberosAdminAuthenticationException(stdErr);
}
- } finally {
- // If a temporary keytab file was created, clean it up.
- if (tempKeytabFile != null) {
- if (!tempKeytabFile.delete()) {
- tempKeytabFile.deleteOnExit();
- }
+ // Did we fail to connect to the KDC?
+ else if (stdErr.contains("Cannot contact any KDC")) {
+ throw new KerberosKDCConnectionException(stdErr);
+ } else if (stdErr.contains("Cannot resolve network address for admin server in requested realm while initializing kadmin interface")) {
+ throw new KerberosKDCConnectionException(stdErr);
+ }
+ // Was the realm invalid?
+ else if (stdErr.contains("Missing parameters in krb5.conf required for kadmin client")) {
+ throw new KerberosRealmException(stdErr);
+ } else if (stdErr.contains("Cannot find KDC for requested realm while initializing kadmin interface")) {
+ throw new KerberosRealmException(stdErr);
+ } else {
+ throw new KerberosOperationException("Unexpected error condition executing the kadmin command");
}
}