public void testGeneralSBBehavior() throws IOException, InterruptedException { MiniDFSCluster cluster = null; try { Configuration conf = new HdfsConfiguration(); conf.setBoolean(DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY, true); conf.setBoolean("dfs.support.append", true); cluster = new MiniDFSCluster.Builder(conf).numDataNodes(4).build(); FileSystem hdfs = cluster.getFileSystem(); assertTrue(hdfs instanceof DistributedFileSystem); Path baseDir = new Path("/mcgann"); hdfs.mkdirs(baseDir); confirmCanAppend(conf, hdfs, baseDir); baseDir = new Path("/eccleston"); hdfs.mkdirs(baseDir); confirmSettingAndGetting(hdfs, baseDir); baseDir = new Path("/tennant"); hdfs.mkdirs(baseDir); confirmDeletingFiles(conf, hdfs, baseDir); baseDir = new Path("/smith"); hdfs.mkdirs(baseDir); confirmStickyBitDoesntPropagate(hdfs, baseDir); } finally { if (cluster != null) cluster.shutdown(); } }
/** * Test that one user can't delete another user's file when the sticky bit is * set. */ private void confirmDeletingFiles(Configuration conf, FileSystem hdfs, Path baseDir) throws IOException, InterruptedException { Path p = new Path(baseDir, "contemporary"); hdfs.mkdirs(p); hdfs.setPermission(p, new FsPermission((short) 01777)); // Write a file to the new temp directory as a regular user hdfs = DFSTestUtil.getFileSystemAs(user1, conf); Path file = new Path(p, "foo"); writeFile(hdfs, file); // Make sure the correct user is the owner assertEquals(user1.getShortUserName(), hdfs.getFileStatus(file).getOwner()); // Log onto cluster as another user and attempt to delete the file FileSystem hdfs2 = DFSTestUtil.getFileSystemAs(user2, conf); try { hdfs2.delete(file, false); fail("Shouldn't be able to delete someone else's file with SB on"); } catch (IOException ioe) { assertTrue(ioe instanceof AccessControlException); assertTrue(ioe.getMessage().contains("sticky bit")); } }
assertFalse(hdfs.getFileStatus(p1).getPermission().getStickyBit()); withSB = (short) (hdfs.getFileStatus(p1).getPermission().toShort() | 01000); assertTrue((new FsPermission(withSB)).getStickyBit()); assertTrue(hdfs.getFileStatus(p1).getPermission().getStickyBit()); writeFile(hdfs, f); assertFalse(hdfs.getFileStatus(f).getPermission().getStickyBit()); assertFalse(hdfs.getFileStatus(f).getPermission().getStickyBit());
FileSystem hdfs = cluster.getFileSystem(); assertTrue(hdfs instanceof DistributedFileSystem); writeFile(hdfs2, file); fail("Shouldn't be able to rename someone else's file with SB on"); } catch (IOException ioe) { assertTrue(ioe instanceof AccessControlException); assertTrue(ioe.getMessage().contains("sticky bit"));
/** * Ensure that even if a file is in a directory with the sticky bit on, * another user can write to that file (assuming correct permissions). */ private void confirmCanAppend(Configuration conf, FileSystem hdfs, Path baseDir) throws IOException, InterruptedException { // Create a tmp directory with wide-open permissions and sticky bit Path p = new Path(baseDir, "tmp"); hdfs.mkdirs(p); hdfs.setPermission(p, new FsPermission((short) 01777)); // Write a file to the new tmp directory as a regular user hdfs = DFSTestUtil.getFileSystemAs(user1, conf); Path file = new Path(p, "foo"); writeFile(hdfs, file); hdfs.setPermission(file, new FsPermission((short) 0777)); // Log onto cluster as another user and attempt to append to file hdfs = DFSTestUtil.getFileSystemAs(user2, conf); Path file2 = new Path(p, "foo"); FSDataOutputStream h = hdfs.append(file2); h.write("Some more data".getBytes()); h.close(); }
private void testMovingFiles(boolean useAcl) throws Exception { // Create a tmp directory with wide-open permissions and sticky bit Path tmpPath = new Path("/tmp"); Path tmpPath2 = new Path("/tmp2"); hdfs.mkdirs(tmpPath); hdfs.mkdirs(tmpPath2); hdfs.setPermission(tmpPath, new FsPermission((short) 01777)); if (useAcl) { applyAcl(tmpPath); } hdfs.setPermission(tmpPath2, new FsPermission((short) 01777)); if (useAcl) { applyAcl(tmpPath2); } // Write a file to the new tmp directory as a regular user Path file = new Path(tmpPath, "foo"); writeFile(hdfsAsUser1, file); // Log onto cluster as another user and attempt to move the file try { hdfsAsUser2.rename(file, new Path(tmpPath2, "renamed")); fail("Shouldn't be able to rename someone else's file with SB on"); } catch (IOException ioe) { assertTrue(ioe instanceof AccessControlException); assertTrue(ioe.getMessage().contains("sticky bit")); } }
@Test public void testAclStickyBitPersistence() throws Exception { // A tale of three directories... Path sbSet = new Path("/Housemartins"); Path sbNotSpecified = new Path("/INXS"); Path sbSetOff = new Path("/Easyworld"); for (Path p : new Path[] { sbSet, sbNotSpecified, sbSetOff }) hdfs.mkdirs(p); // Two directories had there sticky bits set explicitly... hdfs.setPermission(sbSet, new FsPermission((short) 01777)); applyAcl(sbSet); hdfs.setPermission(sbSetOff, new FsPermission((short) 00777)); applyAcl(sbSetOff); shutdown(); // Start file system up again initCluster(false); assertTrue(hdfs.exists(sbSet)); assertTrue(hdfs.getFileStatus(sbSet).getPermission().getStickyBit()); assertTrue(hdfs.exists(sbNotSpecified)); assertFalse(hdfs.getFileStatus(sbNotSpecified).getPermission() .getStickyBit()); assertTrue(hdfs.exists(sbSetOff)); assertFalse(hdfs.getFileStatus(sbSetOff).getPermission().getStickyBit()); }
FileSystem hdfs = cluster.getFileSystem(); assertTrue(hdfs instanceof DistributedFileSystem); hdfs = cluster.getFileSystem(); assertTrue(hdfs.exists(sbSet)); assertTrue(hdfs.getFileStatus(sbSet).getPermission().getStickyBit()); assertTrue(hdfs.exists(sbNotSpecified)); assertFalse(hdfs.getFileStatus(sbNotSpecified).getPermission() .getStickyBit()); assertTrue(hdfs.exists(sbSetOff)); assertFalse(hdfs.getFileStatus(sbSetOff).getPermission().getStickyBit());
/** * Test that if a directory is created in a directory that has the sticky bit * on, the new directory does not automatically get a sticky bit, as is * standard Unix behavior */ private void confirmStickyBitDoesntPropagate(FileSystem hdfs, Path baseDir) throws IOException { Path p = new Path(baseDir, "scissorsisters"); // Turn on its sticky bit hdfs.mkdirs(p, new FsPermission((short) 01666)); // Create a subdirectory within it Path p2 = new Path(p, "bar"); hdfs.mkdirs(p2); // Ensure new directory doesn't have its sticky bit on assertFalse(hdfs.getFileStatus(p2).getPermission().getStickyBit()); }
/** * Ensure that even if a file is in a directory with the sticky bit on, * another user can write to that file (assuming correct permissions). */ private void confirmCanAppend(Configuration conf, Path p) throws Exception { // Write a file to the new tmp directory as a regular user Path file = new Path(p, "foo"); writeFile(hdfsAsUser1, file); hdfsAsUser1.setPermission(file, new FsPermission((short) 0777)); // Log onto cluster as another user and attempt to append to file Path file2 = new Path(p, "foo"); FSDataOutputStream h = null; try { h = hdfsAsUser2.append(file2); h.write("Some more data".getBytes()); h.close(); h = null; } finally { IOUtils.cleanup(null, h); } }
applyAcl(p); confirmCanAppend(conf, p); applyAcl(p); confirmSettingAndGetting(hdfs, p, baseDir); hdfs.mkdirs(p); hdfs.setPermission(p, new FsPermission((short) 01777)); applyAcl(p); confirmDeletingFiles(conf, p); applyAcl(p); confirmStickyBitDoesntPropagate(hdfs, p);
/** * Test that one user can't delete another user's file when the sticky bit is * set. */ private void confirmDeletingFiles(Configuration conf, Path p) throws Exception { // Write a file to the new temp directory as a regular user Path file = new Path(p, "foo"); writeFile(hdfsAsUser1, file); // Make sure the correct user is the owner assertEquals(user1.getShortUserName(), hdfsAsUser1.getFileStatus(file).getOwner()); // Log onto cluster as another user and attempt to delete the file try { hdfsAsUser2.delete(file, false); fail("Shouldn't be able to delete someone else's file with SB on"); } catch (IOException ioe) { assertTrue(ioe instanceof AccessControlException); assertTrue(ioe.getMessage().contains("sticky bit")); assertTrue(ioe.getMessage().contains("user="+user2.getUserName())); assertTrue(ioe.getMessage().contains("path=\"" + file + "\"")); assertTrue(ioe.getMessage().contains("parent=\"" + file.getParent() + "\"")); } }
@Test public void testGeneralSBBehavior() throws Exception { Path baseDir = new Path("/mcgann"); hdfs.mkdirs(baseDir); // Create a tmp directory with wide-open permissions and sticky bit Path p = new Path(baseDir, "tmp"); hdfs.mkdirs(p); hdfs.setPermission(p, new FsPermission((short) 01777)); confirmCanAppend(conf, p); baseDir = new Path("/eccleston"); hdfs.mkdirs(baseDir); p = new Path(baseDir, "roguetraders"); hdfs.mkdirs(p); confirmSettingAndGetting(hdfs, p, baseDir); baseDir = new Path("/tennant"); hdfs.mkdirs(baseDir); p = new Path(baseDir, "contemporary"); hdfs.mkdirs(p); hdfs.setPermission(p, new FsPermission((short) 01777)); confirmDeletingFiles(conf, p); baseDir = new Path("/smith"); hdfs.mkdirs(baseDir); p = new Path(baseDir, "scissorsisters"); // Turn on its sticky bit hdfs.mkdirs(p, new FsPermission((short) 01666)); confirmStickyBitDoesntPropagate(hdfs, baseDir); }
/** * Test basic ability to get and set sticky bits on files and directories. */ private void confirmSettingAndGetting(FileSystem hdfs, Path p, Path baseDir) throws IOException { // Initially sticky bit should not be set assertFalse(hdfs.getFileStatus(p).getPermission().getStickyBit()); // Same permission, but with sticky bit on short withSB; withSB = (short) (hdfs.getFileStatus(p).getPermission().toShort() | 01000); assertTrue((new FsPermission(withSB)).getStickyBit()); hdfs.setPermission(p, new FsPermission(withSB)); assertTrue(hdfs.getFileStatus(p).getPermission().getStickyBit()); // Write a file to the fs, try to set its sticky bit Path f = new Path(baseDir, "somefile"); writeFile(hdfs, f); assertFalse(hdfs.getFileStatus(f).getPermission().getStickyBit()); withSB = (short) (hdfs.getFileStatus(f).getPermission().toShort() | 01000); hdfs.setPermission(f, new FsPermission(withSB)); assertTrue(hdfs.getFileStatus(f).getPermission().getStickyBit()); }