yuqi1129 commented on code in PR #13455:
URL: https://github.com/apache/gravitino/pull/13455#discussion_r4231032617


##########
clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/BaseGVFSOperations.java:
##########
@@ -453,23 +455,72 @@ public abstract FSDataOutputStream append(Path gvfsPath, 
int bufferSize, Progres
    */
   public abstract Token<?>[] addDelegationTokens(String renewer, Credentials 
credentials);
 
+  /**
+   * Resolve the filesets listed in {@link
+   * 
GravitinoVirtualFileSystemConfiguration#FS_GRAVITINO_DELEGATION_TOKEN_FILESETS},
 so that their
+   * actual file systems exist before delegation tokens are collected. Token 
requests carry no path,
+   * so the filesets cannot be learned from the caller.
+   */
+  public void prepareDelegationTokens() {
+    for (String path :
+        conf.getTrimmedStrings(
+            
GravitinoVirtualFileSystemConfiguration.FS_GRAVITINO_DELEGATION_TOKEN_FILESETS))
 {
+      try {
+        getActualFileSystem(new Path(path), currentLocationName());
+      } catch (Exception e) {
+        // Never fail token collection: an unresolvable fileset simply yields 
no token.
+        LOG.warn("Failed to resolve {} while preparing delegation tokens", 
path, e);
+      }
+    }
+  }
+
   /**
    * Add delegation tokens for all file systems in the cache.
    *
+   * <p>Only tokens owned by the current user are added. A fileset configured 
with its own Kerberos
+   * principal is accessed as that principal, and its token must not be handed 
to the caller's job.
+   *
    * @param renewer the renewer.
    * @param credentials the credentials.
    * @return the array of tokens.
    */
   protected Token<?>[] addDelegationTokensForAllFS(String renewer, Credentials 
credentials) {
+    String currentUser;
+    try {
+      currentUser = UserGroupInformation.getCurrentUser().getShortUserName();
+    } catch (IOException e) {
+      LOG.warn("Failed to get the current user, skipping delegation tokens", 
e);
+      return new Token<?>[0];
+    }
+
     List<Token<?>> tokenList = Lists.newArrayList();
     for (FileSystem fileSystem : fileSystemCache.asMap().values()) {

Review Comment:
   [Important] Token collection still depends on the filesystem cache retaining 
every configured authority.
   
   `prepareDelegationTokens()` resolves the whole list before this loop runs. 
With `fs.gravitino.fileset.cache.maxCapacity=1` and two configured filesets on 
different HDFS authorities, one entry can be evicted before collection, so only 
one authority gets a token. The default capacity is 20, so this also affects 
larger lists; expiration during preparation is another way to lose an entry.
   
   Please collect tokens as each fileset is resolved, or collect from an 
explicit set of the resolved filesystem instances rather than the bounded 
cache. Retain collection for previously cached filesystems where needed for 
compatibility.
   
   Verified on 20b1ec7: a temporary regression test used the real GVFS cache 
with capacity 1, two configured filesets, mocked filesystem construction/token 
issuance, and cache cleanup between resolutions. It expected two credential 
tokens and received one. This was not a real multi-cluster Kerberos E2E run. 
Please add this boundary to the regression suite.



##########
clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/BaseGVFSOperations.java:
##########
@@ -453,23 +455,72 @@ public abstract FSDataOutputStream append(Path gvfsPath, 
int bufferSize, Progres
    */
   public abstract Token<?>[] addDelegationTokens(String renewer, Credentials 
credentials);
 
+  /**
+   * Resolve the filesets listed in {@link
+   * 
GravitinoVirtualFileSystemConfiguration#FS_GRAVITINO_DELEGATION_TOKEN_FILESETS},
 so that their
+   * actual file systems exist before delegation tokens are collected. Token 
requests carry no path,
+   * so the filesets cannot be learned from the caller.
+   */
+  public void prepareDelegationTokens() {
+    for (String path :
+        conf.getTrimmedStrings(
+            
GravitinoVirtualFileSystemConfiguration.FS_GRAVITINO_DELEGATION_TOKEN_FILESETS))
 {
+      try {
+        getActualFileSystem(new Path(path), currentLocationName());
+      } catch (Exception e) {
+        // Never fail token collection: an unresolvable fileset simply yields 
no token.
+        LOG.warn("Failed to resolve {} while preparing delegation tokens", 
path, e);
+      }
+    }
+  }
+
   /**
    * Add delegation tokens for all file systems in the cache.
    *
+   * <p>Only tokens owned by the current user are added. A fileset configured 
with its own Kerberos
+   * principal is accessed as that principal, and its token must not be handed 
to the caller's job.
+   *
    * @param renewer the renewer.
    * @param credentials the credentials.
    * @return the array of tokens.
    */
   protected Token<?>[] addDelegationTokensForAllFS(String renewer, Credentials 
credentials) {
+    String currentUser;
+    try {
+      currentUser = UserGroupInformation.getCurrentUser().getShortUserName();
+    } catch (IOException e) {
+      LOG.warn("Failed to get the current user, skipping delegation tokens", 
e);
+      return new Token<?>[0];
+    }
+
     List<Token<?>> tokenList = Lists.newArrayList();
     for (FileSystem fileSystem : fileSystemCache.asMap().values()) {
+      // Collect into a copy, so a token owned by another user never reaches 
the caller.
+      Credentials fetched = new Credentials(credentials);

Review Comment:
   [Important] This breaks the Hadoop `addDelegationTokens(renewer, null)` 
contract.
   
   Hadoop's `DelegationTokenIssuer.addDelegationTokens` accepts null 
credentials, creates a local `Credentials`, and returns the newly acquired 
tokens. GVFS's operations Javadoc explicitly refers to that contract. With a 
populated cache, `new Credentials(null)` now throws a NullPointerException 
before token collection. The later `credentials.getToken`/`addToken` calls 
would also need the same normalization.
   
   Please normalize null to a local empty `Credentials` at the method entry, 
use it consistently for copying, deduplication and merging, and preserve the 
returned token array.
   
   Verified on 20b1ec7 with a temporary regression test whose mocked underlying 
filesystem supports null as Hadoop does: the call failed in 
`Credentials.addAll` with `other` null. Spark passes non-null credentials on 
the reviewed path, so this is a public API compatibility regression rather than 
the main Spark failure.
   
   Hadoop implementation: 
https://github.com/apache/hadoop/blob/rel/release-3.3.6/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/DelegationTokenIssuer.java#L71



##########
clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/BaseGVFSOperations.java:
##########
@@ -453,23 +455,72 @@ public abstract FSDataOutputStream append(Path gvfsPath, 
int bufferSize, Progres
    */
   public abstract Token<?>[] addDelegationTokens(String renewer, Credentials 
credentials);
 
+  /**
+   * Resolve the filesets listed in {@link
+   * 
GravitinoVirtualFileSystemConfiguration#FS_GRAVITINO_DELEGATION_TOKEN_FILESETS},
 so that their
+   * actual file systems exist before delegation tokens are collected. Token 
requests carry no path,
+   * so the filesets cannot be learned from the caller.
+   */
+  public void prepareDelegationTokens() {
+    for (String path :
+        conf.getTrimmedStrings(
+            
GravitinoVirtualFileSystemConfiguration.FS_GRAVITINO_DELEGATION_TOKEN_FILESETS))
 {
+      try {
+        getActualFileSystem(new Path(path), currentLocationName());

Review Comment:
   [Important] Preparing tokens can now create the fileset's storage directory 
before the job accesses any data.
   
   This call reaches `getActualFileSystemByLocationName`, which calls 
`createFilesetLocationIfNeed`. When the catalog has 
`disable-filesystem-ops=true` and GVFS has 
`fs.gravitino.autoCreateLocation=true` (the default), preparation performs 
`exists()` and potentially `mkdirs()`. Token collection during submission or 
renewal therefore introduces storage writes, even for a listed fileset that the 
job never reads.
   
   Please provide a resolution/initialization path for token preparation that 
skips directory creation, leaving auto-creation on the data-operation path. Add 
a regression asserting that preparing tokens does not create a missing location.
   
   Verified on 20b1ec7 using the real local filesystem and the production 
resolution path, with mocked Gravitino metadata: calling only 
`prepareDelegationTokens()` created an initially absent fileset directory. HDFS 
permission/error behavior was not executed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to