/* * 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 static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import java.io.File; import java.lang.reflect.Method; import javax.persistence.EntityManager; import org.apache.ambari.server.audit.AuditLogger; import org.apache.ambari.server.controller.KerberosHelper; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.HostDAO; import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO; import org.apache.ambari.server.orm.entities.HostEntity; import org.apache.ambari.server.serveraction.ActionLog; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.utils.StageUtils; import org.apache.commons.io.FileUtils; import org.easymock.EasyMockSupport; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import junit.framework.Assert; public class ConfigureAmbariIdentitiesServerActionTest extends EasyMockSupport { @Rule public TemporaryFolder testFolder = new TemporaryFolder(); @Test public void installAmbariServerIdentity() throws Exception { installAmbariServerIdentity(createNiceMock(ActionLog.class), true); } @Test public void installAmbariServerIdentityWithNoAgentOnAmbariServer() throws Exception { installAmbariServerIdentity(createNiceMock(ActionLog.class), false); } @Test public void installAmbariServerIdentityWithNullActionLog() throws Exception { installAmbariServerIdentity(null, true); } private void installAmbariServerIdentity(ActionLog actionLog, boolean ambariServerHasAgent) throws Exception { String principal = "ambari-server@EXAMPLE.COM"; File srcKeytabFile = testFolder.newFile(); File destKeytabFile = new File(testFolder.getRoot().getAbsolutePath(), "ambari-server.keytab"); Injector injector = createInjector(); HostEntity hostEntity; if (ambariServerHasAgent) { KerberosPrincipalHostDAO kerberosPrincipalHostDAO = injector.getInstance(KerberosPrincipalHostDAO.class); expect(kerberosPrincipalHostDAO.exists(principal, 1L)).andReturn(false).once(); kerberosPrincipalHostDAO.create(principal, 1L); expectLastCall().once(); hostEntity = createMock(HostEntity.class); expect(hostEntity.getHostId()).andReturn(1L).once(); } else { hostEntity = null; } HostDAO hostDAO = injector.getInstance(HostDAO.class); expect(hostDAO.findByName(StageUtils.getHostName())).andReturn(hostEntity).once(); // Mock the methods that do the actual file manipulation to avoid having to deal with ambari-sudo.sh used in // ShellCommandUtil#mkdir, ShellCommandUtil#copyFile, etc.. Method methodCopyFile = ConfigureAmbariIdentitiesServerAction.class.getDeclaredMethod("copyFile", String.class, String.class); Method methodSetFileACL = ConfigureAmbariIdentitiesServerAction.class.getDeclaredMethod("setFileACL", String.class, String.class, boolean.class, boolean.class, String.class, boolean.class, boolean.class); ConfigureAmbariIdentitiesServerAction action = createMockBuilder(ConfigureAmbariIdentitiesServerAction.class) .addMockedMethod(methodCopyFile) .addMockedMethod(methodSetFileACL) .createMock(); action.copyFile(srcKeytabFile.getAbsolutePath(), destKeytabFile.getAbsolutePath()); expectLastCall().once(); action.setFileACL(destKeytabFile.getAbsolutePath(), "user1", true, true, "groupA", true, false); expectLastCall().once(); replayAll(); injector.injectMembers(action); action.installAmbariServerIdentity(principal, srcKeytabFile.getAbsolutePath(), destKeytabFile.getAbsolutePath(), "user1", true, true, "groupA", true, false, actionLog); verifyAll(); // There is no need to verify that the file was copied. We are not testing the ability to copy // and we have mocked the method that does the actual copying to avoid having to deal with // ambari-sudo.sh via the ShellCommandUtil class. } @Test public void configureJAAS() throws Exception { configureJAAS(createNiceMock(ActionLog.class)); } @Test public void configureJAASWithNullActionLog() throws Exception { configureJAAS(null); } private void configureJAAS(ActionLog actionLog) throws Exception { String principal = "ambari-server@EXAMPLE.COM"; String keytabFilePath = "/etc/security/keytabs/ambari.server.keytab"; File jaasConfFile = testFolder.newFile(); File jaasConfFileBak = new File(jaasConfFile.getAbsolutePath() + ".bak"); String originalJAASFileContent = "com.sun.security.jgss.krb5.initiate {\n" + " com.sun.security.auth.module.Krb5LoginModule required\n" + " renewTGT=false\n" + " doNotPrompt=true\n" + " useKeyTab=true\n" + " keyTab=\"/etc/security/keytabs/ambari.keytab\"\n" + " principal=\"ambari@EXAMPLE.COM\"\n" + " storeKey=true\n" + " useTicketCache=false;\n" + "};\n"; FileUtils.writeStringToFile(jaasConfFile, originalJAASFileContent); Injector injector = createInjector(); Method methodGetJAASConfFilePath = ConfigureAmbariIdentitiesServerAction.class.getDeclaredMethod("getJAASConfFilePath"); ConfigureAmbariIdentitiesServerAction action = createMockBuilder(ConfigureAmbariIdentitiesServerAction.class) .addMockedMethod(methodGetJAASConfFilePath) .createMock(); expect(action.getJAASConfFilePath()).andReturn(jaasConfFile.getAbsolutePath()); replayAll(); injector.injectMembers(action); action.configureJAAS(principal, keytabFilePath, actionLog); verifyAll(); Assert.assertEquals( "com.sun.security.jgss.krb5.initiate {\n" + " com.sun.security.auth.module.Krb5LoginModule required\n" + " renewTGT=false\n" + " doNotPrompt=true\n" + " useKeyTab=true\n" + " keyTab=\"/etc/security/keytabs/ambari.server.keytab\"\n" + " principal=\"ambari-server@EXAMPLE.COM\"\n" + " storeKey=true\n" + " useTicketCache=false;\n" + "};\n", FileUtils.readFileToString(jaasConfFile) ); // Ensure the backup file matches the original content Assert.assertEquals(originalJAASFileContent, FileUtils.readFileToString(jaasConfFileBak)); } private Injector createInjector() { return Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class)); bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class)); bind(AuditLogger.class).toInstance(createNiceMock(AuditLogger.class)); bind(Clusters.class).toInstance(createNiceMock(Clusters.class)); bind(KerberosHelper.class).toInstance(createNiceMock(KerberosHelper.class)); bind(HostDAO.class).toInstance(createMock(HostDAO.class)); bind(KerberosPrincipalHostDAO.class).toInstance(createMock(KerberosPrincipalHostDAO.class)); } }); } }