HDFS-16901: RBF: Propagates real user's username via the caller context, when a proxy user is being used. (#5346)
This commit is contained in:
parent
2e997d818d
commit
4cc33e5e37
@ -49,6 +49,7 @@ public final class CallerContext {
|
|||||||
public static final String CLIENT_PORT_STR = "clientPort";
|
public static final String CLIENT_PORT_STR = "clientPort";
|
||||||
public static final String CLIENT_ID_STR = "clientId";
|
public static final String CLIENT_ID_STR = "clientId";
|
||||||
public static final String CLIENT_CALL_ID_STR = "clientCallId";
|
public static final String CLIENT_CALL_ID_STR = "clientCallId";
|
||||||
|
public static final String REAL_USER_STR = "realUser";
|
||||||
|
|
||||||
/** The caller context.
|
/** The caller context.
|
||||||
*
|
*
|
||||||
|
@ -491,7 +491,7 @@ public Object invokeMethod(
|
|||||||
+ router.getRouterId());
|
+ router.getRouterId());
|
||||||
}
|
}
|
||||||
|
|
||||||
addClientInfoToCallerContext();
|
addClientInfoToCallerContext(ugi);
|
||||||
|
|
||||||
Object ret = null;
|
Object ret = null;
|
||||||
if (rpcMonitor != null) {
|
if (rpcMonitor != null) {
|
||||||
@ -627,14 +627,18 @@ public Object invokeMethod(
|
|||||||
/**
|
/**
|
||||||
* For tracking some information about the actual client.
|
* For tracking some information about the actual client.
|
||||||
* It adds trace info "clientIp:ip", "clientPort:port",
|
* It adds trace info "clientIp:ip", "clientPort:port",
|
||||||
* "clientId:id" and "clientCallId:callId"
|
* "clientId:id", "clientCallId:callId" and "realUser:userName"
|
||||||
* in the caller context, removing the old values if they were
|
* in the caller context, removing the old values if they were
|
||||||
* already present.
|
* already present.
|
||||||
*/
|
*/
|
||||||
private void addClientInfoToCallerContext() {
|
private void addClientInfoToCallerContext(UserGroupInformation ugi) {
|
||||||
CallerContext ctx = CallerContext.getCurrent();
|
CallerContext ctx = CallerContext.getCurrent();
|
||||||
String origContext = ctx == null ? null : ctx.getContext();
|
String origContext = ctx == null ? null : ctx.getContext();
|
||||||
byte[] origSignature = ctx == null ? null : ctx.getSignature();
|
byte[] origSignature = ctx == null ? null : ctx.getSignature();
|
||||||
|
String realUser = null;
|
||||||
|
if (ugi.getRealUser() != null) {
|
||||||
|
realUser = ugi.getRealUser().getUserName();
|
||||||
|
}
|
||||||
CallerContext.Builder builder =
|
CallerContext.Builder builder =
|
||||||
new CallerContext.Builder("", contextFieldSeparator)
|
new CallerContext.Builder("", contextFieldSeparator)
|
||||||
.append(CallerContext.CLIENT_IP_STR, Server.getRemoteAddress())
|
.append(CallerContext.CLIENT_IP_STR, Server.getRemoteAddress())
|
||||||
@ -644,6 +648,7 @@ private void addClientInfoToCallerContext() {
|
|||||||
StringUtils.byteToHexString(Server.getClientId()))
|
StringUtils.byteToHexString(Server.getClientId()))
|
||||||
.append(CallerContext.CLIENT_CALL_ID_STR,
|
.append(CallerContext.CLIENT_CALL_ID_STR,
|
||||||
Integer.toString(Server.getCallId()))
|
Integer.toString(Server.getCallId()))
|
||||||
|
.append(CallerContext.REAL_USER_STR, realUser)
|
||||||
.setSignature(origSignature);
|
.setSignature(origSignature);
|
||||||
// Append the original caller context
|
// Append the original caller context
|
||||||
if (origContext != null) {
|
if (origContext != null) {
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -218,6 +219,14 @@ public static void globalSetUp() throws Exception {
|
|||||||
cluster.setIndependentDNs();
|
cluster.setIndependentDNs();
|
||||||
|
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
|
// Setup proxy users.
|
||||||
|
conf.set("hadoop.proxyuser.testRealUser.groups", "*");
|
||||||
|
conf.set("hadoop.proxyuser.testRealUser.hosts", "*");
|
||||||
|
String loginUser = UserGroupInformation.getLoginUser().getUserName();
|
||||||
|
conf.set(String.format("hadoop.proxyuser.%s.groups", loginUser), "*");
|
||||||
|
conf.set(String.format("hadoop.proxyuser.%s.hosts", loginUser), "*");
|
||||||
|
// Enable IP proxy users.
|
||||||
|
conf.set(DFSConfigKeys.DFS_NAMENODE_IP_PROXY_USERS, "placeholder");
|
||||||
conf.setInt(DFSConfigKeys.DFS_LIST_LIMIT, 5);
|
conf.setInt(DFSConfigKeys.DFS_LIST_LIMIT, 5);
|
||||||
cluster.addNamenodeOverrides(conf);
|
cluster.addNamenodeOverrides(conf);
|
||||||
// Start NNs and DNs and wait until ready
|
// Start NNs and DNs and wait until ready
|
||||||
@ -2077,6 +2086,38 @@ public void testMkdirsWithCallerContext() throws IOException {
|
|||||||
assertTrue(verifyFileExists(routerFS, dirPath));
|
assertTrue(verifyFileExists(routerFS, dirPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRealUserPropagationInCallerContext()
|
||||||
|
throws IOException, InterruptedException {
|
||||||
|
GenericTestUtils.LogCapturer auditlog =
|
||||||
|
GenericTestUtils.LogCapturer.captureLogs(FSNamesystem.auditLog);
|
||||||
|
|
||||||
|
// Current callerContext is null
|
||||||
|
assertNull(CallerContext.getCurrent());
|
||||||
|
|
||||||
|
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
|
||||||
|
UserGroupInformation realUser = UserGroupInformation
|
||||||
|
.createUserForTesting("testRealUser", new String[]{"group"});
|
||||||
|
UserGroupInformation proxyUser = UserGroupInformation
|
||||||
|
.createProxyUser("testProxyUser", realUser);
|
||||||
|
FileSystem proxyFs = proxyUser.doAs(
|
||||||
|
(PrivilegedExceptionAction<FileSystem>) () -> router.getFileSystem());
|
||||||
|
proxyFs.listStatus(new Path("/"));
|
||||||
|
|
||||||
|
|
||||||
|
final String logOutput = auditlog.getOutput();
|
||||||
|
// Login user, which is used as the router's user, is different from the realUser.
|
||||||
|
assertNotEquals(loginUser.getUserName(), realUser.getUserName());
|
||||||
|
// Login user is used in the audit log's ugi field.
|
||||||
|
assertTrue("The login user is the proxyUser in the UGI field",
|
||||||
|
logOutput.contains(String.format("ugi=%s (auth:PROXY) via %s (auth:SIMPLE)",
|
||||||
|
proxyUser.getUserName(),
|
||||||
|
loginUser.getUserName())));
|
||||||
|
// Real user is added to the caller context.
|
||||||
|
assertTrue("The audit log should contain the real user.",
|
||||||
|
logOutput.contains(String.format("realUser:%s", realUser.getUserName())));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetBalancerBandwidth() throws Exception {
|
public void testSetBalancerBandwidth() throws Exception {
|
||||||
long defaultBandwidth =
|
long defaultBandwidth =
|
||||||
|
Loading…
Reference in New Issue
Block a user