HDDS-5. Enable OzoneManager kerberos auth. Contributed by Ajay Kumar.

This commit is contained in:
Xiaoyu Yao 2018-05-14 09:36:57 -07:00
parent ff61931f91
commit d3920ecbb7
8 changed files with 254 additions and 53 deletions

View File

@ -1596,7 +1596,23 @@
<name>ozone.scm.kerberos.principal</name> <name>ozone.scm.kerberos.principal</name>
<value></value> <value></value>
<tag> OZONE, SECURITY</tag> <tag> OZONE, SECURITY</tag>
<description>The SCM service principal. Ex scm/_HOST@REALM.TLD.</description> <description>The SCM service principal. Ex scm/_HOST@REALM.COM</description>
</property>
<property>
<name>ozone.om.kerberos.keytab.file</name>
<value></value>
<tag> OZONE, SECURITY</tag>
<description> The keytab file used by KSM daemon to login as its
service principal. The principal name is configured with
hdds.ksm.kerberos.principal.
</description>
</property>
<property>
<name>ozone.om.kerberos.principal</name>
<value></value>
<tag> OZONE, SECURITY</tag>
<description>The KSM service principal. Ex ksm/_HOST@REALM.COM</description>
</property> </property>
<property> <property>
@ -1608,4 +1624,18 @@
<value>/etc/security/keytabs/HTTP.keytab</value> <value>/etc/security/keytabs/HTTP.keytab</value>
</property> </property>
<property>
<name>ozone.om.http.kerberos.principal</name>
<value>HTTP/_HOST@EXAMPLE.COM</value>
<description>
KSM http server kerberos principal.
</description>
</property>
<property>
<name>ozone.om.http.kerberos.keytab.file</name>
<value>/etc/security/keytabs/HTTP.keytab</value>
<description>
KSM http server kerberos keytab.
</description>
</property>
</configuration> </configuration>

View File

@ -175,4 +175,13 @@ private OMConfigKeys() {
public static final TimeDuration public static final TimeDuration
OZONE_OM_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT = OZONE_OM_LEADER_ELECTION_MINIMUM_TIMEOUT_DURATION_DEFAULT =
TimeDuration.valueOf(1, TimeUnit.SECONDS); TimeDuration.valueOf(1, TimeUnit.SECONDS);
public static final String OZONE_OM_KERBEROS_KEYTAB_FILE_KEY = "ozone.om."
+ "kerberos.keytab.file";
public static final String OZONE_OM_KERBEROS_PRINCIPAL_KEY = "ozone.om"
+ ".kerberos.principal";
public static final String OZONE_OM_WEB_AUTHENTICATION_KERBEROS_KEYTAB_FILE =
"ozone.om.http.kerberos.keytab.file";
public static final String OZONE_OM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY
= "ozone.om.http.kerberos.principal";
} }

View File

