3333import org .apache .hadoop .fs .XAttr ;
3434import org .apache .hadoop .fs .permission .*;
3535import org .apache .hadoop .hdfs .DFSConfigKeys ;
36+ import org .apache .hadoop .hdfs .DistributedFileSystem ;
3637import org .apache .hadoop .hdfs .HdfsConfiguration ;
3738import org .apache .hadoop .hdfs .MiniDFSCluster ;
3839import org .apache .hadoop .security .AccessControlException ;
@@ -80,6 +81,7 @@ public void checkPermission(String fsOwner, String supergroup,
8081 ancestorAccess , parentAccess , access , subAccess , ignoreEmptyDir );
8182 }
8283 CALLED .add ("checkPermission|" + ancestorAccess + "|" + parentAccess + "|" + access );
84+ CALLED .add ("checkPermission|" + path );
8385 }
8486
8587 @ Override
@@ -93,6 +95,7 @@ public void checkPermissionWithContext(
9395 CALLED .add ("checkPermission|" + authzContext .getAncestorAccess ()
9496 + "|" + authzContext .getParentAccess () + "|" + authzContext
9597 .getAccess ());
98+ CALLED .add ("checkPermission|" + authzContext .getPath ());
9699 }
97100 }
98101
@@ -109,7 +112,12 @@ public void stop() {
109112 @ Override
110113 public INodeAttributes getAttributes (String [] pathElements ,
111114 final INodeAttributes inode ) {
115+ String fullPath = String .join ("/" , pathElements );
116+ if (!fullPath .startsWith ("/" )) {
117+ fullPath = "/" + fullPath ;
118+ }
112119 CALLED .add ("getAttributes" );
120+ CALLED .add ("getAttributes|" +fullPath );
113121 final boolean useDefault = useDefault (pathElements );
114122 final boolean useNullAcl = useNullAclFeature (pathElements );
115123 return new INodeAttributes () {
@@ -485,4 +493,111 @@ public Void run() throws Exception {
485493 }
486494 });
487495 }
496+
497+ @ Test
498+ // HDFS-15372 - Attribute provider should not see the snapshot path as it
499+ // should be resolved into the original path name before it hits the provider.
500+ public void testAttrProviderSeesResolvedSnapahotPaths () throws Exception {
501+ FileSystem fs = FileSystem .get (miniDFS .getConfiguration (0 ));
502+ DistributedFileSystem hdfs = miniDFS .getFileSystem ();
503+ final Path userPath = new Path ("/user" );
504+ final Path authz = new Path ("/user/authz" );
505+ final Path authzChild = new Path ("/user/authz/child2" );
506+
507+ fs .mkdirs (userPath );
508+ fs .setPermission (userPath , new FsPermission (HDFS_PERMISSION ));
509+ fs .mkdirs (authz );
510+ hdfs .allowSnapshot (userPath );
511+ fs .setPermission (authz , new FsPermission (HDFS_PERMISSION ));
512+ fs .mkdirs (authzChild );
513+ fs .setPermission (authzChild , new FsPermission (HDFS_PERMISSION ));
514+ fs .createSnapshot (userPath , "snapshot_1" );
515+ UserGroupInformation ugi = UserGroupInformation .createUserForTesting ("u1" ,
516+ new String []{"g1" });
517+ ugi .doAs (new PrivilegedExceptionAction <Void >() {
518+ @ Override
519+ public Void run () throws Exception {
520+ FileSystem fs = FileSystem .get (miniDFS .getConfiguration (0 ));
521+ final Path snapChild =
522+ new Path ("/user/.snapshot/snapshot_1/authz/child2" );
523+ // Run various methods on the path to access the attributes etc.
524+ fs .getAclStatus (snapChild );
525+ fs .getContentSummary (snapChild );
526+ fs .getFileStatus (snapChild );
527+ Assert .assertFalse (CALLED .contains ("getAttributes|" +
528+ snapChild .toString ()));
529+ Assert .assertTrue (CALLED .contains ("getAttributes|/user/authz/child2" ));
530+ // The snapshot path should be seen by the permission checker, but when
531+ // it checks access, the paths will be resolved so the attributeProvider
532+ // only sees the resolved path.
533+ Assert .assertTrue (
534+ CALLED .contains ("checkPermission|" + snapChild .toString ()));
535+ CALLED .clear ();
536+ fs .getAclStatus (new Path ("/" ));
537+ Assert .assertTrue (CALLED .contains ("checkPermission|/" ));
538+ Assert .assertTrue (CALLED .contains ("getAttributes|/" ));
539+
540+ CALLED .clear ();
541+ fs .getFileStatus (new Path ("/user" ));
542+ Assert .assertTrue (CALLED .contains ("checkPermission|/user" ));
543+ Assert .assertTrue (CALLED .contains ("getAttributes|/user" ));
544+
545+ CALLED .clear ();
546+ fs .getFileStatus (new Path ("/user/.snapshot" ));
547+ Assert .assertTrue (CALLED .contains ("checkPermission|/user/.snapshot" ));
548+ // attribute provider never sees the .snapshot path directly.
549+ Assert .assertFalse (CALLED .contains ("getAttributes|/user/.snapshot" ));
550+
551+ CALLED .clear ();
552+ fs .getFileStatus (new Path ("/user/.snapshot/snapshot_1" ));
553+ Assert .assertTrue (
554+ CALLED .contains ("checkPermission|/user/.snapshot/snapshot_1" ));
555+ Assert .assertTrue (
556+ CALLED .contains ("getAttributes|/user/.snapshot/snapshot_1" ));
557+
558+ CALLED .clear ();
559+ fs .getFileStatus (new Path ("/user/.snapshot/snapshot_1/authz" ));
560+ Assert .assertTrue (CALLED
561+ .contains ("checkPermission|/user/.snapshot/snapshot_1/authz" ));
562+ Assert .assertTrue (CALLED .contains ("getAttributes|/user/authz" ));
563+
564+ CALLED .clear ();
565+ fs .getFileStatus (new Path ("/user/authz" ));
566+ Assert .assertTrue (CALLED .contains ("checkPermission|/user/authz" ));
567+ Assert .assertTrue (CALLED .contains ("getAttributes|/user/authz" ));
568+ return null ;
569+ }
570+ });
571+ // Delete the files / folders covered by the snapshot, then re-check they
572+ // are all readable correctly.
573+ fs .delete (authz , true );
574+ ugi .doAs (new PrivilegedExceptionAction <Void >() {
575+ @ Override
576+ public Void run () throws Exception {
577+ FileSystem fs = FileSystem .get (miniDFS .getConfiguration (0 ));
578+
579+ CALLED .clear ();
580+ fs .getFileStatus (new Path ("/user/.snapshot" ));
581+ Assert .assertTrue (CALLED .contains ("checkPermission|/user/.snapshot" ));
582+ // attribute provider never sees the .snapshot path directly.
583+ Assert .assertFalse (CALLED .contains ("getAttributes|/user/.snapshot" ));
584+
585+ CALLED .clear ();
586+ fs .getFileStatus (new Path ("/user/.snapshot/snapshot_1" ));
587+ Assert .assertTrue (
588+ CALLED .contains ("checkPermission|/user/.snapshot/snapshot_1" ));
589+ Assert .assertTrue (
590+ CALLED .contains ("getAttributes|/user/.snapshot/snapshot_1" ));
591+
592+ CALLED .clear ();
593+ fs .getFileStatus (new Path ("/user/.snapshot/snapshot_1/authz" ));
594+ Assert .assertTrue (CALLED
595+ .contains ("checkPermission|/user/.snapshot/snapshot_1/authz" ));
596+ Assert .assertTrue (CALLED .contains ("getAttributes|/user/authz" ));
597+
598+ return null ;
599+ }
600+ });
601+
602+ }
488603}
0 commit comments