/*
* 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));
}
});
}
}