@ -18,6 +18,8 @@
package org.apache.hadoop.ozone.om.protocol; package org.apache.hadoop.ozone.om.protocol;
import org.apache.hadoop.ozone.om.helpers.OmMultipartCommitUploadPartInfo; import org.apache.hadoop.ozone.om.helpers.OmMultipartCommitUploadPartInfo;
import org.apache.hadoop.ozone.om.helpers.OmMultipartInfo; import org.apache.hadoop.ozone.om.helpers.OmMultipartInfo;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.helpers.OmBucketArgs; import org.apache.hadoop.ozone.om.helpers.OmBucketArgs;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs; import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
@ -28,14 +30,19 @@
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OpenKeySession; import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
import org.apache.hadoop.ozone.om.helpers.ServiceInfo; import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
import org.apache.hadoop.ozone.protocol.proto import org.apache.hadoop.ozone.protocol.proto
.OzoneManagerProtocolProtos.OzoneAclInfo; .OzoneManagerProtocolProtos.OzoneAclInfo;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import org.apache.hadoop.security.KerberosInfo;
/** /**
* Protocol to talk to OM. * Protocol to talk to OM.
*/ */
@KerberosInfo(
serverPrincipal = OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY)
public interface OzoneManagerProtocol { public interface OzoneManagerProtocol {
/** /**

View File

@ -18,9 +18,11 @@
package org.apache.hadoop.ozone.om.protocolPB; package org.apache.hadoop.ozone.om.protocolPB;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ipc.ProtocolInfo; import org.apache.hadoop.ipc.ProtocolInfo;
import org.apache.hadoop.ozone.protocol.proto import org.apache.hadoop.ozone.protocol.proto
.OzoneManagerProtocolProtos.OzoneManagerService; .OzoneManagerProtocolProtos.OzoneManagerService;
import org.apache.hadoop.security.KerberosInfo;
/** /**
* Protocol used to communicate with OM. * Protocol used to communicate with OM.
@ -28,6 +30,8 @@
@ProtocolInfo(protocolName = @ProtocolInfo(protocolName =
"org.apache.hadoop.ozone.protocol.OzoneManagerProtocol", "org.apache.hadoop.ozone.protocol.OzoneManagerProtocol",
protocolVersion = 1) protocolVersion = 1)
@KerberosInfo(
serverPrincipal = OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY)
@InterfaceAudience.Private @InterfaceAudience.Private
public interface OzoneManagerProtocolPB public interface OzoneManagerProtocolPB
extends OzoneManagerService.BlockingInterface { extends OzoneManagerService.BlockingInterface {

View File

@ -469,7 +469,8 @@ private void initializeOmStorage(OMStorage omStorage) throws IOException{
* *
* @throws IOException * @throws IOException
*/ */
private OzoneManager createOM() throws IOException { private OzoneManager createOM()
throws IOException, AuthenticationException {
configureOM(); configureOM();
OMStorage omStore = new OMStorage(conf); OMStorage omStore = new OMStorage(conf);
initializeOmStorage(omStore); initializeOmStorage(omStore);

View File

@ -22,28 +22,38 @@
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic; import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.hdds.HddsConfigKeys;
import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.scm.ScmConfigKeys; import org.apache.hadoop.hdds.scm.ScmConfigKeys;
import org.apache.hadoop.hdds.scm.ScmInfo; import org.apache.hadoop.hdds.scm.ScmInfo;
import org.apache.hadoop.hdds.scm.server.SCMStorage; import org.apache.hadoop.hdds.scm.server.SCMStorage;
import org.apache.hadoop.hdds.scm.server.StorageContainerManager; import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
import org.apache.hadoop.minikdc.MiniKdc; import org.apache.hadoop.minikdc.MiniKdc;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.OMStorage;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.security.KerberosAuthException; import org.apache.hadoop.security.KerberosAuthException;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.authentication.util.KerberosUtil; import org.apache.hadoop.security.authentication.util.KerberosUtil;
import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.test.GenericTestUtils.LogCapturer;
import org.apache.hadoop.test.LambdaTestUtils; import org.apache.hadoop.test.LambdaTestUtils;
import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.Timeout;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -56,13 +66,23 @@ public final class TestSecureOzoneCluster {
private Logger LOGGER = LoggerFactory private Logger LOGGER = LoggerFactory
.getLogger(TestSecureOzoneCluster.class); .getLogger(TestSecureOzoneCluster.class);
@Rule
public Timeout timeout = new Timeout(80000);
private MiniKdc miniKdc; private MiniKdc miniKdc;
private OzoneConfiguration conf; private OzoneConfiguration conf;
private File workDir; private File workDir;
private static Properties securityProperties; private static Properties securityProperties;
private File scmKeytab; private File scmKeytab;
private File spnegoKeytab; private File spnegoKeytab;
private File omKeyTab;
private String curUser; private String curUser;
private StorageContainerManager scm;
private OzoneManager om;
private static String clusterId;
private static String scmId;
private static String omId;
@Before @Before
public void init() { public void init() {
@ -71,6 +91,10 @@ public void init() {
startMiniKdc(); startMiniKdc();
setSecureConfig(conf); setSecureConfig(conf);
createCredentialsInKDC(conf, miniKdc); createCredentialsInKDC(conf, miniKdc);
clusterId = UUID.randomUUID().toString();
scmId = UUID.randomUUID().toString();
omId = UUID.randomUUID().toString();
} catch (IOException e) { } catch (IOException e) {
LOGGER.error("Failed to initialize TestSecureOzoneCluster", e); LOGGER.error("Failed to initialize TestSecureOzoneCluster", e);
} catch (Exception e) { } catch (Exception e) {
@ -78,12 +102,31 @@ public void init() {
} }
} }
@After
public void stop() {
try {
stopMiniKdc();
if (scm != null) {
scm.stop();
}
if (om != null) {
om.stop();
}
} catch (Exception e) {
LOGGER.error("Failed to stop TestSecureOzoneCluster", e);
}
}
private void createCredentialsInKDC(Configuration conf, MiniKdc miniKdc) private void createCredentialsInKDC(Configuration conf, MiniKdc miniKdc)
throws Exception { throws Exception {
createPrincipal(scmKeytab, createPrincipal(scmKeytab,
conf.get(ScmConfigKeys.OZONE_SCM_KERBEROS_PRINCIPAL_KEY)); conf.get(ScmConfigKeys.OZONE_SCM_KERBEROS_PRINCIPAL_KEY));
createPrincipal(spnegoKeytab, createPrincipal(spnegoKeytab,
conf.get(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY)); conf.get(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY),
conf.get(OMConfigKeys.OZONE_OM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY));
createPrincipal(omKeyTab,
conf.get(OMConfigKeys
.OZONE_OM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY));
} }
private void createPrincipal(File keytab, String... principal) private void createPrincipal(File keytab, String... principal)
@ -99,9 +142,13 @@ private void startMiniKdc() throws Exception {
miniKdc.start(); miniKdc.start();
} }
private void stopMiniKdc() throws Exception {
miniKdc.stop();
}
private void setSecureConfig(Configuration conf) throws IOException { private void setSecureConfig(Configuration conf) throws IOException {
conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true); conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
String host = KerberosUtil.getLocalHostName(); String host = InetAddress.getLocalHost().getCanonicalHostName();
String realm = miniKdc.getRealm(); String realm = miniKdc.getRealm();
curUser = UserGroupInformation.getCurrentUser() curUser = UserGroupInformation.getCurrentUser()
.getUserName(); .getUserName();
@ -114,59 +161,56 @@ private void setSecureConfig(Configuration conf) throws IOException {
conf.set(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY, conf.set(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY,
"HTTP_SCM/" + host + "@" + realm); "HTTP_SCM/" + host + "@" + realm);
conf.set(OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY,
"om/" + host + "@" + realm);
conf.set(OMConfigKeys.OZONE_OM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY,
"HTTP_KSM/" + host + "@" + realm);
scmKeytab = new File(workDir, "scm.keytab"); scmKeytab = new File(workDir, "scm.keytab");
spnegoKeytab = new File(workDir, "http.keytab"); spnegoKeytab = new File(workDir, "http.keytab");
omKeyTab = new File(workDir, "om.keytab");
conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY, conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY,
scmKeytab.getAbsolutePath()); scmKeytab.getAbsolutePath());
conf.set(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_KEYTAB_FILE_KEY, conf.set(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_KEYTAB_FILE_KEY,
spnegoKeytab.getAbsolutePath()); spnegoKeytab.getAbsolutePath());
conf.set(OMConfigKeys.OZONE_OM_KERBEROS_KEYTAB_FILE_KEY,
omKeyTab.getAbsolutePath());
} }
@Test @Test
public void testSecureScmStartupSuccess() throws Exception { public void testSecureScmStartupSuccess() throws Exception {
final String path = GenericTestUtils
.getTempPath(UUID.randomUUID().toString()); initSCM();
Path scmPath = Paths.get(path, "scm-meta"); scm = StorageContainerManager.createSCM(null, conf);
conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, scmPath.toString());
conf.setBoolean(OzoneConfigKeys.OZONE_ENABLED, true);
SCMStorage scmStore = new SCMStorage(conf);
String clusterId = UUID.randomUUID().toString();
String scmId = UUID.randomUUID().toString();
scmStore.setClusterId(clusterId);
scmStore.setScmId(scmId);
// writes the version file properties
scmStore.initialize();
StorageContainerManager scm = StorageContainerManager.createSCM(null, conf);
//Reads the SCM Info from SCM instance //Reads the SCM Info from SCM instance
ScmInfo scmInfo = scm.getClientProtocolServer().getScmInfo(); ScmInfo scmInfo = scm.getClientProtocolServer().getScmInfo();
Assert.assertEquals(clusterId, scmInfo.getClusterId()); Assert.assertEquals(clusterId, scmInfo.getClusterId());
Assert.assertEquals(scmId, scmInfo.getScmId()); Assert.assertEquals(scmId, scmInfo.getScmId());
} }
@Test private void initSCM()
public void testSecureScmStartupFailure() throws Exception { throws IOException, AuthenticationException {
final String path = GenericTestUtils final String path = GenericTestUtils
.getTempPath(UUID.randomUUID().toString()); .getTempPath(UUID.randomUUID().toString());
Path scmPath = Paths.get(path, "scm-meta"); Path scmPath = Paths.get(path, "scm-meta");
conf.set(HddsConfigKeys.OZONE_METADATA_DIRS, scmPath.toString());
OzoneConfiguration conf = new OzoneConfiguration();
conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, scmPath.toString());
conf.setBoolean(OzoneConfigKeys.OZONE_ENABLED, true); conf.setBoolean(OzoneConfigKeys.OZONE_ENABLED, true);
conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_PRINCIPAL_KEY,
"scm@" + miniKdc.getRealm());
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
"kerberos");
SCMStorage scmStore = new SCMStorage(conf); SCMStorage scmStore = new SCMStorage(conf);
String clusterId = UUID.randomUUID().toString();
String scmId = UUID.randomUUID().toString();
scmStore.setClusterId(clusterId); scmStore.setClusterId(clusterId);
scmStore.setScmId(scmId); scmStore.setScmId(scmId);
// writes the version file properties // writes the version file properties
scmStore.initialize(); scmStore.initialize();
}
@Test
public void testSecureScmStartupFailure() throws Exception {
initSCM();
conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY, "");
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
"kerberos");
LambdaTestUtils.intercept(IOException.class, LambdaTestUtils.intercept(IOException.class,
"Running in secure mode, but config doesn't have a keytab", "Running in secure mode, but config doesn't have a keytab",
() -> { () -> {
@ -178,28 +222,82 @@ public void testSecureScmStartupFailure() throws Exception {
conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY, conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY,
"/etc/security/keytabs/scm.keytab"); "/etc/security/keytabs/scm.keytab");
testCommonKerberosFailures(
() -> StorageContainerManager.createSCM(null, conf));
}
private void testCommonKerberosFailures(Callable callable) throws Exception {
LambdaTestUtils.intercept(KerberosAuthException.class, "failure " LambdaTestUtils.intercept(KerberosAuthException.class, "failure "
+ "to login: for principal:", + "to login: for principal:", callable);
() -> {
StorageContainerManager.createSCM(null, conf);
});
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
"OAuth2"); "OAuth2");
LambdaTestUtils.intercept(IllegalArgumentException.class, "Invalid" LambdaTestUtils.intercept(IllegalArgumentException.class, "Invalid"
+ " attribute value for hadoop.security.authentication of OAuth2", + " attribute value for hadoop.security.authentication of OAuth2",
() -> { callable);
StorageContainerManager.createSCM(null, conf);
});
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
"KERBEROS_SSL"); "KERBEROS_SSL");
LambdaTestUtils.intercept(AuthenticationException.class, LambdaTestUtils.intercept(AuthenticationException.class,
"KERBEROS_SSL authentication method not support.", "KERBEROS_SSL authentication method not",
() -> { callable);
StorageContainerManager.createSCM(null, conf); }
});
/**
* Tests the secure KSM Initialization Failure.
*
* @throws IOException
*/
@Test
public void testSecureKsmInitializationFailure() throws Exception {
initSCM();
// Create a secure SCM instance as om client will connect to it
scm = StorageContainerManager.createSCM(null, conf);
final String path = GenericTestUtils
.getTempPath(UUID.randomUUID().toString());
OMStorage ksmStore = new OMStorage(conf);
ksmStore.setClusterId("testClusterId");
ksmStore.setScmId("testScmId");
// writes the version file properties
ksmStore.initialize();
conf.set(OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY,
"non-existent-user@EXAMPLE.com");
testCommonKerberosFailures(() -> OzoneManager.createOm(null, conf));
}
/**
* Tests the secure KSM Initialization success.
*
* @throws IOException
*/
@Test
public void testSecureKsmInitializationSuccess() throws Exception {
initSCM();
// Create a secure SCM instance as om client will connect to it
scm = StorageContainerManager.createSCM(null, conf);
LogCapturer logs = LogCapturer.captureLogs(OzoneManager.LOG);
GenericTestUtils
.setLogLevel(LoggerFactory.getLogger(OzoneManager.class.getName()),
org.slf4j.event.Level.INFO);
final String path = GenericTestUtils
.getTempPath(UUID.randomUUID().toString());
Path metaDirPath = Paths.get(path, "om-meta");
OMStorage omStore = new OMStorage(conf);
omStore.setClusterId("testClusterId");
omStore.setScmId("testScmId");
// writes the version file properties
omStore.initialize();
try {
om = OzoneManager.createOm(null, conf);
} catch (Exception ex) {
// Expects timeout failure from scmClient in KSM but KSM user login via
// kerberos should succeed
Assert.assertTrue(logs.getOutput().contains("KSM login successful"));
}
} }
} }

