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]