Skip to content

Commit

Permalink
InjectSecurity - inject User object in UserInfo in threadContext (ope…
Browse files Browse the repository at this point in the history
…nsearch-project#396)

* Added user_info injection of User object in InjectSecurity

Signed-off-by: Petar <petar.dzepina@gmail.com>
  • Loading branch information
petardz authored Apr 13, 2023
1 parent deed4bd commit f7639aa
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
39 changes: 37 additions & 2 deletions src/main/java/org/opensearch/commons/InjectSecurity.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS;

import java.util.List;
import java.util.StringJoiner;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.common.Strings;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.util.concurrent.ThreadContext;
import org.opensearch.commons.authuser.User;

/**
* For background jobs usage only. User or Roles injection can be done using transport layer only.
Expand Down Expand Up @@ -91,6 +93,7 @@ public InjectSecurity(final String id, final Settings settings, final ThreadCont

/**
* Injects user or roles, based on opendistro_security_use_injected_user_for_plugins setting. By default injects roles.
* Expects threadContext to be stashed
* @param user
* @param roles
*/
Expand All @@ -104,7 +107,8 @@ public void inject(final String user, final List<String> roles) {

/**
* Injects user.
* @param user
* Expects threadContext to be stashed
* @param user name
*/
public void injectUser(final String user) {
if (Strings.isNullOrEmpty(user)) {
Expand All @@ -115,8 +119,39 @@ public void injectUser(final String user) {
threadContext.putTransient(INJECTED_USER, user);
log.debug("{}, InjectSecurity - inject roles: {}", Thread.currentThread().getName(), id);
} else {
log.error("{}, InjectSecurity- most likely thread context corruption : {}", Thread.currentThread().getName(), id);
log.error("{}, InjectSecurity - most likely thread context corruption : {}", Thread.currentThread().getName(), id);
}
}

/**
* Injects user object into user info.
* Expects threadContext to be stashed.
* @param user
*/
public void injectUserInfo(final User user) {
if (user == null) {
return;
}
String userObjectAsString = threadContext.getTransient(ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT);
if (userObjectAsString != null) {
log
.error(
"{}, InjectSecurity - id: [{}] found existing user_info: {}",
Thread.currentThread().getName(),
id,
userObjectAsString
);
return;
}
StringJoiner joiner = new StringJoiner("|");
joiner.add(user.getName());
joiner.add(java.lang.String.join(",", user.getBackendRoles()));
joiner.add(java.lang.String.join(",", user.getRoles()));
String requestedTenant = user.getRequestedTenant();
if (!Strings.isNullOrEmpty(requestedTenant)) {
joiner.add(requestedTenant);
}
threadContext.putTransient(ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT, joiner.toString());
}

/**
Expand Down
39 changes: 39 additions & 0 deletions src/test/java/org/opensearch/commons/InjectSecurityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.opensearch.commons.ConfigConstants.INJECTED_USER;
import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_INJECTED_ROLES;
import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT;
import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.util.concurrent.ThreadContext;
import org.opensearch.commons.authuser.User;

public class InjectSecurityTest {

Expand Down Expand Up @@ -85,6 +88,42 @@ public void testInjectUser() {
assertNull(threadContext.getTransient(INJECTED_USER));
}

@Test
public void testInjectUserInfo() {
Settings settings = Settings.builder().build();
Settings headerSettings = Settings.builder().put("request.headers.default", "1").build();
ThreadContext threadContext = new ThreadContext(headerSettings);
threadContext.putHeader("name", "opendistro");
threadContext.putTransient("ctx.name", "plugin");

assertEquals("1", threadContext.getHeader("default"));
assertEquals("opendistro", threadContext.getHeader("name"));
assertEquals("plugin", threadContext.getTransient("ctx.name"));

User user = new User(
"Bob",
List.of("backendRole1", "backendRole2"),
List.of("role1", "role2"),
List.of("attr1", "attr2"),
"tenant1"
);
try (InjectSecurity helper = new InjectSecurity("test-name", null, threadContext)) {
helper.injectUserInfo(user);
assertEquals("1", threadContext.getHeader("default"));
assertEquals("opendistro", threadContext.getHeader("name"));
assertEquals("plugin", threadContext.getTransient("ctx.name"));
assertNotNull(threadContext.getTransient(OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT));
assertEquals(
"Bob|backendRole1,backendRole2|role1,role2|tenant1",
threadContext.getTransient(OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT)
);
}
assertEquals("1", threadContext.getHeader("default"));
assertEquals("opendistro", threadContext.getHeader("name"));
assertEquals("plugin", threadContext.getTransient("ctx.name"));
assertNull(threadContext.getTransient(OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT));
}

@Test
public void testInjectProperty() {
Settings settings = Settings.builder().put(OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS, false).build();
Expand Down

0 comments on commit f7639aa

Please sign in to comment.