This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 6f0b5a3b390 HDDS-15467. Do not fall back to the OM starter user in 
OMClientRequest (#10469)
6f0b5a3b390 is described below

commit 6f0b5a3b3909239fa672883317fec3bf84c202c8
Author: KUAN-HAO HUANG <[email protected]>
AuthorDate: Sat Jun 27 00:16:54 2026 +0800

    HDDS-15467. Do not fall back to the OM starter user in OMClientRequest 
(#10469)
---
 .../hadoop/ozone/om/request/OMClientRequest.java   |  39 ++------
 .../om/request/key/OMAllocateBlockRequest.java     |   4 +-
 .../ozone/om/request/key/OMKeyDeleteRequest.java   |   2 +-
 .../ozone/om/request/key/OMKeyRenameRequest.java   |   2 +-
 .../TestOMClientRequestUserInfoFallback.java       | 106 +++++++++++++++++++++
 5 files changed, 118 insertions(+), 35 deletions(-)

diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java
index 884c5fa310b..9ffdef1784b 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java
@@ -115,7 +115,7 @@ public OMRequest preExecute(OzoneManager ozoneManager)
         
.setVersion(ozoneManager.getVersionManager().getMetadataLayoutVersion())
         .build();
     omRequest = getOmRequest().toBuilder()
-        .setUserInfo(getUserIfNotExists(ozoneManager))
+        .setUserInfo(getUserInfo())
         .setLayoutVersion(layoutVersion).build();
     return omRequest;
   }
@@ -193,41 +193,18 @@ public OzoneManagerProtocolProtos.UserInfo getUserInfo() 
throws IOException {
         && grpcContextClientIpAddress != null) {
       userInfo.setHostName(grpcContextClientHostname);
       userInfo.setRemoteAddress(grpcContextClientIpAddress);
+    } else if (omRequest.hasUserInfo()
+        && omRequest.getUserInfo().hasRemoteAddress()) {
+      // For non-RPC internal service requests (e.g. the Trash emptier) that
+      // populate their own UserInfo, preserve the supplied host/address since
+      // there is no RPC or gRPC client context to derive it from.
+      userInfo.setHostName(omRequest.getUserInfo().getHostName());
+      userInfo.setRemoteAddress(omRequest.getUserInfo().getRemoteAddress());
     }
 
     return userInfo.build();
   }
 
