Repository: ambari Updated Branches: refs/heads/trunk e67c5ea50 -> efe79f015
http://git-wip-us.apache.org/repos/asf/ambari/blob/efe79f01/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java index 9f0e7ed..d95dc5b 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandlerTest.java @@ -18,39 +18,228 @@ package org.apache.ambari.server.serveraction.kerberos; -import junit.framework.Assert; -import org.apache.ambari.server.AmbariException; -import org.junit.Before; +import org.easymock.EasyMockSupport; +import org.easymock.IAnswer; +import org.junit.Ignore; import org.junit.Test; -public class ADKerberosOperationHandlerTest { +import javax.naming.AuthenticationException; +import javax.naming.CommunicationException; +import javax.naming.NamingEnumeration; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; - @Test +import java.util.Properties; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +public class ADKerberosOperationHandlerTest extends EasyMockSupport { + private static final String DEFAULT_ADMIN_PRINCIPAL = "[email protected]"; + private static final String DEFAULT_ADMIN_PASSWORD = "hadoop"; + private static final String DEFAULT_LDAP_URL = "ldaps://ad.example.com"; + private static final String DEFAULT_PRINCIPAL_CONTAINER_DN = "ou=cluster,dc=example,dc=com"; + private static final String DEFAULT_REALM = "EXAMPLE.COM"; + + @Test(expected = KerberosKDCConnectionException.class) public void testOpenExceptionLdapUrlNotProvided() throws Exception { - try { - KerberosOperationHandler handler = new ADKerberosOperationHandler(); - KerberosCredential kc = new KerberosCredential( - "[email protected]", "adminpass", null); // null keytab - - handler.open(kc, "KNOX.COM"); - Assert.fail("AmbariException not thrown for null ldapUrl"); - } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); - } + KerberosOperationHandler handler = new ADKerberosOperationHandler(); + KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null); + handler.open(kc, DEFAULT_REALM, null, DEFAULT_PRINCIPAL_CONTAINER_DN); + handler.close(); + } + + @Test(expected = KerberosLDAPContainerException.class) + public void testOpenExceptionPrincipalContainerDnNotProvided() throws Exception { + KerberosOperationHandler handler = new ADKerberosOperationHandler(); + KerberosCredential kc = new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null); + handler.open(kc, DEFAULT_REALM, DEFAULT_LDAP_URL, null); + handler.close(); + } + + @Test(expected = KerberosAdminAuthenticationException.class) + public void testOpenExceptionAdminCredentialsNotProvided() throws Exception { + KerberosOperationHandler handler = new ADKerberosOperationHandler(); + handler.open(null, DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN); + handler.close(); + } + + @Test(expected = KerberosAdminAuthenticationException.class) + public void testTestAdministratorCredentialsIncorrectAdminPassword() throws Exception { + ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) + .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) + .createNiceMock(); + + expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class))).andAnswer(new IAnswer<LdapContext>() { + @Override + public LdapContext answer() throws Throwable { + throw new AuthenticationException(); + } + }).once(); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, "wrong", null), + DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN); + handler.testAdministratorCredentials(); + handler.close(); + } + + @Test(expected = KerberosAdminAuthenticationException.class) + public void testTestAdministratorCredentialsIncorrectAdminPrincipal() throws Exception { + ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) + .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) + .createNiceMock(); + + expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class))).andAnswer(new IAnswer<LdapContext>() { + @Override + public LdapContext answer() throws Throwable { + throw new AuthenticationException(); + } + }).once(); + + replayAll(); + + handler.open(new KerberosCredential("wrong", DEFAULT_ADMIN_PASSWORD, null), + DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN); + handler.testAdministratorCredentials(); + handler.close(); + } + + @Test(expected = KerberosKDCConnectionException.class) + public void testTestAdministratorCredentialsKDCConnectionException() throws Exception { + ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) + .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) + .createNiceMock(); + + expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class))).andAnswer(new IAnswer<LdapContext>() { + @Override + public LdapContext answer() throws Throwable { + throw new CommunicationException(); + } + }).once(); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), + DEFAULT_REALM, "invalid", DEFAULT_PRINCIPAL_CONTAINER_DN); + handler.testAdministratorCredentials(); + handler.close(); + } + + + @Test + public void testTestAdministratorCredentialsSuccess() throws Exception { + ADKerberosOperationHandler handler = createMockBuilder(ADKerberosOperationHandler.class) + .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createInitialLdapContext", Properties.class, Control[].class)) + .addMockedMethod(ADKerberosOperationHandler.class.getDeclaredMethod("createSearchControls")) + .createNiceMock(); + + expect(handler.createInitialLdapContext(anyObject(Properties.class), anyObject(Control[].class))) + .andAnswer(new IAnswer<LdapContext>() { + @Override + public LdapContext answer() throws Throwable { + LdapContext ldapContext = createNiceMock(LdapContext.class); + expect(ldapContext.search(anyObject(String.class), anyObject(String.class), anyObject(SearchControls.class))) + .andAnswer(new IAnswer<NamingEnumeration<SearchResult>>() { + @Override + public NamingEnumeration<SearchResult> answer() throws Throwable { + NamingEnumeration<SearchResult> result = createNiceMock(NamingEnumeration.class); + expect(result.hasMore()).andReturn(false).once(); + replay(result); + return result; + } + }) + .once(); + replay(ldapContext); + return ldapContext; + } + }) + .once(); + expect(handler.createSearchControls()).andAnswer(new IAnswer<SearchControls>() { + @Override + public SearchControls answer() throws Throwable { + SearchControls searchControls = createNiceMock(SearchControls.class); + replay(searchControls); + return searchControls; + } + }).once(); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), + DEFAULT_REALM, DEFAULT_LDAP_URL, DEFAULT_PRINCIPAL_CONTAINER_DN); + handler.testAdministratorCredentials(); + handler.close(); } - @Test - public void testOpenExceptionPrincipalContainerDnNotProvided() throws Exception { - try { - KerberosOperationHandler handler = new ADKerberosOperationHandler(); - KerberosCredential kc = new KerberosCredential( - "[email protected]", "adminpass", null); // null keytab + /** + * Implementation to illustrate the use of operations on this class + * + * @throws Throwable + */ + @Test + @Ignore + public void testLive() throws Throwable { + + /* ****************************************************************************************** + * SSL Certificate of AD should have been imported into truststore when that certificate + * is not issued by trusted authority. This is typical with self signed certificated in + * development environment. To use specific trust store, set path to it in + * javax.net.ssl.trustStore System property. Example: + * System.setProperty( + * "javax.net.ssl.trustStore", + * "/tmp/workspace/ambari/apache-ambari-rd/cacerts" + * ); + * ****************************************************************************************** */ + + ADKerberosOperationHandler handler = new ADKerberosOperationHandler(); + String principal = System.getProperty("principal"); + String password = System.getProperty("password"); + String realm = System.getProperty("realm"); + String ldapUrl = System.getProperty("ldap_url"); + String containerDN = System.getProperty("container_dn"); + + if (principal == null) { + principal = DEFAULT_ADMIN_PRINCIPAL; + } + + if (password == null) { + password = DEFAULT_ADMIN_PASSWORD; + } - handler.open(kc, "KNOX.COM", "ldaps://dillwin12.knox.com:636", null); - Assert.fail("AmbariException not thrown for null principalContainerDn"); - } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); - } + if (realm == null) { + realm = DEFAULT_REALM; } + if (ldapUrl == null) { + ldapUrl = DEFAULT_LDAP_URL; + } + + if (containerDN == null) { + containerDN = ""; + } + + KerberosCredential credentials = new KerberosCredential(principal, password, null); + + handler.open(credentials, realm, ldapUrl, containerDN); + + // does the principal already exist? + System.out.println("Principal exists: " + handler.principalExists("nn/c1508.ambari.apache.org")); + + //create principal + handler.createServicePrincipal("nn/c1508.ambari.apache.org", "welcome"); + + //update the password + handler.setPrincipalPassword("nn/c1508.ambari.apache.org", "welcome10"); + + // remove the principal + // handler.removeServicePrincipal("nn/c1508.ambari.apache.org"); + + handler.close(); + } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/efe79f01/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractKerberosOperationHandlerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractKerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractKerberosOperationHandlerTest.java deleted file mode 100644 index 92a4100..0000000 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/AbstractKerberosOperationHandlerTest.java +++ /dev/null @@ -1,245 +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 junit.framework.Assert; -import org.apache.ambari.server.AmbariException; -import org.apache.commons.codec.binary.Base64; -import org.apache.directory.server.kerberos.shared.keytab.Keytab; -import org.apache.directory.server.kerberos.shared.keytab.KeytabEntry; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; -import org.junit.Before; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.FileInputStream; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public abstract class AbstractKerberosOperationHandlerTest { - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - protected final KerberosOperationHandler handler; - - protected AbstractKerberosOperationHandlerTest(KerberosOperationHandler handler) { - this.handler = handler; - } - - @Before - public void startUp() throws AmbariException { - handler.open(new KerberosCredential(), "EXAMPLE.COM"); - } - - @After - public void cleanUp() throws AmbariException { - handler.close(); - } - - @Test - public void testCreateSecurePassword() throws Exception { - KerberosOperationHandler handler2 = new KerberosOperationHandler() { - - @Override - public void open(KerberosCredential administratorCredentials, String defaultRealm) throws AmbariException { - setAdministratorCredentials(administratorCredentials); - setDefaultRealm(defaultRealm); - } - - @Override - public void close() throws AmbariException { - - } - - @Override - public boolean principalExists(String principal) throws AmbariException { - return false; - } - - @Override - public Integer createServicePrincipal(String principal, String password) throws AmbariException { - return 0; - } - - @Override - public Integer setPrincipalPassword(String principal, String password) throws AmbariException { - return 0; - } - - @Override - public boolean removeServicePrincipal(String principal) throws AmbariException { - return false; - } - }; - - String password1 = handler.createSecurePassword(); - Assert.assertNotNull(password1); - Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password1.length()); - - String password2 = handler2.createSecurePassword(); - Assert.assertNotNull(password2); - Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password2.length()); - - // Make sure the passwords are different... if they are the same, that indicated the random - // number generators are generating using the same pattern and that is not secure. - Assert.assertFalse((password1.equals(password2))); - } - - @Test - public void testCreateSecurePasswordWithSize() throws Exception { - String password; - - password = handler.createSecurePassword(10); - Assert.assertNotNull(password); - Assert.assertEquals(10, password.length()); - - password = handler.createSecurePassword(0); - Assert.assertNotNull(password); - Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password.length()); - - password = handler.createSecurePassword(-20); - Assert.assertNotNull(password); - Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password.length()); - } - - @Test - public void testCreateKeytabFileOneAtATime() throws Exception { - File file = folder.newFile(); - final String principal1 = "[email protected]"; - final String principal2 = "[email protected]"; - int count; - - Assert.assertTrue(handler.createKeytabFile(principal1, handler.createSecurePassword(), 0, file)); - - Keytab keytab = Keytab.read(file); - Assert.assertNotNull(keytab); - - List<KeytabEntry> entries = keytab.getEntries(); - Assert.assertNotNull(entries); - Assert.assertFalse(entries.isEmpty()); - - count = entries.size(); - - for (KeytabEntry entry : entries) { - Assert.assertEquals(principal1, entry.getPrincipalName()); - } - - Assert.assertTrue(handler.createKeytabFile(principal2, handler.createSecurePassword(), 0, file)); - - keytab = Keytab.read(file); - Assert.assertNotNull(keytab); - - entries = keytab.getEntries(); - Assert.assertNotNull(entries); - Assert.assertFalse(entries.isEmpty()); - - Assert.assertEquals(count * 2, entries.size()); - } - - @Test - public void testEnsureKeytabFileContainsNoDuplicates() throws Exception { - File file = folder.newFile(); - final String principal1 = "[email protected]"; - final String principal2 = "[email protected]"; - Set<String> seenEntries = new HashSet<String>(); - - Assert.assertTrue(handler.createKeytabFile(principal1, handler.createSecurePassword(), 0, file)); - Assert.assertTrue(handler.createKeytabFile(principal2, handler.createSecurePassword(), 0, file)); - - // Attempt to add duplicate entries - Assert.assertTrue(handler.createKeytabFile(principal2, handler.createSecurePassword(), 0, file)); - - Keytab keytab = Keytab.read(file); - Assert.assertNotNull(keytab); - - List<KeytabEntry> entries = keytab.getEntries(); - Assert.assertNotNull(entries); - Assert.assertFalse(entries.isEmpty()); - - for (KeytabEntry entry : entries) { - String seenEntry = String.format("%s|%s", entry.getPrincipalName(), entry.getKey().getKeyType().toString()); - Assert.assertFalse(seenEntries.contains(seenEntry)); - seenEntries.add(seenEntry); - } - } - - @Test - public void testCreateKeytabFileExceptions() throws Exception { - File file = folder.newFile(); - final String principal1 = "[email protected]"; - - try { - handler.createKeytabFile(null, handler.createSecurePassword(), 0, file); - Assert.fail("AmbariException not thrown with null principal"); - } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); - } - - try { - handler.createKeytabFile(principal1, null, null, file); - Assert.fail("AmbariException not thrown with null password"); - } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); - } - - try { - handler.createKeytabFile(principal1, handler.createSecurePassword(), 0, null); - Assert.fail("AmbariException not thrown with null file"); - } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); - } - } - - @Test - public void testCreateKeytabFileFromBase64EncodedData() throws Exception { - File file = folder.newFile(); - final String principal = "[email protected]"; - - Assert.assertTrue(handler.createKeytabFile(principal, handler.createSecurePassword(), 0, file)); - - FileInputStream fis = new FileInputStream(file); - byte[] data = new byte[(int) file.length()]; - - Assert.assertEquals(data.length, fis.read(data)); - fis.close(); - - File f = handler.createKeytabFile(Base64.encodeBase64String(data)); - - try { - Keytab keytab = Keytab.read(f); - Assert.assertNotNull(keytab); - - List<KeytabEntry> entries = keytab.getEntries(); - Assert.assertNotNull(entries); - Assert.assertFalse(entries.isEmpty()); - - for (KeytabEntry entry : entries) { - Assert.assertEquals(principal, entry.getPrincipalName()); - } - } finally { - if (!f.delete()) { - f.deleteOnExit(); - } - } - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/efe79f01/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerFactoryTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerFactoryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerFactoryTest.java index 4c7e49d..5ec519d 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerFactoryTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerFactoryTest.java @@ -27,13 +27,13 @@ public class KerberosOperationHandlerFactoryTest { @Test public void testForAD() { Assert.assertEquals(MITKerberosOperationHandler.class, - KerberosOperationHandlerFactory.getKerberosOperationHandler(KDCType.MIT_KDC).getClass()); + new KerberosOperationHandlerFactory().getKerberosOperationHandler(KDCType.MIT_KDC).getClass()); } @Test public void testForMIT() { Assert.assertEquals(ADKerberosOperationHandler.class, - KerberosOperationHandlerFactory.getKerberosOperationHandler(KDCType.ACTIVE_DIRECTORY).getClass()); + new KerberosOperationHandlerFactory().getKerberosOperationHandler(KDCType.ACTIVE_DIRECTORY).getClass()); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/efe79f01/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java index 72d58e2..e86656d 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandlerTest.java @@ -18,42 +18,224 @@ package org.apache.ambari.server.serveraction.kerberos; -import org.apache.ambari.server.AmbariException; +import junit.framework.Assert; +import org.apache.commons.codec.binary.Base64; +import org.apache.directory.server.kerberos.shared.keytab.Keytab; +import org.apache.directory.server.kerberos.shared.keytab.KeytabEntry; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; -public class KerberosOperationHandlerTest extends AbstractKerberosOperationHandlerTest { +import java.io.File; +import java.io.FileInputStream; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public abstract class KerberosOperationHandlerTest { + + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + + @Test + public void testCreateSecurePassword() throws Exception { + + KerberosOperationHandler handler1 = createHandler(); + KerberosOperationHandler handler2 = createHandler(); + + String password1 = handler1.createSecurePassword(); + Assert.assertNotNull(password1); + Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password1.length()); + + String password2 = handler2.createSecurePassword(); + Assert.assertNotNull(password2); + Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password2.length()); + + // Make sure the passwords are different... if they are the same, that indicated the random + // number generators are generating using the same pattern and that is not secure. + Assert.assertFalse((password1.equals(password2))); + } + + @Test + public void testCreateSecurePasswordWithSize() throws Exception { + KerberosOperationHandler handler = createHandler(); + + String password; + + password = handler.createSecurePassword(10); + Assert.assertNotNull(password); + Assert.assertEquals(10, password.length()); + + password = handler.createSecurePassword(0); + Assert.assertNotNull(password); + Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password.length()); + + password = handler.createSecurePassword(-20); + Assert.assertNotNull(password); + Assert.assertEquals(KerberosOperationHandler.SECURE_PASSWORD_LENGTH, password.length()); + } + + @Test + public void testCreateKeytabFileOneAtATime() throws Exception { + KerberosOperationHandler handler = createHandler(); + File file = folder.newFile(); + final String principal1 = "[email protected]"; + final String principal2 = "[email protected]"; + int count; + + Assert.assertTrue(handler.createKeytabFile(principal1, handler.createSecurePassword(), 0, file)); + + Keytab keytab = Keytab.read(file); + Assert.assertNotNull(keytab); + + List<KeytabEntry> entries = keytab.getEntries(); + Assert.assertNotNull(entries); + Assert.assertFalse(entries.isEmpty()); + + count = entries.size(); + + for (KeytabEntry entry : entries) { + Assert.assertEquals(principal1, entry.getPrincipalName()); + } + + Assert.assertTrue(handler.createKeytabFile(principal2, handler.createSecurePassword(), 0, file)); + + keytab = Keytab.read(file); + Assert.assertNotNull(keytab); + + entries = keytab.getEntries(); + Assert.assertNotNull(entries); + Assert.assertFalse(entries.isEmpty()); + + Assert.assertEquals(count * 2, entries.size()); + } + + @Test + public void testEnsureKeytabFileContainsNoDuplicates() throws Exception { + KerberosOperationHandler handler = createHandler(); + File file = folder.newFile(); + final String principal1 = "[email protected]"; + final String principal2 = "[email protected]"; + Set<String> seenEntries = new HashSet<String>(); + + Assert.assertTrue(handler.createKeytabFile(principal1, handler.createSecurePassword(), 0, file)); + Assert.assertTrue(handler.createKeytabFile(principal2, handler.createSecurePassword(), 0, file)); + + // Attempt to add duplicate entries + Assert.assertTrue(handler.createKeytabFile(principal2, handler.createSecurePassword(), 0, file)); + + Keytab keytab = Keytab.read(file); + Assert.assertNotNull(keytab); + + List<KeytabEntry> entries = keytab.getEntries(); + Assert.assertNotNull(entries); + Assert.assertFalse(entries.isEmpty()); + + for (KeytabEntry entry : entries) { + String seenEntry = String.format("%s|%s", entry.getPrincipalName(), entry.getKey().getKeyType().toString()); + Assert.assertFalse(seenEntries.contains(seenEntry)); + seenEntries.add(seenEntry); + } + } + + @Test + public void testCreateKeytabFileExceptions() throws Exception { + KerberosOperationHandler handler = createHandler(); + File file = folder.newFile(); + final String principal1 = "[email protected]"; + + try { + handler.createKeytabFile(null, handler.createSecurePassword(), 0, file); + Assert.fail("KerberosOperationException not thrown with null principal"); + } catch (Throwable t) { + Assert.assertEquals(KerberosOperationException.class, t.getClass()); + } + + try { + handler.createKeytabFile(principal1, null, null, file); + Assert.fail("KerberosOperationException not thrown with null password"); + } catch (Throwable t) { + Assert.assertEquals(KerberosOperationException.class, t.getClass()); + } + + try { + handler.createKeytabFile(principal1, handler.createSecurePassword(), 0, null); + Assert.fail("KerberosOperationException not thrown with null file"); + } catch (Throwable t) { + Assert.assertEquals(KerberosOperationException.class, t.getClass()); + } + } + + @Test + public void testCreateKeytabFileFromBase64EncodedData() throws Exception { + KerberosOperationHandler handler = createHandler(); + File file = folder.newFile(); + final String principal = "[email protected]"; + + Assert.assertTrue(handler.createKeytabFile(principal, handler.createSecurePassword(), 0, file)); + + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + + Assert.assertEquals(data.length, fis.read(data)); + fis.close(); + + File f = handler.createKeytabFile(Base64.encodeBase64String(data)); + + try { + Keytab keytab = Keytab.read(f); + Assert.assertNotNull(keytab); + + List<KeytabEntry> entries = keytab.getEntries(); + Assert.assertNotNull(entries); + Assert.assertFalse(entries.isEmpty()); + + for (KeytabEntry entry : entries) { + Assert.assertEquals(principal, entry.getPrincipalName()); + } + } finally { + if (!f.delete()) { + f.deleteOnExit(); + } + } + } + + private KerberosOperationHandler createHandler() throws KerberosOperationException { + KerberosOperationHandler handler = new KerberosOperationHandler() { - public KerberosOperationHandlerTest() { - super(new KerberosOperationHandler() { @Override - public void open(KerberosCredential administratorCredentials, String defaultRealm) throws AmbariException { + public void open(KerberosCredential administratorCredentials, String defaultRealm) throws KerberosOperationException { setAdministratorCredentials(administratorCredentials); setDefaultRealm(defaultRealm); } @Override - public void close() throws AmbariException { + public void close() throws KerberosOperationException { } @Override - public boolean principalExists(String principal) throws AmbariException { + public boolean principalExists(String principal) throws KerberosOperationException { return false; } @Override - public Integer createServicePrincipal(String principal, String password) throws AmbariException { + public Integer createServicePrincipal(String principal, String password) throws KerberosOperationException { return 0; } @Override - public Integer setPrincipalPassword(String principal, String password) throws AmbariException { + public Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException { return 0; } @Override - public boolean removeServicePrincipal(String principal) throws AmbariException { + public boolean removeServicePrincipal(String principal) throws KerberosOperationException { return false; } - }); + }; + + handler.open(new KerberosCredential("admin/admin", "hadoop", null), "EXAMPLE.COM"); + return handler; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/efe79f01/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java index b61b76f..4a1e399 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java @@ -19,48 +19,334 @@ package org.apache.ambari.server.serveraction.kerberos; import junit.framework.Assert; -import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.utils.ShellCommandUtil; +import org.easymock.EasyMockSupport; +import org.easymock.IAnswer; +import org.junit.Ignore; import org.junit.Test; -public class MITKerberosOperationHandlerTest extends AbstractKerberosOperationHandlerTest { +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; - public MITKerberosOperationHandlerTest() { - super(new MITKerberosOperationHandler()); - } +public class MITKerberosOperationHandlerTest extends EasyMockSupport { + + private static final String DEFAULT_ADMIN_PRINCIPAL = "admin/admin"; + private static final String DEFAULT_ADMIN_PASSWORD = "hadoop"; + private static final String DEFAULT_REALM = "EXAMPLE.COM"; @Test public void testSetPrincipalPasswordExceptions() throws Exception { + MITKerberosOperationHandler handler = new MITKerberosOperationHandler(); + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + + try { + handler.setPrincipalPassword(DEFAULT_ADMIN_PRINCIPAL, null); + Assert.fail("KerberosOperationException not thrown for null password"); + } catch (Throwable t) { + Assert.assertEquals(KerberosOperationException.class, t.getClass()); + } + try { - handler.setPrincipalPassword(null, "1234"); - Assert.fail("AmbariException not thrown for null principal"); + handler.setPrincipalPassword(DEFAULT_ADMIN_PRINCIPAL, ""); + Assert.fail("KerberosOperationException not thrown for empty password"); } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); + Assert.assertEquals(KerberosOperationException.class, t.getClass()); } try { - handler.createServicePrincipal("", "1234"); - Assert.fail("AmbariException not thrown for empty principal"); + handler.setPrincipalPassword(null, DEFAULT_ADMIN_PASSWORD); + Assert.fail("KerberosOperationException not thrown for null principal"); } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); + Assert.assertEquals(KerberosOperationException.class, t.getClass()); + } + + try { + handler.setPrincipalPassword("", DEFAULT_ADMIN_PASSWORD); + Assert.fail("KerberosOperationException not thrown for empty principal"); + } catch (Throwable t) { + Assert.assertEquals(KerberosOperationException.class, t.getClass()); } } @Test public void testCreateServicePrincipalExceptions() throws Exception { + MITKerberosOperationHandler handler = new MITKerberosOperationHandler(); + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + + try { + handler.createServicePrincipal(DEFAULT_ADMIN_PRINCIPAL, null); + Assert.fail("KerberosOperationException not thrown for null password"); + } catch (Throwable t) { + Assert.assertEquals(KerberosOperationException.class, t.getClass()); + } + + try { + handler.createServicePrincipal(DEFAULT_ADMIN_PRINCIPAL, ""); + Assert.fail("KerberosOperationException not thrown for empty password"); + } catch (Throwable t) { + Assert.assertEquals(KerberosOperationException.class, t.getClass()); + } + try { - handler.createServicePrincipal(null, "1234"); - Assert.fail("AmbariException not thrown for null principal"); + handler.createServicePrincipal(null, DEFAULT_ADMIN_PASSWORD); + Assert.fail("KerberosOperationException not thrown for null principal"); } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); + Assert.assertEquals(KerberosOperationException.class, t.getClass()); } try { - handler.createServicePrincipal("", "1234"); - Assert.fail("AmbariException not thrown for empty principal"); + handler.createServicePrincipal("", DEFAULT_ADMIN_PASSWORD); + Assert.fail("KerberosOperationException not thrown for empty principal"); } catch (Throwable t) { - Assert.assertEquals(AmbariException.class, t.getClass()); + Assert.assertEquals(KerberosOperationException.class, t.getClass()); } } + @Test(expected = KerberosAdminAuthenticationException.class) + public void testTestAdministratorCredentialsIncorrectAdminPassword() throws Exception { + MITKerberosOperationHandler handler = createMockBuilder(MITKerberosOperationHandler.class) + .addMockedMethod(KerberosOperationHandler.class.getDeclaredMethod("executeCommand", String[].class)) + .createNiceMock(); + + expect(handler.executeCommand(anyObject(String[].class))) + .andAnswer(new IAnswer<ShellCommandUtil.Result>() { + @Override + public ShellCommandUtil.Result answer() throws Throwable { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + + expect(result.getExitCode()).andReturn(1).anyTimes(); + expect(result.isSuccessful()).andReturn(false).anyTimes(); + expect(result.getStderr()) + .andReturn("kadmin: Incorrect password while initializing kadmin interface") + .anyTimes(); + expect(result.getStdout()) + .andReturn("Authenticating as principal admin/admin with password.") + .anyTimes(); + + replay(result); + return result; + } + }); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + handler.testAdministratorCredentials(); + handler.close(); + } + + @Test(expected = KerberosAdminAuthenticationException.class) + public void testTestAdministratorCredentialsIncorrectAdminPrincipal() throws Exception { + MITKerberosOperationHandler handler = createMockBuilder(MITKerberosOperationHandler.class) + .addMockedMethod(KerberosOperationHandler.class.getDeclaredMethod("executeCommand", String[].class)) + .createNiceMock(); + + expect(handler.executeCommand(anyObject(String[].class))) + .andAnswer(new IAnswer<ShellCommandUtil.Result>() { + @Override + public ShellCommandUtil.Result answer() throws Throwable { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + + expect(result.getExitCode()).andReturn(1).anyTimes(); + expect(result.isSuccessful()).andReturn(false).anyTimes(); + expect(result.getStderr()) + .andReturn("kadmin: Client not found in Kerberos database while initializing kadmin interface") + .anyTimes(); + expect(result.getStdout()) + .andReturn("Authenticating as principal admin/admin with password.") + .anyTimes(); + + replay(result); + return result; + } + }); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + handler.testAdministratorCredentials(); + handler.close(); + } + + @Test(expected = KerberosRealmException.class) + public void testTestAdministratorCredentialsInvalidRealm() throws Exception { + MITKerberosOperationHandler handler = createMockBuilder(MITKerberosOperationHandler.class) + .addMockedMethod(KerberosOperationHandler.class.getDeclaredMethod("executeCommand", String[].class)) + .createNiceMock(); + + expect(handler.executeCommand(anyObject(String[].class))) + .andAnswer(new IAnswer<ShellCommandUtil.Result>() { + @Override + public ShellCommandUtil.Result answer() throws Throwable { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + + expect(result.getExitCode()).andReturn(1).anyTimes(); + expect(result.isSuccessful()).andReturn(false).anyTimes(); + expect(result.getStderr()) + .andReturn("kadmin: Missing parameters in krb5.conf required for kadmin client while initializing kadmin interface") + .anyTimes(); + expect(result.getStdout()) + .andReturn("Authenticating as principal admin/admin with password.") + .anyTimes(); + + replay(result); + return result; + } + }); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + handler.testAdministratorCredentials(); + handler.close(); + } + + @Test(expected = KerberosKDCConnectionException.class) + public void testTestAdministratorCredentialsKDCConnectionException() throws Exception { + MITKerberosOperationHandler handler = createMockBuilder(MITKerberosOperationHandler.class) + .addMockedMethod(KerberosOperationHandler.class.getDeclaredMethod("executeCommand", String[].class)) + .createNiceMock(); + + expect(handler.executeCommand(anyObject(String[].class))) + .andAnswer(new IAnswer<ShellCommandUtil.Result>() { + @Override + public ShellCommandUtil.Result answer() throws Throwable { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + + expect(result.getExitCode()).andReturn(1).anyTimes(); + expect(result.isSuccessful()).andReturn(false).anyTimes(); + expect(result.getStderr()) + .andReturn("kadmin: Cannot contact any KDC for requested realm while initializing kadmin interface") + .anyTimes(); + expect(result.getStdout()) + .andReturn("Authenticating as principal admin/admin with password.") + .anyTimes(); + + replay(result); + return result; + } + }); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + handler.testAdministratorCredentials(); + handler.close(); + } + + @Test + public void testTestAdministratorCredentialsNotFound() throws Exception { + MITKerberosOperationHandler handler = createMockBuilder(MITKerberosOperationHandler.class) + .addMockedMethod(KerberosOperationHandler.class.getDeclaredMethod("executeCommand", String[].class)) + .createNiceMock(); + + expect(handler.executeCommand(anyObject(String[].class))) + .andAnswer(new IAnswer<ShellCommandUtil.Result>() { + @Override + public ShellCommandUtil.Result answer() throws Throwable { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + + expect(result.getExitCode()).andReturn(0).anyTimes(); + expect(result.isSuccessful()).andReturn(true).anyTimes(); + expect(result.getStderr()) + .andReturn("get_principal: Principal does not exist while retrieving \"admin/[email protected]\".") + .anyTimes(); + expect(result.getStdout()) + .andReturn("Authenticating as principal admin/admin with password.") + .anyTimes(); + + replay(result); + return result; + } + }); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + Assert.assertFalse(handler.testAdministratorCredentials()); + handler.close(); + } + + @Test + public void testTestAdministratorCredentialsSuccess() throws Exception { + MITKerberosOperationHandler handler = createMockBuilder(MITKerberosOperationHandler.class) + .addMockedMethod(KerberosOperationHandler.class.getDeclaredMethod("executeCommand", String[].class)) + .createNiceMock(); + + expect(handler.executeCommand(anyObject(String[].class))) + .andAnswer(new IAnswer<ShellCommandUtil.Result>() { + @Override + public ShellCommandUtil.Result answer() throws Throwable { + ShellCommandUtil.Result result = createMock(ShellCommandUtil.Result.class); + + expect(result.getExitCode()).andReturn(0).anyTimes(); + expect(result.isSuccessful()).andReturn(true).anyTimes(); + expect(result.getStderr()) + .andReturn("") + .anyTimes(); + expect(result.getStdout()) + .andReturn("Authenticating as principal admin/admin with password.\n" + + "Principal: admin/[email protected]\n" + + "Expiration date: [never]\n" + + "Last password change: Thu Jan 08 13:09:52 UTC 2015\n" + + "Password expiration date: [none]\n" + + "Maximum ticket life: 1 day 00:00:00\n" + + "Maximum renewable life: 0 days 00:00:00\n" + + "Last modified: Thu Jan 08 13:09:52 UTC 2015 (root/[email protected])\n" + + "Last successful authentication: [never]\n" + + "Last failed authentication: [never]\n" + + "Failed password attempts: 0\n" + + "Number of keys: 6\n" + + "Key: vno 1, aes256-cts-hmac-sha1-96, no salt\n" + + "Key: vno 1, aes128-cts-hmac-sha1-96, no salt\n" + + "Key: vno 1, des3-cbc-sha1, no salt\n" + + "Key: vno 1, arcfour-hmac, no salt\n" + + "Key: vno 1, des-hmac-sha1, no salt\n" + + "Key: vno 1, des-cbc-md5, no salt\n" + + "MKey: vno 1\n" + + "Attributes:\n" + + "Policy: [none]") + .anyTimes(); + + replay(result); + return result; + } + }); + + replayAll(); + + handler.open(new KerberosCredential(DEFAULT_ADMIN_PRINCIPAL, DEFAULT_ADMIN_PASSWORD, null), DEFAULT_REALM); + handler.testAdministratorCredentials(); + handler.close(); + } + + @Test + @Ignore + public void testTestAdministratorCredentialsLive() throws KerberosOperationException { + MITKerberosOperationHandler handler = new MITKerberosOperationHandler(); + String principal = System.getProperty("principal"); + String password = System.getProperty("password"); + String realm = System.getProperty("realm"); + + if (principal == null) { + principal = DEFAULT_ADMIN_PRINCIPAL; + } + + if (password == null) { + password = DEFAULT_ADMIN_PASSWORD; + } + + if (realm == null) { + realm = DEFAULT_REALM; + } + + KerberosCredential credentials = new KerberosCredential(principal, password, null); + + handler.open(credentials, realm); + handler.testAdministratorCredentials(); + handler.close(); + } + } \ No newline at end of file
