| /** |
| * 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.namenode; |
| |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.fs.BatchedRemoteIterator; |
| import org.apache.hadoop.fs.CommonConfigurationKeys; |
| import org.apache.hadoop.fs.permission.FsPermission; |
| import org.apache.hadoop.fs.FileSystem; |
| import org.apache.hadoop.fs.Path; |
| import org.apache.hadoop.hdfs.DistributedFileSystem; |
| import org.apache.hadoop.hdfs.DFSTestUtil; |
| import org.apache.hadoop.hdfs.MiniDFSCluster; |
| import org.apache.hadoop.hdfs.HdfsConfiguration; |
| import org.apache.hadoop.hdfs.DFSConfigKeys; |
| import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo; |
| import org.apache.hadoop.hdfs.protocol.CachePoolEntry; |
| import org.apache.hadoop.hdfs.protocol.CachePoolInfo; |
| import org.apache.hadoop.hdfs.protocol.HdfsConstants; |
| import org.apache.hadoop.hdfs.server.protocol.DatanodeStorageReport; |
| import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols; |
| import org.apache.hadoop.ipc.RPC; |
| import org.apache.hadoop.ipc.Server; |
| import org.apache.hadoop.security.AccessControlException; |
| import org.apache.hadoop.security.UserGroupInformation; |
| import org.apache.hadoop.test.GenericTestUtils; |
| import org.apache.hadoop.security.token.Token; |
| import org.apache.hadoop.test.GenericTestUtils.LogCapturer; |
| import java.io.IOException; |
| import java.security.PrivilegedExceptionAction; |
| |
| import org.junit.After; |
| import static org.junit.Assert.assertEquals; |
| import org.junit.Before; |
| import org.junit.Test; |
| import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_ALWAYS_USE_KEY; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.fail; |
| import org.mockito.Mockito; |
| |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.Mockito.doThrow; |
| import static org.mockito.Mockito.spy; |
| import static org.mockito.Mockito.when; |
| |
| public class TestAuditLoggerWithCommands { |
| |
| static final int NUM_DATA_NODES = 2; |
| static final long seed = 0xDEADBEEFL; |
| static final int blockSize = 8192; |
| private static MiniDFSCluster cluster = null; |
| private static FileSystem fileSys = null; |
| private static FileSystem fs2 = null; |
| private static FileSystem fs = null; |
| private static LogCapturer auditlog; |
| static Configuration conf; |
| static UserGroupInformation user1; |
| static UserGroupInformation user2; |
| private static NamenodeProtocols proto; |
| |
| @Before |
| public void initialize() throws Exception { |
| // start a cluster |
| conf = new HdfsConfiguration(); |
| conf.setBoolean(DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY, true); |
| conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_KEY,true); |
| conf.setBoolean(DFS_NAMENODE_DELEGATION_TOKEN_ALWAYS_USE_KEY, true); |
| conf.setBoolean( |
| CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION, true); |
| cluster = |
| new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATA_NODES).build(); |
| cluster.waitActive(); |
| user1 = |
| UserGroupInformation.createUserForTesting("theDoctor", |
| new String[]{"tardis"}); |
| user2 = |
| UserGroupInformation.createUserForTesting("theEngineer", |
| new String[]{"hadoop"}); |
| auditlog = LogCapturer.captureLogs(FSNamesystem.AUDIT_LOG); |
| proto = cluster.getNameNodeRpc(); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| fs2 = DFSTestUtil.getFileSystemAs(user2, conf); |
| fs = cluster.getFileSystem(); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| Server.getCurCall().set(null); |
| fs.close(); |
| fs2.close(); |
| fileSys.close(); |
| cluster.shutdown(); |
| } |
| |
| @Test |
| public void testGetContentSummary() throws IOException { |
| Path dir1 = new Path("/dir1"); |
| Path dir2 = new Path("/dir2"); |
| String acePattern = |
| ".*allowed=false.*ugi=theEngineer.*cmd=contentSummary.*"; |
| fs.mkdirs(dir1,new FsPermission((short)0600)); |
| fs.mkdirs(dir2,new FsPermission((short)0600)); |
| fs.setOwner(dir1, user1.getUserName(), user1.getPrimaryGroupName()); |
| fs.setOwner(dir2, user2.getUserName(), user2.getPrimaryGroupName()); |
| try { |
| fs2.getContentSummary(new Path("/")); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| int length = verifyAuditLogs(acePattern); |
| try { |
| fs2.getContentSummary(new Path("/dir3")); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log from getContentSummary", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testSetQuota() throws Exception { |
| Path path = new Path("/testdir/testdir1"); |
| fs.mkdirs(path); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| verifySetQuota(path, HdfsConstants.QUOTA_RESET, |
| HdfsConstants.QUOTA_DONT_SET); |
| verifySetQuota(path, HdfsConstants.QUOTA_DONT_SET, |
| HdfsConstants.QUOTA_RESET); |
| verifySetQuota(path, HdfsConstants.QUOTA_DONT_SET, |
| HdfsConstants.BYTES_IN_INTEGER); |
| verifySetQuota(path, HdfsConstants.BYTES_IN_INTEGER, |
| HdfsConstants.BYTES_IN_INTEGER); |
| fileSys.close(); |
| } |
| |
| private void verifySetQuota(Path path, long nsQuota, long ssQuota) |
| throws IOException { |
| String operationName = cluster.getNamesystem().getQuotaCommand( |
| nsQuota, ssQuota); |
| String acePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=.*" + operationName + ".*"; |
| try { |
| ((DistributedFileSystem) fileSys).setQuota(path, nsQuota, ssQuota); |
| fail("The operation should have failed"); |
| } catch (AccessControlException ace) { |
| } |
| verifyAuditLogs(acePattern); |
| } |
| |
| @Test |
| public void testConcat() throws Exception { |
| Path file1 = new Path("/file1"); |
| Path file2 = new Path("/file2"); |
| Path targetDir = new Path("/target"); |
| String acePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=concat.*"; |
| fs.createNewFile(file1); |
| fs.createNewFile(file2); |
| fs.mkdirs(targetDir); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| fileSys.concat(targetDir, new Path[]{file1, file2}); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| int length = verifyAuditLogs(acePattern); |
| fileSys.close(); |
| try { |
| fileSys.concat(targetDir, new Path[]{file1, file2}); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log from Concat", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testCreateRenameSnapShot() throws Exception { |
| Path srcDir = new Path("/src"); |
| String aceCreatePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=createSnapshot.*"; |
| String aceRenamePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=renameSnapshot.*"; |
| fs.mkdirs(srcDir); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| ((DistributedFileSystem)fs).allowSnapshot(srcDir); |
| try { |
| fileSys.createSnapshot(srcDir); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| verifyAuditLogs(aceCreatePattern); |
| try { |
| Path s1 = fs.createSnapshot(srcDir); |
| fileSys.renameSnapshot(srcDir, s1.getName(), "test"); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| int length = auditlog.getOutput().split("\n").length; |
| verifyAuditLogs(aceRenamePattern); |
| try { |
| fs.createSnapshot(new Path("/test1")); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| try { |
| fs.renameSnapshot(new Path("/test1"), "abc", "test2"); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testDeleteSnapshot() throws Exception { |
| Path srcDir = new Path("/src"); |
| Path s1; |
| fs.mkdirs(srcDir); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| ((DistributedFileSystem)fs).allowSnapshot(srcDir); |
| try { |
| s1 = fs.createSnapshot(srcDir); |
| fileSys.deleteSnapshot(srcDir, s1.getName()); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| String aceDeletePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=deleteSnapshot.*"; |
| int length = verifyAuditLogs(aceDeletePattern); |
| fileSys.close(); |
| try { |
| s1 = fs.createSnapshot(srcDir); |
| fileSys.deleteSnapshot(srcDir, s1.getName()); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length+1 == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testAllowSnapshot() throws Exception { |
| Path srcDir = new Path(System.getProperty("user.dir"), "/src"); |
| fs.mkdirs(srcDir); |
| String pattern = |
| ".*allowed=true.*ugi=" + |
| System.getProperty("user.name")+".*cmd=allowSnapshot.*"; |
| try { |
| ((DistributedFileSystem)fs).allowSnapshot(srcDir); |
| verifyAuditLogs(pattern); |
| } catch (Exception e) { |
| fail("The operation should not have failed with Exception"); |
| } |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem)fileSys).allowSnapshot(srcDir); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| pattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=allowSnapshot.*"; |
| verifyAuditLogs(pattern); |
| fs.delete(srcDir, true); |
| fileSys.close(); |
| } |
| |
| @Test |
| public void testDisallowSnapshot() throws Exception { |
| Path srcDir = new Path(System.getProperty("user.dir"), "/src"); |
| fs.mkdirs(srcDir); |
| cluster.getNamesystem().allowSnapshot(srcDir.toString()); |
| String pattern = |
| ".*allowed=true.*ugi=" + |
| System.getProperty("user.name")+".*cmd=disallowSnapshot.*"; |
| try { |
| ((DistributedFileSystem)fs).disallowSnapshot(srcDir); |
| verifyAuditLogs(pattern); |
| } catch (Exception e) { |
| fail("The operation should not have failed with Exception"); |
| } |
| cluster.getNamesystem().allowSnapshot(srcDir.toString()); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem)fileSys).disallowSnapshot(srcDir); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| pattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=disallowSnapshot.*"; |
| verifyAuditLogs(pattern); |
| } |
| fileSys.close(); |
| } |
| |
| @Test |
| public void testAddCacheDirective() throws Exception { |
| removeExistingCachePools(null); |
| proto.addCachePool(new CachePoolInfo("pool1"). |
| setMode(new FsPermission((short) 0))); |
| CacheDirectiveInfo alpha = new CacheDirectiveInfo.Builder(). |
| setPath(new Path(System.getProperty("user.dir"), "/alpha")). |
| setPool("pool1"). |
| build(); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem)fileSys).addCacheDirective(alpha); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| String aceAddCachePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=addCache.*"; |
| int length = verifyAuditLogs(aceAddCachePattern); |
| try { |
| fileSys.close(); |
| ((DistributedFileSystem)fileSys).addCacheDirective(alpha); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testModifyCacheDirective() throws Exception { |
| removeExistingCachePools(null); |
| proto.addCachePool(new CachePoolInfo("pool1"). |
| setMode(new FsPermission((short) 0))); |
| CacheDirectiveInfo alpha = new CacheDirectiveInfo.Builder(). |
| setPath(new Path("/alpha")). |
| setPool("pool1"). |
| build(); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| Long id = |
| ((DistributedFileSystem)fs).addCacheDirective(alpha); |
| try { |
| ((DistributedFileSystem)fileSys).modifyCacheDirective( |
| new CacheDirectiveInfo.Builder(). |
| setId(id). |
| setReplication((short) 1). |
| build()); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| String aceModifyCachePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=modifyCache.*"; |
| verifyAuditLogs(aceModifyCachePattern); |
| fileSys.close(); |
| try { |
| ((DistributedFileSystem)fileSys).modifyCacheDirective( |
| new CacheDirectiveInfo.Builder(). |
| setId(id). |
| setReplication((short) 1). |
| build()); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| } |
| |
| @Test |
| public void testRemoveCacheDirective() throws Exception { |
| removeExistingCachePools(null); |
| proto.addCachePool(new CachePoolInfo("pool1"). |
| setMode(new FsPermission((short) 0))); |
| CacheDirectiveInfo alpha = new CacheDirectiveInfo.Builder(). |
| setPath(new Path("/alpha")). |
| setPool("pool1"). |
| build(); |
| String aceRemoveCachePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=removeCache.*"; |
| int length = -1; |
| Long id =((DistributedFileSystem)fs).addCacheDirective(alpha); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem) fileSys).removeCacheDirective(id); |
| fail("It should have failed with an AccessControlException"); |
| } catch (AccessControlException ace) { |
| length = verifyAuditLogs(aceRemoveCachePattern); |
| } |
| try { |
| fileSys.close(); |
| ((DistributedFileSystem)fileSys).removeCacheDirective(id); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testGetSnapshotDiffReport() throws Exception { |
| Path snapshotDirPath = new Path("/test"); |
| fs.mkdirs(snapshotDirPath, new FsPermission((short) 0)); |
| cluster.getNamesystem().allowSnapshot(snapshotDirPath.toString()); |
| Path s1 = fs.createSnapshot(snapshotDirPath); |
| Path s2 = fs.createSnapshot(snapshotDirPath); |
| int length; |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem) fileSys).getSnapshotDiffReport(snapshotDirPath, |
| s1.getName(), s2.getName()); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| String aceSnapshotDiffPattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=computeSnapshotDiff.*"; |
| length = verifyAuditLogs(aceSnapshotDiffPattern); |
| try { |
| fileSys.close(); |
| ((DistributedFileSystem) fileSys).getSnapshotDiffReport(snapshotDirPath, |
| s1.getName(), s2.getName()); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testGetQuotaUsage() throws Exception { |
| Path path = new Path("/test"); |
| fs.mkdirs(path, new FsPermission((short) 0)); |
| String aceGetQuotaUsagePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=quotaUsage.*"; |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| fileSys.getQuotaUsage(path); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| int length = verifyAuditLogs(aceGetQuotaUsagePattern); |
| fileSys.close(); |
| try { |
| fileSys.getQuotaUsage(path); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testAddCachePool() throws Exception { |
| removeExistingCachePools(null); |
| CachePoolInfo cacheInfo = new CachePoolInfo("pool1"). |
| setMode(new FsPermission((short) 0)); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem) fileSys).addCachePool(cacheInfo); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| String aceAddCachePoolPattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=addCachePool.*"; |
| int length = verifyAuditLogs(aceAddCachePoolPattern); |
| try { |
| fileSys.close(); |
| ((DistributedFileSystem) fileSys).addCachePool(cacheInfo); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testModifyCachePool() throws Exception { |
| removeExistingCachePools(null); |
| CachePoolInfo cacheInfo = new CachePoolInfo("pool1"). |
| setMode(new FsPermission((short) 0)); |
| ((DistributedFileSystem) fs).addCachePool(cacheInfo); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem) fileSys).modifyCachePool(cacheInfo); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| String aceModifyCachePoolPattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=modifyCachePool.*"; |
| int length = verifyAuditLogs(aceModifyCachePoolPattern); |
| try { |
| fileSys.close(); |
| ((DistributedFileSystem) fileSys).modifyCachePool(cacheInfo); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testRemoveCachePool() throws Exception { |
| removeExistingCachePools(null); |
| CachePoolInfo cacheInfo = new CachePoolInfo("pool1"). |
| setMode(new FsPermission((short) 0)); |
| ((DistributedFileSystem) fs).addCachePool(cacheInfo); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| try { |
| ((DistributedFileSystem) fileSys).removeCachePool("pool1"); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| String aceRemoveCachePoolPattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=removeCachePool.*"; |
| int length = verifyAuditLogs(aceRemoveCachePoolPattern); |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| try { |
| fileSys.close(); |
| ((DistributedFileSystem) fileSys).removeCachePool("pool1"); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testGetEZForPath() throws Exception { |
| Path path = new Path("/test"); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| fs.mkdirs(path,new FsPermission((short)0)); |
| String aceGetEzForPathPattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=getEZForPath.*"; |
| try { |
| ((DistributedFileSystem) fileSys).getEZForPath(path); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace){ |
| } |
| int length = verifyAuditLogs(aceGetEzForPathPattern); |
| fileSys.close(); |
| try { |
| ((DistributedFileSystem) fileSys).getEZForPath(path); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e){ |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testRenameTo() throws Exception { |
| Path path = new Path("/test"); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| fs.mkdirs(path,new FsPermission((short)0)); |
| String aceRenameToPattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=rename.*"; |
| try { |
| fileSys.rename(path, path); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| int length = verifyAuditLogs(aceRenameToPattern); |
| fileSys.close(); |
| try { |
| fileSys.rename(path, path); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testGetXattrs() throws Exception { |
| Path path = new Path("/test"); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| fs.mkdirs(path,new FsPermission((short)0)); |
| String aceGetXattrsPattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=getXAttrs.*"; |
| try { |
| fileSys.getXAttrs(path); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| int length = verifyAuditLogs(aceGetXattrsPattern); |
| fileSys.close(); |
| try { |
| fileSys.getXAttrs(path); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException e) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| } |
| |
| @Test |
| public void testListXattrs() throws Exception { |
| Path path = new Path("/test"); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| fs.mkdirs(path); |
| fs.setOwner(path,user1.getUserName(),user1.getPrimaryGroupName()); |
| String aceListXattrsPattern = |
| ".*allowed=true.*ugi=theDoctor.*cmd=listXAttrs.*"; |
| fileSys.listXAttrs(path); |
| verifyAuditLogs(aceListXattrsPattern); |
| } |
| |
| @Test |
| public void testGetAclStatus() throws Exception { |
| Path path = new Path("/test"); |
| fs.mkdirs(path); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| fs.setOwner(path, user1.getUserName(), user1.getPrimaryGroupName()); |
| final FSDirectory dir = cluster.getNamesystem().getFSDirectory(); |
| final FSDirectory mockedDir = Mockito.spy(dir); |
| AccessControlException ex = new AccessControlException(); |
| doThrow(ex).when(mockedDir).checkTraverse(any(), any(), any()); |
| cluster.getNamesystem().setFSDirectory(mockedDir); |
| String aceGetAclStatus = |
| ".*allowed=false.*ugi=theDoctor.*cmd=getAclStatus.*"; |
| try { |
| fileSys.getAclStatus(path); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (AccessControlException ace) { |
| } |
| int length = verifyAuditLogs(aceGetAclStatus); |
| fileSys.close(); |
| try { |
| fileSys.getAclStatus(path); |
| verifyAuditLogs(aceGetAclStatus); |
| fail("The operation should have failed with IOException"); |
| } catch (IOException ace) { |
| } |
| assertTrue("Unexpected log!", |
| length == auditlog.getOutput().split("\n").length); |
| cluster.getNamesystem().setFSDirectory(dir); |
| } |
| |
| @Test |
| public void testDelegationTokens() throws Exception { |
| Token dt = fs.getDelegationToken("foo"); |
| final String getDT = |
| ".*src=HDFS_DELEGATION_TOKEN token 1.*with renewer foo.*"; |
| verifyAuditLogs(true, ".*cmd=getDelegationToken" + getDT); |
| |
| // renew |
| final UserGroupInformation foo = |
| UserGroupInformation.createUserForTesting("foo", new String[] {}); |
| foo.doAs(new PrivilegedExceptionAction<Void>() { |
| @Override |
| public Void run() throws Exception { |
| dt.renew(conf); |
| return null; |
| } |
| }); |
| verifyAuditLogs(true, ".*cmd=renewDelegationToken" + getDT); |
| try { |
| dt.renew(conf); |
| fail("Renewing a token with non-renewer should fail"); |
| } catch (AccessControlException expected) { |
| } |
| verifyAuditLogs(false, ".*cmd=renewDelegationToken" + getDT); |
| |
| // cancel |
| final UserGroupInformation bar = |
| UserGroupInformation.createUserForTesting("bar", new String[] {}); |
| try { |
| bar.doAs(new PrivilegedExceptionAction<Void>() { |
| @Override |
| public Void run() throws Exception { |
| dt.cancel(conf); |
| return null; |
| } |
| }); |
| fail("Canceling a token with non-renewer should fail"); |
| } catch (AccessControlException expected) { |
| } |
| verifyAuditLogs(false, ".*cmd=cancelDelegationToken" + getDT); |
| dt.cancel(conf); |
| verifyAuditLogs(true, ".*cmd=cancelDelegationToken" + getDT); |
| } |
| |
| private int verifyAuditLogs(final boolean allowed, final String pattern) { |
| return verifyAuditLogs(".*allowed=" + allowed + pattern); |
| } |
| |
| @Test |
| public void testMetaSave() throws Exception { |
| String aceMetaSave = |
| ".*allowed=true.*cmd=metaSave.*"; |
| try { |
| ((DistributedFileSystem)fs).metaSave("test.log"); |
| verifyAuditLogs(aceMetaSave); |
| } catch (Exception e) { |
| fail("The operation should not have failed with Exception"); |
| } |
| try { |
| ((DistributedFileSystem)fileSys).metaSave("test.log"); |
| fail("The operation should have failed with AccessControlException"); |
| } catch (IOException ace) { |
| GenericTestUtils.assertExceptionContains("Access denied", ace); |
| aceMetaSave = |
| ".*allowed=false.*cmd=metaSave.*"; |
| verifyAuditLogs(aceMetaSave); |
| } |
| } |
| |
| @Test |
| public void testStartReconfiguration() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=startNamenodeReconfiguration.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| ((NameNodeRpcServer) cluster.getNameNodeRpc()).startReconfiguration(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("StartConfiguration should have passed!"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| ((NameNodeRpcServer)cluster.getNameNodeRpc()).startReconfiguration(); |
| fail( |
| "startNameNodeReconfiguration should throw AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=startNamenodeReconfiguration.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testGetReconfigurationStatus() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=getNamenodeReconfigurationStatus.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| ((NameNodeRpcServer) cluster.getNameNodeRpc()).getReconfigurationStatus(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("getNamenodeReconfigurationStatus " + |
| " threw Exception!"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| ((NameNodeRpcServer)cluster.getNameNodeRpc()).getReconfigurationStatus(); |
| fail("getNamenodeReconfigurationStatus " + |
| " did not throw AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=getNamenodeReconfigurationStatus.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testListReconfigurableProperties() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=listNamenodeReconfigurableProperties.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| ((NameNodeRpcServer) cluster.getNameNodeRpc()). |
| listReconfigurableProperties(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("listReconfigurableProperties " + |
| " threw Exception!"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| ((NameNodeRpcServer)cluster.getNameNodeRpc()). |
| listReconfigurableProperties(); |
| fail("getNamenodeReconfigurationStatus " + |
| " did not throw AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=listNamenodeReconfigurableProperties.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testRefreshUserToGroupsMappings() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=refreshUserToGroupsMappings.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| ((NameNodeRpcServer)cluster.getNameNodeRpc()). |
| refreshUserToGroupsMappings(); |
| verifyAuditLogs(auditLogString); |
| } |
| |
| @Test |
| public void testRefreshSuperUserGroupsConfiguration() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=refreshSuperUserGroupsConfiguration.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| ((NameNodeRpcServer) cluster.getNameNodeRpc()). |
| refreshSuperUserGroupsConfiguration(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail(" The operation threw an exception"); |
| } |
| } |
| |
| @Test |
| public void testRefreshQueue() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=refreshCallQueue.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| ((NameNodeRpcServer) cluster.getNameNodeRpc()).refreshCallQueue(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail(" The operation threw an exception"); |
| } |
| } |
| |
| @Test |
| public void testRefreshServiceAcl() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=refreshServiceAcl.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| ((NameNodeRpcServer) cluster.getNameNodeRpc()).refreshServiceAcl(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail(" The operation threw an exception" + e); |
| } |
| } |
| |
| @Test |
| public void testFinalizeRollingUpgrade() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=finalizeRollingUpgrade.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| fsNamesystem.setRollingUpgradeInfo(false, System.currentTimeMillis()); |
| try { |
| fsNamesystem.finalizeRollingUpgrade(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("finalizeRollingUpgrade threw Exception"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.finalizeRollingUpgrade(); |
| fail("finalizeRollingUpgrade should throw AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=finalizeRollingUpgrade.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testQueryRollingUpgrade() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=queryRollingUpgrade.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| fsNamesystem.setRollingUpgradeInfo(false, System.currentTimeMillis()); |
| try { |
| fsNamesystem.queryRollingUpgrade(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("queryRollingUpgrade threw Exception"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.queryRollingUpgrade(); |
| fail("queryRollingUpgrade should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=queryRollingUpgrade.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testRollEditLog() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=rollEditLog.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| fsNamesystem.rollEditLog(); |
| } catch (Exception e) { |
| fail("rollEditLog threw Exception"); |
| } |
| verifyAuditLogs(auditLogString); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.rollEditLog(); |
| fail("rollEditLog should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=rollEditLog.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testSetSafeMode() throws Exception { |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| verifySuccessfulSetSafeMode(fsNamesystem, |
| HdfsConstants.SafeModeAction.SAFEMODE_ENTER); |
| verifySuccessfulSetSafeMode(fsNamesystem, |
| HdfsConstants.SafeModeAction.SAFEMODE_GET); |
| verifySuccessfulSetSafeMode(fsNamesystem, |
| HdfsConstants.SafeModeAction.SAFEMODE_LEAVE); |
| verifySuccessfulSetSafeMode(fsNamesystem, |
| HdfsConstants.SafeModeAction.SAFEMODE_FORCE_EXIT); |
| String auditLogString; |
| auditLogString = |
| ".*allowed=true.*cmd=safemode_get.*"; |
| fsNamesystem.setSafeMode(HdfsConstants.SafeModeAction.SAFEMODE_GET); |
| verifyAuditLogs(auditLogString); |
| auditLogString = |
| ".*allowed=true.*cmd=safemode_leave.*"; |
| fsNamesystem.setSafeMode(HdfsConstants.SafeModeAction.SAFEMODE_LEAVE); |
| verifyAuditLogs(auditLogString); |
| auditLogString = |
| ".*allowed=true.*cmd=safemode_force_exit.*"; |
| fsNamesystem.setSafeMode(HdfsConstants.SafeModeAction.SAFEMODE_FORCE_EXIT); |
| verifyAuditLogs(auditLogString); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| verifySafeModeAction(fsNamesystem, |
| HdfsConstants.SafeModeAction.SAFEMODE_ENTER); |
| verifySafeModeAction(fsNamesystem, |
| HdfsConstants.SafeModeAction.SAFEMODE_LEAVE); |
| verifySafeModeAction(fsNamesystem, |
| HdfsConstants.SafeModeAction.SAFEMODE_FORCE_EXIT); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| } |
| |
| @Test |
| public void testSetBalancerBandwidth() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=setBalancerBandwidth.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| fsNamesystem.setBalancerBandwidth(10); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("setBalancerBandwidth threw exception!"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.setBalancerBandwidth(10); |
| fail( |
| "setBalancerBandwidth should have thrown AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=setBalancerBandwidth.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testRefreshNodes() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=refreshNodes.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| fsNamesystem.refreshNodes(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("refreshNodes threw exception!"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.refreshNodes(); |
| fail( |
| "refreshNodes should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=refreshNodes.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testFinalizeUpgrade() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=finalizeUpgrade.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| fsNamesystem.finalizeUpgrade(); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("finalizeUpgrade threw Exception"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.finalizeUpgrade(); |
| fail("finalizeUpgrade should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=finalizeUpgrade.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testSaveNamespace() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=saveNamespace.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| fsNamesystem.setSafeMode(HdfsConstants.SafeModeAction.SAFEMODE_ENTER); |
| try { |
| fsNamesystem.saveNamespace(10, 10); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("saveNamespace threw Exception"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.saveNamespace(10, 10); |
| fail("saveNamespace should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=saveNamespace.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testDatanodeReport() throws Exception { |
| String auditLogString = |
| ".*allowed=true.*cmd=datanodeReport.*"; |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| try { |
| fsNamesystem.datanodeReport(HdfsConstants.DatanodeReportType.ALL); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("datanodeReport threw Exception"); |
| } |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| try { |
| fsNamesystem.datanodeReport(HdfsConstants.DatanodeReportType.ALL); |
| fail( |
| "datanodeReport should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=datanodeReport.*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testRestoreFailedStorage() throws Exception { |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| verifyAuditRestoreFailedStorage(fsNamesystem, "check"); |
| verifyAuditRestoreFailedStorage(fsNamesystem, "true"); |
| verifyAuditRestoreFailedStorage(fsNamesystem, "false"); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| verifyAuditRestoreFailedStorageACE(fsNamesystem, "check"); |
| verifyAuditRestoreFailedStorageACE(fsNamesystem, "true"); |
| verifyAuditRestoreFailedStorageACE(fsNamesystem, "false"); |
| } |
| |
| @Test |
| public void testGetDatanodeStorageReport() throws Exception { |
| FSNamesystem fsNamesystem = spy(cluster.getNamesystem()); |
| when(fsNamesystem.isExternalInvocation()).thenReturn(true); |
| Server.Call call = spy(new Server.Call( |
| 1, 1, null, null, RPC.RpcKind.RPC_BUILTIN, new byte[] {1, 2, 3})); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser(System.getProperty("user.name"))); |
| Server.getCurCall().set(call); |
| DatanodeStorageReport[] reports = fsNamesystem.getDatanodeStorageReport( |
| HdfsConstants.DatanodeReportType.ALL); |
| String auditLogString = |
| ".*allowed=true.*cmd=" + "getDatanodeStorageReport" + ".*"; |
| verifyAuditLogs(auditLogString); |
| when(call.getRemoteUser()).thenReturn( |
| UserGroupInformation.createRemoteUser("theDoctor")); |
| auditLogString = |
| ".*allowed=false.*cmd=" + "getDatanodeStorageReport" + ".*"; |
| try { |
| fsNamesystem.getDatanodeStorageReport( |
| HdfsConstants.DatanodeReportType.ALL); |
| fail("Should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| @Test |
| public void testDeleteRoot() throws Exception { |
| Path srcDir = new Path("/"); |
| fileSys = DFSTestUtil.getFileSystemAs(user1, conf); |
| boolean result = fileSys.delete(srcDir, true); |
| fileSys.close(); |
| assertFalse(result); |
| String aceDeletePattern = |
| ".*allowed=false.*ugi=theDoctor.*cmd=delete.*"; |
| verifyAuditLogs(aceDeletePattern); |
| } |
| |
| private void verifyAuditRestoreFailedStorageACE( |
| FSNamesystem fsNamesystem, String arg) throws IOException { |
| String operationName = fsNamesystem.getFailedStorageCommand(arg); |
| try { |
| fsNamesystem.restoreFailedStorage(arg); |
| fail( |
| "RestoreFailedStorage should have thrown AccessControlException!"); |
| } catch (IOException ace) { |
| assertEquals("Unexpected Exception!", |
| ace.getClass(), AccessControlException.class); |
| String auditLogString = |
| ".*allowed=false.*cmd=" + operationName + ".*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| private void verifyAuditRestoreFailedStorage( |
| FSNamesystem fsNamesystem, String arg) throws IOException { |
| String operationName = fsNamesystem.getFailedStorageCommand(arg); |
| String auditLogString = |
| ".*allowed=true.*cmd=" + operationName + ".*"; |
| try { |
| fsNamesystem.restoreFailedStorage(arg); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail( |
| "The operation should not have failed with Exception"); |
| } |
| } |
| |
| private void verifySuccessfulSetSafeMode(FSNamesystem fsNamesystem, |
| HdfsConstants.SafeModeAction safeModeAction) throws IOException { |
| String operationName = safeModeAction.toString().toLowerCase(); |
| String auditLogString = |
| ".*allowed=true.*cmd=" + operationName +".*"; |
| try { |
| fsNamesystem.setSafeMode(safeModeAction); |
| verifyAuditLogs(auditLogString); |
| } catch (Exception e) { |
| fail("The operation should not have failed with Exception"); |
| } |
| } |
| |
| private void verifySafeModeAction( |
| FSNamesystem fsNamesystem, HdfsConstants.SafeModeAction safeModeAction) |
| throws IOException { |
| String operationName = safeModeAction.toString().toLowerCase(); |
| String auditLogString; |
| try { |
| fsNamesystem.setSafeMode(safeModeAction); |
| fail("setSafeMode should have thrown an AccessControlException!"); |
| } catch (AccessControlException ace) { |
| auditLogString = |
| ".*allowed=false.*cmd=" + operationName +".*"; |
| verifyAuditLogs(auditLogString); |
| } |
| } |
| |
| private int verifyAuditLogs(String pattern) { |
| int length = auditlog.getOutput().split(System.lineSeparator()).length; |
| String lastAudit = auditlog.getOutput() |
| .split(System.lineSeparator())[length - 1]; |
| assertTrue("Unexpected log!", lastAudit.matches(pattern)); |
| return length; |
| } |
| |
| private void removeExistingCachePools(String prevPool) throws Exception { |
| BatchedRemoteIterator.BatchedEntries<CachePoolEntry> entries = |
| proto.listCachePools(prevPool); |
| for(int i =0;i < entries.size();i++) { |
| proto.removeCachePool(entries.get(i).getInfo().getPoolName()); |
| } |
| } |
| } |