-  /**
-   * For non-rpc internal calls Server.getRemoteUser()
-   * and Server.getRemoteIp() will be null.
-   * Passing getCurrentUser() and Ip of the Om node that started it.
-   * @return User Info.
-   */
-  public OzoneManagerProtocolProtos.UserInfo getUserIfNotExists(
-      OzoneManager ozoneManager) throws IOException {
-    OzoneManagerProtocolProtos.UserInfo userInfo = getUserInfo();
-    if (!userInfo.hasRemoteAddress() || !userInfo.hasUserName()) {
-      OzoneManagerProtocolProtos.UserInfo.Builder newuserInfo =
-          OzoneManagerProtocolProtos.UserInfo.newBuilder();
-      UserGroupInformation user;
-      InetAddress remoteAddress;
-      try {
-        user = UserGroupInformation.getCurrentUser();
-        remoteAddress = ozoneManager.getOmRpcServerAddr()
-            .getAddress();
-      } catch (Exception e) {
-        LOG.debug("Couldn't get om Rpc server address", e);
-        return getUserInfo();
-      }
-      newuserInfo.setUserName(user.getUserName());
-      newuserInfo.setHostName(remoteAddress.getHostName());
-      newuserInfo.setRemoteAddress(remoteAddress.getHostAddress());
-      return newuserInfo.build();
-    }
-    return getUserInfo();
-  }
-
   /**
    * Check Acls of ozone object.
    * @param ozoneManager
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java
index e8b3abfe219..d7cd3bea5ec 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java
@@ -105,7 +105,7 @@ public OMRequest preExecute(OzoneManager ozoneManager) 
throws IOException {
     //  BlockOutputStreamEntryPool, so we are fine for now. But if one some
     //  one uses direct omclient we might be in trouble.
 
-    UserInfo userInfo = getUserIfNotExists(ozoneManager);
+    UserInfo userInfo = getOmRequest().getUserInfo();
     ReplicationConfig repConfig = 
ReplicationConfig.fromProto(keyArgs.getType(),
         keyArgs.getFactor(), keyArgs.getEcReplicationConfig());
     // To allocate atleast one block passing requested size and scmBlockSize
@@ -142,7 +142,7 @@ public OMRequest preExecute(OzoneManager ozoneManager) 
throws IOException {
     newAllocatedBlockRequest.setKeyLocation(
         omKeyLocationInfoList.get(0).getProtobuf(getOmRequest().getVersion()));
 
-    return getOmRequest().toBuilder().setUserInfo(userInfo)
+    return getOmRequest().toBuilder()
         .setAllocateBlockRequest(newAllocatedBlockRequest).build();
 
   }
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
index 4726d4af2d5..43b0e2a9f8f 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
@@ -92,7 +92,7 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws 
IOException {
     return getOmRequest().toBuilder()
         .setDeleteKeyRequest(deleteKeyRequest.toBuilder()
             .setKeyArgs(resolvedArgs))
-        .setUserInfo(getUserIfNotExists(ozoneManager)).build();
+        .build();
   }
 
   protected KeyArgs resolveBucketAndCheckAcls(OzoneManager ozoneManager,
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java
index 850f111a913..2c2e54d3a7b 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java
@@ -95,7 +95,7 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws 
IOException {
     return getOmRequest().toBuilder()
         .setRenameKeyRequest(renameKeyRequest.toBuilder().setToKeyName(dstKey)
             .setKeyArgs(resolvedArgs))
-        .setUserInfo(getUserIfNotExists(ozoneManager)).build();
+        .build();
 
   }
 
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestUserInfoFallback.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestUserInfoFallback.java
new file mode 100644
index 00000000000..202ada1b016
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestUserInfoFallback.java
@@ -0,0 +1,106 @@
+/*
+ * 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.ozone.om.request;
+
+import static 
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.newBucketInfoBuilder;
+import static 
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.newCreateBucketRequest;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mockStatic;
+
+import java.util.UUID;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos.StorageTypeProto;
+import org.apache.hadoop.ipc_.Server;
+import org.apache.hadoop.ozone.om.request.bucket.OMBucketCreateRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketInfo;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UserInfo;
+import 
org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+/**
+ * Tests that {@link OMClientRequest} does not silently fall back to the OM
+ * starter/login user when a request carries no user information (HDDS-15467).
+ */
+public class TestOMClientRequestUserInfoFallback {
+
+  private OMRequest newBucketRequest(UserInfo userInfo) {
+    BucketInfo.Builder bucketInfo = newBucketInfoBuilder(
+        UUID.randomUUID().toString(), UUID.randomUUID().toString())
+        .setIsVersionEnabled(true)
+        .setStorageType(StorageTypeProto.DISK);
+    OMRequest.Builder builder = newCreateBucketRequest(bucketInfo);
+    if (userInfo != null) {
+      builder.setUserInfo(userInfo);
+    }
+    return builder.build();
+  }
+
+  /**
+   * With no RPC/gRPC context and no UserInfo on the request, getUserInfo() 
must
+   * not manufacture an identity from the OM starter user; createUGI() then
+   * fails closed instead of silently escalating.
+   */
+  @Test
+  public void noFallbackToServerUserWhenUserInfoMissing() throws Exception {
+    try (MockedStatic<Server> mockedRpcServer = mockStatic(Server.class)) {
+      mockedRpcServer.when(Server::getRemoteUser).thenReturn(null);
+      mockedRpcServer.when(Server::getRemoteIp).thenReturn(null);
+
+      OMRequest omRequest = newBucketRequest(null);
+      OMClientRequest request = new OMBucketCreateRequest(omRequest);
+
+      UserInfo userInfo = request.getUserInfo();
+      assertFalse(userInfo.hasUserName());
+      assertFalse(userInfo.hasRemoteAddress());
+
+      OMClientRequest withUserInfo = new OMBucketCreateRequest(
+          omRequest.toBuilder().setUserInfo(userInfo).build());
+      assertThrows(AuthenticationException.class, withUserInfo::createUGI);
+    }
+  }
+
+  /**
+   * An internal service (e.g. the Trash emptier) populates its own UserInfo.
+   * With no RPC/gRPC context, getUserInfo() must preserve that identity rather
+   * than replacing it with the OM starter user.
+   */
+  @Test
+  public void internalServiceUserInfoIsPreserved() throws Exception {
+    try (MockedStatic<Server> mockedRpcServer = mockStatic(Server.class)) {
+      mockedRpcServer.when(Server::getRemoteUser).thenReturn(null);
+      mockedRpcServer.when(Server::getRemoteIp).thenReturn(null);
+
+      UserInfo serviceUserInfo = UserInfo.newBuilder()
+          .setUserName("trash-service-user")
+          .setHostName("om-host")
+          .setRemoteAddress("10.0.0.9")
+          .build();
+
+      OMClientRequest request =
+          new OMBucketCreateRequest(newBucketRequest(serviceUserInfo));
+
+      UserInfo result = request.getUserInfo();
+      assertEquals("trash-service-user", result.getUserName());
+      assertEquals("10.0.0.9", result.getRemoteAddress());
+      assertEquals("om-host", result.getHostName());
+    }
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to