Skip to content

Commit

Permalink
Mild switch to RequestChannel
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Nied <[email protected]>
  • Loading branch information
peternied committed Oct 2, 2023
1 parent fa98ba9 commit 9844df9
Show file tree
Hide file tree
Showing 37 changed files with 246 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

import com.google.common.annotations.VisibleForTesting;
import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
import org.apache.cxf.rs.security.jose.jwt.JwtToken;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand All @@ -39,7 +41,7 @@
import org.opensearch.rest.RestChannel;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.security.auth.HTTPAuthenticator;
import org.opensearch.security.filter.SecurityRequest;
import org.opensearch.security.filter.SecurityRequestChannel;
import org.opensearch.security.user.AuthCredentials;

public abstract class AbstractHTTPJwtAuthenticator implements HTTPAuthenticator {
Expand Down Expand Up @@ -83,7 +85,7 @@ public AbstractHTTPJwtAuthenticator(Settings settings, Path configPath) {

@Override
@SuppressWarnings("removal")
public AuthCredentials extractCredentials(final SecurityRequest request, final ThreadContext context)
public AuthCredentials extractCredentials(final SecurityRequestChannel request, final ThreadContext context)
throws OpenSearchSecurityException {
final SecurityManager sm = System.getSecurityManager();

Expand All @@ -101,7 +103,7 @@ public AuthCredentials run() {
return creds;
}

private AuthCredentials extractCredentials0(final SecurityRequest request) throws OpenSearchSecurityException {
private AuthCredentials extractCredentials0(final SecurityRequestChannel request) throws OpenSearchSecurityException {

String jwtString = getJwtTokenString(request);

Expand Down Expand Up @@ -142,7 +144,7 @@ private AuthCredentials extractCredentials0(final SecurityRequest request) throw

}

protected String getJwtTokenString(SecurityRequest request) {
protected String getJwtTokenString(SecurityRequestChannel request) {
String jwtToken = request.header(jwtHeaderName);
if (isDefaultAuthHeader && jwtToken != null && BASIC.matcher(jwtToken).matches()) {
jwtToken = null;
Expand Down Expand Up @@ -237,11 +239,11 @@ public String[] extractRoles(JwtClaims claims) {
protected abstract KeyProvider initKeyProvider(Settings settings, Path configPath) throws Exception;

@Override
public boolean reRequestAuthentication(RestChannel channel, AuthCredentials authCredentials) {
final BytesRestResponse wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, "");
wwwAuthenticateResponse.addHeader("WWW-Authenticate", "Bearer realm=\"OpenSearch Security\"");
channel.sendResponse(wwwAuthenticateResponse);
return true;
public boolean reRequestAuthentication(final SecurityRequestChannel request, AuthCredentials authCredentials) {
return request.completeWithResponse(
HttpStatus.SC_UNAUTHORIZED,
Map.of("WWW-Authenticate", "Bearer realm=\"OpenSearch Security\""),
"");
}

public String getRequiredAudience() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

Expand All @@ -23,6 +24,7 @@
import io.jsonwebtoken.JwtParserBuilder;
import io.jsonwebtoken.security.WeakKeyException;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand All @@ -34,7 +36,7 @@
import org.opensearch.rest.RestChannel;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.security.auth.HTTPAuthenticator;
import org.opensearch.security.filter.SecurityRequest;
import org.opensearch.security.filter.SecurityRequestChannel;
import org.opensearch.security.user.AuthCredentials;
import org.opensearch.security.util.KeyUtils;

Expand Down Expand Up @@ -84,7 +86,7 @@ public HTTPJwtAuthenticator(final Settings settings, final Path configPath) {

@Override
@SuppressWarnings("removal")
public AuthCredentials extractCredentials(final SecurityRequest request, final ThreadContext context)
public AuthCredentials extractCredentials(final SecurityRequestChannel request, final ThreadContext context)
throws OpenSearchSecurityException {
final SecurityManager sm = System.getSecurityManager();

Expand All @@ -102,7 +104,7 @@ public AuthCredentials run() {
return creds;
}

private AuthCredentials extractCredentials0(final SecurityRequest request) {
private AuthCredentials extractCredentials0(final SecurityRequestChannel request) {
if (jwtParser == null) {
log.error("Missing Signing Key. JWT authentication will not work");
return null;
Expand Down Expand Up @@ -172,19 +174,19 @@ private AuthCredentials extractCredentials0(final SecurityRequest request) {
}

@Override
public boolean reRequestAuthentication(final RestChannel channel, AuthCredentials creds) {
final BytesRestResponse wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, "");
wwwAuthenticateResponse.addHeader("WWW-Authenticate", "Bearer realm=\"OpenSearch Security\"");
channel.sendResponse(wwwAuthenticateResponse);
return true;
public boolean reRequestAuthentication(final SecurityRequestChannel channel, AuthCredentials creds) {
return channel.completeWithResponse(
HttpStatus.SC_UNAUTHORIZED,
Map.of("WWW-Authenticate", "Bearer realm=\"OpenSearch Security\""),
"");
}

@Override
public String getType() {
return "jwt";
}

protected String extractSubject(final Claims claims, final SecurityRequest request) {
protected String extractSubject(final Claims claims, final SecurityRequestChannel request) {
String subject = claims.getSubject();
if (subjectKey != null) {
// try to get roles from claims, first as Object to avoid having to catch the ExpectedTypeException
Expand All @@ -208,7 +210,7 @@ protected String extractSubject(final Claims claims, final SecurityRequest reque
}

@SuppressWarnings("unchecked")
protected String[] extractRoles(final Claims claims, final SecurityRequest request) {
protected String[] extractRoles(final Claims claims, final SecurityRequestChannel request) {
// no roles key specified
if (rolesKey == null) {
return new String[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@
import java.security.PrivilegedExceptionAction;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

import com.google.common.base.Strings;

import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.ietf.jgss.GSSContext;
Expand All @@ -52,12 +56,11 @@
import org.opensearch.rest.RestChannel;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.security.auth.HTTPAuthenticator;
import org.opensearch.security.filter.SecurityRequest;
import org.opensearch.security.filter.SecurityRequestChannel;
import org.opensearch.security.user.AuthCredentials;

public class HTTPSpnegoAuthenticator implements HTTPAuthenticator {

private static final String EMPTY_STRING = "";
private static final Oid[] KRB_OIDS = new Oid[] { KrbConstants.SPNEGO, KrbConstants.KRB5MECH };

protected final Logger log = LogManager.getLogger(this.getClass());
Expand Down Expand Up @@ -171,7 +174,7 @@ public Void run() {

@Override
@SuppressWarnings("removal")
public AuthCredentials extractCredentials(final SecurityRequest request, final ThreadContext threadContext) {
public AuthCredentials extractCredentials(final SecurityRequestChannel request, final ThreadContext threadContext) {
final SecurityManager sm = System.getSecurityManager();

if (sm != null) {
Expand All @@ -188,7 +191,7 @@ public AuthCredentials run() {
return creds;
}

private AuthCredentials extractCredentials0(final SecurityRequest request) {
private AuthCredentials extractCredentials0(final SecurityRequestChannel request) {

if (acceptorPrincipal == null || acceptorKeyTabPath == null) {
log.error("Missing acceptor principal or keytab configuration. Kerberos authentication will not work");
Expand Down Expand Up @@ -280,27 +283,24 @@ public GSSCredential run() throws GSSException {
}

@Override
public boolean reRequestAuthentication(final RestChannel channel, AuthCredentials creds) {

final BytesRestResponse wwwAuthenticateResponse;
XContentBuilder response = getNegotiateResponseBody();

if (response != null) {
wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, response);
} else {
wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, EMPTY_STRING);
public boolean reRequestAuthentication(final SecurityRequestChannel request, AuthCredentials creds) {
String responseBody = "";
final String negotiateResponseBody = getNegotiateResponseBody();
if (negotiateResponseBody != null) {
responseBody = negotiateResponseBody;
}

final Map<String, String> headers = new HashMap<>();
if (creds == null || creds.getNativeCredentials() == null) {
wwwAuthenticateResponse.addHeader("WWW-Authenticate", "Negotiate");
headers.put("WWW-Authenticate", "Negotiate");
} else {
wwwAuthenticateResponse.addHeader(
headers.put(
"WWW-Authenticate",
"Negotiate " + Base64.getEncoder().encodeToString((byte[]) creds.getNativeCredentials())
);
}
channel.sendResponse(wwwAuthenticateResponse);
return true;

return request.completeWithResponse(HttpStatus.SC_UNAUTHORIZED, headers, responseBody);
}

@Override
Expand Down Expand Up @@ -372,7 +372,7 @@ private static String getUsernameFromGSSContext(final GSSContext gssContext, fin
return null;
}

private XContentBuilder getNegotiateResponseBody() {
private String getNegotiateResponseBody() {
try {
XContentBuilder negotiateResponseBody = XContentFactory.jsonBuilder();
negotiateResponseBody.startObject();
Expand All @@ -384,7 +384,7 @@ private XContentBuilder getNegotiateResponseBody() {
negotiateResponseBody.endObject();
negotiateResponseBody.endObject();
negotiateResponseBody.endObject();
return negotiateResponseBody;
return negotiateResponseBody.toString();
} catch (Exception ex) {
log.error("Can't construct response body", ex);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.security.PrivateKey;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -35,6 +36,7 @@
import net.shibboleth.utilities.java.support.xml.BasicParserPool;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensaml.core.config.InitializationException;
Expand All @@ -61,7 +63,8 @@
import org.opensearch.core.rest.RestStatus;
import org.opensearch.security.auth.Destroyable;
import org.opensearch.security.auth.HTTPAuthenticator;
import org.opensearch.security.filter.SecurityRequest;
import org.opensearch.security.filter.SecurityRequestChannel;
import org.opensearch.security.filter.SecurityRequestFactory.SecurityRestRequest;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.security.support.PemKeyReader;
import org.opensearch.security.user.AuthCredentials;
Expand Down Expand Up @@ -150,7 +153,7 @@ public HTTPSamlAuthenticator(final Settings settings, final Path configPath) {
}

@Override
public AuthCredentials extractCredentials(final SecurityRequest request, final ThreadContext threadContext)
public AuthCredentials extractCredentials(final SecurityRequestChannel request, final ThreadContext threadContext)
throws OpenSearchSecurityException {
Matcher matcher = PATTERN_PATH_PREFIX.matcher(request.path());
final String suffix = matcher.matches() ? matcher.group(2) : null;
Expand All @@ -173,23 +176,28 @@ public String getType() {
}

@Override
public boolean reRequestAuthentication(RestChannel restChannel, AuthCredentials authCredentials) {
public boolean reRequestAuthentication(final SecurityRequestChannel request, final AuthCredentials authCredentials) {
try {
RestRequest restRequest = restChannel.request();
Matcher matcher = PATTERN_PATH_PREFIX.matcher(restRequest.path());
Matcher matcher = PATTERN_PATH_PREFIX.matcher(request.path());
final String suffix = matcher.matches() ? matcher.group(2) : null;
if (API_AUTHTOKEN_SUFFIX.equals(suffix) && this.authTokenProcessorHandler.handle(restRequest, restChannel)) {
return true;

if (request instanceof SecurityRestRequest) {
final SecurityRestRequest securityRequestChannel = (SecurityRestRequest)request;
final RestRequest restRequest = securityRequestChannel.breakEncapulation().v1();
final RestChannel channel = securityRequestChannel.breakEncapulation().v2();
// TODO: This codebase REQUIRES the body of the request, seems like we need to escape the SecurityRequestChannel
if (API_AUTHTOKEN_SUFFIX.equals(suffix) && this.authTokenProcessorHandler.handle(restRequest, channel)) {
return true;
}
} else {
// If the request is not SecurityRestRequest type, we could not read the body to process the response, this
// means were are in a potential exit early flow
return false;
}

Saml2Settings saml2Settings = this.saml2SettingsProvider.getCached();
BytesRestResponse authenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, "");

authenticateResponse.addHeader("WWW-Authenticate", getWwwAuthenticateHeader(saml2Settings));

restChannel.sendResponse(authenticateResponse);

return true;
return request.completeWithResponse(HttpStatus.SC_UNAUTHORIZED, Map.of("WWW-Authenticate", getWwwAuthenticateHeader(saml2Settings)), "");
} catch (Exception e) {
log.error("Error in reRequestAuthentication()", e);
return false;
Expand Down Expand Up @@ -400,7 +408,7 @@ String buildLogoutUrl(AuthCredentials authCredentials) {

}

private void initLogoutUrl(SecurityRequest restRequest, ThreadContext threadContext, AuthCredentials authCredentials) {
private void initLogoutUrl(SecurityRequestChannel restRequest, ThreadContext threadContext, AuthCredentials authCredentials) {
threadContext.putTransient(ConfigConstants.SSO_LOGOUT_URL, buildLogoutUrl(authCredentials));
}

Expand Down
14 changes: 7 additions & 7 deletions src/main/java/org/opensearch/security/auditlog/AuditLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,21 @@
import org.opensearch.core.index.shard.ShardId;
import org.opensearch.security.auditlog.config.AuditConfig;
import org.opensearch.security.compliance.ComplianceConfig;
import org.opensearch.security.filter.SecurityRequest;
import org.opensearch.security.filter.SecurityRequestChannel;
import org.opensearch.tasks.Task;
import org.opensearch.transport.TransportRequest;

public interface AuditLog extends Closeable {

// login
void logFailedLogin(String effectiveUser, boolean securityadmin, String initiatingUser, SecurityRequest request);
void logFailedLogin(String effectiveUser, boolean securityadmin, String initiatingUser, SecurityRequestChannel request);

void logSucceededLogin(String effectiveUser, boolean securityadmin, String initiatingUser, SecurityRequest request);
void logSucceededLogin(String effectiveUser, boolean securityadmin, String initiatingUser, SecurityRequestChannel request);

// privs
void logMissingPrivileges(String privilege, String effectiveUser, SecurityRequest request);
void logMissingPrivileges(String privilege, String effectiveUser, SecurityRequestChannel request);

void logGrantedPrivileges(String effectiveUser, SecurityRequest request);
void logGrantedPrivileges(String effectiveUser, SecurityRequestChannel request);

void logMissingPrivileges(String privilege, TransportRequest request, Task task);

Expand All @@ -63,13 +63,13 @@ public interface AuditLog extends Closeable {
// spoof
void logBadHeaders(TransportRequest request, String action, Task task);

void logBadHeaders(SecurityRequest request);
void logBadHeaders(SecurityRequestChannel request);

void logSecurityIndexAttempt(TransportRequest request, String action, Task task);

void logSSLException(TransportRequest request, Throwable t, String action, Task task);

void logSSLException(SecurityRequest request, Throwable t);
void logSSLException(SecurityRequestChannel request, Throwable t);

void logDocumentRead(String index, String id, ShardId shardId, Map<String, String> fieldNameValues);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
package org.opensearch.security.auditlog;

import org.opensearch.OpenSearchException;
import org.opensearch.security.filter.SecurityRequest;
import org.opensearch.security.filter.SecurityRequestChannel;
import org.opensearch.security.ssl.SslExceptionHandler;
import org.opensearch.tasks.Task;
import org.opensearch.transport.TransportRequest;
Expand All @@ -42,7 +42,7 @@ public AuditLogSslExceptionHandler(final AuditLog auditLog) {
}

@Override
public void logError(Throwable t, SecurityRequest request, int type) {
public void logError(Throwable t, SecurityRequestChannel request, int type) {
switch (type) {
case 0:
auditLog.logSSLException(request, t);
Expand Down
Loading

0 comments on commit 9844df9

Please sign in to comment.