Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate http headers to security connector context (related to #5700) #6793

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

dependencies {
implementation 'org.slf4j:slf4j-api'
implementation 'javax.servlet:javax.servlet-api'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.testng:testng'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@

<dependencies>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: Apache-2.0 */
/* Copyright Contributors to the ODPi Egeria project. */
package org.odpi.openmetadata.http;

import java.util.Map;

/**
* HttpHeadersThreadLocal keeps ThreadLocal HTTP headers to be available for request thread.
*/
public class HttpHeadersThreadLocal {

/**
* HEADERS_THREAD_LOCAL is a ThreadLocal that holds a map of headers and their value
*/
private static ThreadLocal<Map<String, String>> HEADERS_THREAD_LOCAL = new ThreadLocal<>();

public static ThreadLocal<Map<String, String>> getHeadersThreadLocal() {
return HEADERS_THREAD_LOCAL;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* SPDX-License-Identifier: Apache-2.0 */
/* Copyright Contributors to the ODPi Egeria project. */
package org.odpi.openmetadata.http;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* HttpRequestHeadersFilter is a Java Servlet Filter that receives a list of http header names which are then
* saved from the request in HttpHeadersThreadLocal
*/
public class HttpRequestHeadersFilter implements Filter {
private List<String> headerNames;

/**
* @param headerNames list of http header names
*/
public HttpRequestHeadersFilter(List<String> headerNames) {
this.headerNames = headerNames;
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;

Map<String, String> threadLocalHeaders = new HashMap<>();

for (String headerName : headerNames) {
String headerValue = req.getHeader(headerName);
Fixed Show fixed Hide fixed
threadLocalHeaders.put(headerName, headerValue);
}

HttpHeadersThreadLocal.getHeadersThreadLocal().set(threadLocalHeaders);
filterChain.doFilter(servletRequest, servletResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.apache.tomcat.embed:tomcat-embed-core'
//implementation 'org.springframework.boot:spring-boot-starter-tomcat'
//implementation 'javax.servlet:javax.servlet-api'
// Explicitly needed for gradle - added by maven plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.odpi.openmetadata.adminservices.OMAGServerOperationalServices;
import org.odpi.openmetadata.adminservices.rest.SuccessMessageResponse;
import org.odpi.openmetadata.http.HttpHelper;
import org.odpi.openmetadata.http.HttpRequestHeadersFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
Expand All @@ -18,6 +19,7 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -77,6 +79,9 @@ public class OMAGServerPlatform
@Value("${startup.server.list}")
String startupServers;

@Value("${header.name.list}")
List<String> headerNames;

@Autowired
private Environment env;

Expand Down Expand Up @@ -213,4 +218,19 @@ public void onApplicationEvent(StartupFailEvent event) {

}

/**
* Initialization of HttpRequestHeadersFilter. headerNames is a list of headers defined in application properties.
* @return bean of an initialized FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean<HttpRequestHeadersFilter> getRequestHeadersFilter() {
FilterRegistrationBean<HttpRequestHeadersFilter> registrationBean = new FilterRegistrationBean<>();

registrationBean.setFilter(new HttpRequestHeadersFilter(headerNames));
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);

return registrationBean;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ scan.packages=org.odpi.openmetadata.*
startup.user=system
# Comma separated names of servers to be started
startup.server.list=
# Comma separated values of http headers to be added to ThreadLocal
header.name.list=

################################################
### Logging
Expand Down