TestSecureAliasMap.java
/**
* 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.hadoop.hdfs.server.aliasmap;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.qjournal.TestSecureNNWithQJM;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockManager;
import org.apache.hadoop.hdfs.server.common.blockaliasmap.BlockAliasMap;
import org.apache.hadoop.hdfs.server.datanode.DataNode;
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsDatasetSpi;
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeSpi;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.minikdc.MiniKdc;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
import org.apache.hadoop.test.GenericTestUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test DN & NN communication in secured hdfs with alias map.
*/
public class TestSecureAliasMap {
private static HdfsConfiguration baseConf;
private static File baseDir;
private static MiniKdc kdc;
private static String keystoresDir;
private static String sslConfDir;
private MiniDFSCluster cluster;
private HdfsConfiguration conf;
private FileSystem fs;
@BeforeAll
public static void init() throws Exception {
baseDir =
GenericTestUtils.getTestDir(TestSecureAliasMap.class.getSimpleName());
FileUtil.fullyDelete(baseDir);
assertTrue(baseDir.mkdirs());
Properties kdcConf = MiniKdc.createConf();
kdc = new MiniKdc(kdcConf, baseDir);
kdc.start();
baseConf = new HdfsConfiguration();
SecurityUtil.setAuthenticationMethod(
UserGroupInformation.AuthenticationMethod.KERBEROS, baseConf);
UserGroupInformation.setConfiguration(baseConf);
assertTrue(UserGroupInformation.isSecurityEnabled(),
"Expected configuration to enable security");
String userName = UserGroupInformation.getLoginUser().getShortUserName();
File keytabFile = new File(baseDir, userName + ".keytab");
String keytab = keytabFile.getAbsolutePath();
// Windows will not reverse name lookup "127.0.0.1" to "localhost".
String krbInstance = Path.WINDOWS ? "127.0.0.1" : "localhost";
kdc.createPrincipal(keytabFile, userName + "/" + krbInstance,
"HTTP/" + krbInstance);
keystoresDir = baseDir.getAbsolutePath();
sslConfDir = KeyStoreTestUtil.getClasspathDir(TestSecureNNWithQJM.class);
MiniDFSCluster.setupKerberosConfiguration(baseConf, userName,
kdc.getRealm(), keytab, keystoresDir, sslConfDir);
}
@AfterAll
public static void destroy() throws Exception {
if (kdc != null) {
kdc.stop();
}
FileUtil.fullyDelete(baseDir);
KeyStoreTestUtil.cleanupSSLConfig(keystoresDir, sslConfDir);
}
@AfterEach
public void shutdown() throws IOException {
IOUtils.cleanupWithLogger(null, fs);
if (cluster != null) {
cluster.shutdown();
cluster = null;
}
}
@Test
public void testSecureConnectionToAliasMap() throws Exception {
conf = new HdfsConfiguration(baseConf);
MiniDFSCluster.setupNamenodeProvidedConfiguration(conf);
conf.set(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS,
"127.0.0.1:" + NetUtils.getFreeSocketPort());
int numNodes = 1;
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(numNodes)
.storageTypes(
new StorageType[] {StorageType.DISK, StorageType.PROVIDED})
.build();
cluster.waitActive();
fs = cluster.getFileSystem();
FSNamesystem namesystem = cluster.getNamesystem();
BlockManager blockManager = namesystem.getBlockManager();
DataNode dn = cluster.getDataNodes().get(0);
FsDatasetSpi.FsVolumeReferences volumes =
dn.getFSDataset().getFsVolumeReferences();
FsVolumeSpi providedVolume = null;
for (FsVolumeSpi volume : volumes) {
if (volume.getStorageType().equals(StorageType.PROVIDED)) {
providedVolume = volume;
break;
}
}
String[] bps = providedVolume.getBlockPoolList();
assertEquals(1, bps.length, "Missing provided volume");
BlockAliasMap aliasMap = blockManager.getProvidedStorageMap().getAliasMap();
BlockAliasMap.Reader reader = aliasMap.getReader(null, bps[0]);
assertNotNull(reader, "Failed to create blockAliasMap reader");
}
}