rijash
(Rijash Patel)
September 2, 2019, 7:56am
1
Hi,
We are working to implement RUM agent for application pages performance monitoring.
But, if i am not wrong the RUM agent is sending data from browser to APM server by publicly exposing in internet as below format ,
https://<apm_server_ip>:8200/intake/v2/rum/events
As apm server is hosted private cloud to our company, i believe it can cause a security threat.
Can you suggest how we can handle this ??
Regards,
Rijash
Hi,
There are multiple options for you depending on what you need.
If you want to use authentication on the APM endpoint you can watch this issue: Provide integration with external authentication systems for the RUM endpoint · Issue #1718 · elastic/apm-server · GitHub
If you do not care about authentication and just want to keep the APM endpoint from being exposed you could run a proxy on your application server where you point the RUM agent to which just routes the traffic to the real APM server.
if you want to combine that you could implement a proxy in your application which does the redirect but also checks that the sender is already authenticated in your application.
There might be more but this is what we came up with. We are going with number 3 for now while closely watching the issue above. We have a Java Spring webapp where we created an endpoint /app/apm/route which is secured by Spring Security so only authenticated users can send to it.
The RUM agent is pointed to https://host/app/apm/route
The Request Mapping of the Controller is defined as /app/apm/route/**
We read the requested path of the apm url
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
PathMatcher pathMatcher = new AntPathMatcher();
String finalPath = pathMatcher.extractPathWithinPattern(bestMatchPattern, path);
private String buildTargetUrl(String path,HttpServletRequest req) {
if(req.getQueryString() != null ) {
return String.format("%s/%s?%s", SettingProvider.getApmServerUrl(),path,req.getQueryString());
}else {
return String.format("%s/%s", SettingProvider.getApmServerUrl(),path);
}
}
private void forwardRequest(String path, HttpServletRequest req, HttpServletResponse resp) {
final boolean isPost = ("POST".equals(req.getMethod()));
HttpURLConnection conn = null;
try {
String targetUrl=buildTargetUrl(path,req);
//initialize Connection
final URL url = new URL(targetUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(req.getMethod());
//copy HTTP request headers
for(String header : Collections.list(req.getHeaderNames())) {
for(String value : Collections.list(req.getHeaders(header))) {
conn.addRequestProperty(header, value);
}
}
//open connection
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(isPost);
conn.connect();
//copy HTTP Request Body
if(isPost) {
IOUtils.copy(req.getInputStream(), conn.getOutputStream());
}
//copy HTTP Response Status
resp.setStatus(conn.getResponseCode());
//Copy HTTP response headers
for(var header : conn.getHeaderFields().entrySet()) {
for(String value : header.getValue()) {
if(header.getKey() != null) {
resp.setHeader(header.getKey(), value);
}
}
}
//copy HTTP response Body
if(HttpStatus.valueOf(conn.getResponseCode()).is2xxSuccessful()) {
IOUtils.copy(conn.getInputStream(), resp.getOutputStream());
}
} catch (Exception e) {
log.debug("failed to send APM data",e);
}finally {
if(conn != null) {
conn.disconnect();
}
}
}
Hope this helps...
Best regards
Wolfram
1 Like
rijash
(Rijash Patel)
September 2, 2019, 9:00am
3
Hi Wolfram,
Thanks for your prompt response here.
As of now we have created the proxy for the APM server & planning to use the same in RUM agent configuration.
But, could you please help/guide us on the piece of configuration for sender authentication check.
What could be the configuration we need to put for the approach 3 ??
Regards,
Rijash
Hi Rijash,
This depends on the application you have. What Programming language do you use? What frameworks do you use?
If you already have the RUM agent running:
define a new endpoint in your application for the routing like https://host/myApp/apm/route
create controller for this endpoint. Important: Controller must capture all sub-Urls as we define the Url as https://host/myApp/apm/route but the Agent will call Urls like https://host/myApp/apm/route/intake/v2/rum/events
implement controller to parse the last part of the Url and to redirect the request headers, request body to the correct target Url
update authentication framework config to secure the endpoint
replace the serverUrl
in the elasticApm.init()
call by the newly implemented endpoint
Best regards
Wolfram
system
(system)
Closed
September 23, 2019, 5:21am
5
This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.