View File

@ -53,6 +53,7 @@
import org.apache.hadoop.ozone.audit.AuditMessage; import org.apache.hadoop.ozone.audit.AuditMessage;
import org.apache.hadoop.ozone.audit.Auditor; import org.apache.hadoop.ozone.audit.Auditor;
import org.apache.hadoop.ozone.audit.OMAction; import org.apache.hadoop.ozone.audit.OMAction;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.hadoop.ozone.common.Storage.StorageState; import org.apache.hadoop.ozone.common.Storage.StorageState;
import org.apache.hadoop.ozone.om.exceptions.OMException; import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes; import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
@ -86,7 +87,10 @@
import org.apache.hadoop.ozone.security.acl.OzoneObj.ResourceType; import org.apache.hadoop.ozone.security.acl.OzoneObj.ResourceType;
import org.apache.hadoop.ozone.security.acl.OzoneObjInfo; import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
import org.apache.hadoop.ozone.security.acl.RequestContext; import org.apache.hadoop.ozone.security.acl.RequestContext;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.util.GenericOptionsParser; import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.JvmPauseMonitor; import org.apache.hadoop.util.JvmPauseMonitor;
import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.ReflectionUtils;
@ -97,6 +101,7 @@
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.ws.rs.HEAD;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -140,6 +145,11 @@
import static org.apache.hadoop.ozone.protocol.proto import static org.apache.hadoop.ozone.protocol.proto
.OzoneManagerProtocolProtos.OzoneManagerService .OzoneManagerProtocolProtos.OzoneManagerService
.newReflectiveBlockingService; .newReflectiveBlockingService;
import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneManagerService.newReflectiveBlockingService;
import static org.apache.hadoop.ozone.om.OMConfigKeys
.OZONE_OM_KERBEROS_KEYTAB_FILE_KEY;
import static org.apache.hadoop.ozone.om.OMConfigKeys
.OZONE_OM_KERBEROS_PRINCIPAL_KEY;
import static org.apache.hadoop.util.ExitUtil.terminate; import static org.apache.hadoop.util.ExitUtil.terminate;
/** /**
@ -148,7 +158,7 @@
@InterfaceAudience.LimitedPrivate({"HDFS", "CBLOCK", "OZONE", "HBASE"}) @InterfaceAudience.LimitedPrivate({"HDFS", "CBLOCK", "OZONE", "HBASE"})
public final class OzoneManager extends ServiceRuntimeInfoImpl public final class OzoneManager extends ServiceRuntimeInfoImpl
implements OzoneManagerProtocol, OMMXBean, Auditor { implements OzoneManagerProtocol, OMMXBean, Auditor {
private static final Logger LOG = public static final Logger LOG =
LoggerFactory.getLogger(OzoneManager.class); LoggerFactory.getLogger(OzoneManager.class);
private static final AuditLogger AUDIT = private static final AuditLogger AUDIT =
@ -193,14 +203,16 @@ private OzoneManager(OzoneConfiguration conf) throws IOException {
configuration = conf; configuration = conf;
omStorage = new OMStorage(conf); omStorage = new OMStorage(conf);
omId = omStorage.getOmId(); omId = omStorage.getOmId();
scmBlockClient = getScmBlockClient(configuration);
scmContainerClient = getScmContainerClient(configuration);
if (omStorage.getState() != StorageState.INITIALIZED) { if (omStorage.getState() != StorageState.INITIALIZED) {
throw new OMException("OM not initialized.", throw new OMException("OM not initialized.",
ResultCodes.OM_NOT_INITIALIZED); ResultCodes.OM_NOT_INITIALIZED);
} }
scmContainerClient = getScmContainerClient(configuration);
// verifies that the SCM info in the OM Version file is correct. // verifies that the SCM info in the OM Version file is correct.
scmBlockClient = getScmBlockClient(configuration);
ScmInfo scmInfo = scmBlockClient.getScmInfo(); ScmInfo scmInfo = scmBlockClient.getScmInfo();
if (!(scmInfo.getClusterId().equals(omStorage.getClusterID()) && scmInfo if (!(scmInfo.getClusterId().equals(omStorage.getClusterID()) && scmInfo
.getScmId().equals(omStorage.getScmId()))) { .getScmId().equals(omStorage.getScmId()))) {
@ -301,6 +313,35 @@ private File getMetricsStorageFile() {
} }
/**
* Login KSM service user if security and Kerberos are enabled.
*
* @param conf
* @throws IOException, AuthenticationException
*/
private static void loginKSMUser(OzoneConfiguration conf)
throws IOException, AuthenticationException {
if (SecurityUtil.getAuthenticationMethod(conf).equals
(AuthenticationMethod.KERBEROS)) {
LOG.debug("Ozone security is enabled. Attempting login for KSM user. "
+ "Principal: {},keytab: {}", conf.get
(OZONE_OM_KERBEROS_PRINCIPAL_KEY),
conf.get(OZONE_OM_KERBEROS_KEYTAB_FILE_KEY));
UserGroupInformation.setConfiguration(conf);
InetSocketAddress socAddr = getOmAddress(conf);
SecurityUtil.login(conf, OZONE_OM_KERBEROS_KEYTAB_FILE_KEY,
OZONE_OM_KERBEROS_PRINCIPAL_KEY, socAddr.getHostName());
} else {
throw new AuthenticationException(SecurityUtil.getAuthenticationMethod
(conf) + " authentication method not supported. KSM user login "
+ "failed.");
}
LOG.info("KSM login successful.");
}
/** /**
* Create a scm block client, used by putKey() and getKey(). * Create a scm block client, used by putKey() and getKey().
* *
@ -418,15 +459,16 @@ private static void printUsage(PrintStream out) {
* @param argv Command line arguments * @param argv Command line arguments
* @param conf OzoneConfiguration * @param conf OzoneConfiguration
* @return OM instance * @return OM instance
* @throws IOException in case OM instance creation fails. * @throws IOException, AuthenticationException in case OM instance
* creation fails.
*/ */
@VisibleForTesting @VisibleForTesting
public static OzoneManager createOm( public static OzoneManager createOm(
String[] argv, OzoneConfiguration conf) throws IOException { String[] argv, OzoneConfiguration conf)
throws IOException, AuthenticationException {
return createOm(argv, conf, false); return createOm(argv, conf, false);
} }
/** /**
* Constructs OM instance based on command line arguments. * Constructs OM instance based on command line arguments.
* *
@ -434,10 +476,12 @@ public static OzoneManager createOm(
* @param conf OzoneConfiguration * @param conf OzoneConfiguration
* @param printBanner if true then log a verbose startup message. * @param printBanner if true then log a verbose startup message.
* @return OM instance * @return OM instance
* @throws IOException in case OM instance creation fails. * @throws IOException, AuthenticationException in case OM instance
* creation fails.
*/ */
private static OzoneManager createOm(String[] argv, private static OzoneManager createOm(String[] argv,
OzoneConfiguration conf, boolean printBanner) throws IOException { OzoneConfiguration conf, boolean printBanner)
throws IOException, AuthenticationException {
if (!isHddsEnabled(conf)) { if (!isHddsEnabled(conf)) {
System.err.println("OM cannot be started in secure mode or when " + System.err.println("OM cannot be started in secure mode or when " +
OZONE_ENABLED + " is set to false"); OZONE_ENABLED + " is set to false");
@ -449,6 +493,10 @@ private static OzoneManager createOm(String[] argv,
terminate(1); terminate(1);
return null; return null;
} }
// Authenticate KSM if security is enabled
if (conf.getBoolean(OzoneConfigKeys.OZONE_SECURITY_ENABLED_KEY, true)) {
loginKSMUser(conf);
}
switch (startOpt) { switch (startOpt) {
case INIT: case INIT:
if (printBanner) { if (printBanner) {
@ -654,7 +702,12 @@ public void start() throws IOException {
keyManager.start(configuration); keyManager.start(configuration);
httpServer = new OzoneManagerHttpServer(configuration, this); httpServer = new OzoneManagerHttpServer(configuration, this);
httpServer.start(); try {
httpServer.start();
} catch (Exception ex) {
// Allow OM to start as Http Server failure is not fatal.
LOG.error("OM HttpServer failed to start.", ex);
}
registerMXBean(); registerMXBean();
// Start jvm monitor // Start jvm monitor

View File

@ -18,7 +18,6 @@
package org.apache.hadoop.ozone.om; package org.apache.hadoop.ozone.om;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.hadoop.ozone.OzoneConsts; import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.hdds.server.BaseHttpServer; import org.apache.hadoop.hdds.server.BaseHttpServer;
@ -65,11 +64,11 @@ public OzoneManagerHttpServer(Configuration conf, OzoneManager om)
} }
@Override protected String getKeytabFile() { @Override protected String getKeytabFile() {
return OMConfigKeys.OZONE_OM_KEYTAB_FILE; return OMConfigKeys.OZONE_OM_WEB_AUTHENTICATION_KERBEROS_KEYTAB_FILE;
} }
@Override protected String getSpnegoPrincipal() { @Override protected String getSpnegoPrincipal() {
return OzoneConfigKeys.OZONE_SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL; return OMConfigKeys.OZONE_OM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY;
} }
@Override protected String getEnabledKey() { @Override protected String getEnabledKey() {