Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Security Considerations with Camel HTTP Services

DZone's Guide to

Security Considerations with Camel HTTP Services

Get meaningful headers with your HTTP request using Camel without sending sensitive information.

Free Resource

Learn how API management supports better integration in Achieving Enterprise Agility with Microservices and API Management, brought to you in partnership with 3scale

In the last article we took a look at how we can combine WildFly Swarm and Camel to produce a simple Microservice that responds to HTTP requests. I want to take a little diversion at this point to discuss one of the side effects of creating HTTP services with Camel.

Let’s take a look at how Camel transfers information around its routes.

Screen Shot 2016-04-13 at 3.55.17 PM.png

The exchange contains messages, and the messages contain headers. Note that just because Camel calls metadata associated with a message a “header”, there is not a one to one mapping between Camel message headers and HTTP headers. Although, as we will see, Camel message headers and HTTP headers do often contain the same data.

Our sample application contains the very simple route of:

from("servlet:hello").to("bean:myBean");


This route has the following steps:

  1. A request is made via HTTP to the Camel servlet.
  2. The request is converted into a Camel exchange.
  3. The Camel exchange is then made available to the method defined in the CDI POJO with the name of myBean.
  4. The result of the method call in myBean is set as the body of the outgoing message, which is then sent back to the HTTP client.

If you do a GET HTTP request by opening the link https://wildfly-swarm-camel-1.herokuapp.com/camel/hello?name=Matt you will see the result of the myBean method call being returned as the body of the HTTP response (you might need to give it a minute for Heroku to boot up if you get a 404).

So far so good. But what your browser won’t show you by default are the headers that were sent with the request, and which were returned as part of the response. The screenshot below shows the headers being returned by Camel.

Screen Shot 2016-04-13 at 3.22.41 PM.png

Accept headers in a HTTP response? Why am I getting Authorization details being sent back? And what is a breadcrumbId?

What is actually happening in step 2 of the process detailed above is that the HTTP request body is being added to the Camel exchange incoming message body (for POST and PUT requests), and all HTTP request headers are being added as exchange incoming message headers.

At this point these Camel exchange message headers have no inherent meaning. Camel components can choose to configure certain aspects of their operation based on the presence or values in these headers, but for the most part these headers are simply passed around with no additional logic applied to them.

Once the route is completed, the Camel exchange incoming message becomes the outgoing message sent back to the HTTP client. Headers found in the incoming message are sent back, which is why you see so many HTTP request headers in the subsequent response.

This tendency to leak headers is something of a flaw in Camel. At best, you end up returning headers that have no meaning in a HTTP response. At worst, you may be leaking internal information back to your clients, which could be a huge security risk.

A simple solution is to create a servlet filter that maintains a whitelist of known good headers that can be sent back as a HTTP response. The class below does just that. By passing our own wrapper around the HTTP response, and preventing any header that isn’t in our whitelist from being added to the response, we ensure that our clients don’t see anything we don’t want them to.

package com.matthewcasperson.swarmdemo;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * Clean up the headers that are returned to a HTTP client by a Camel route
 */
@WebFilter("/*")
public class HeaderSanitisation implements Filter {

    /**
     * Headers we want to send back to the client
     * https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Response_fields has a more complete list
     */
    private static final List<String> WHITELIST_HEADERS = Arrays.asList(
            "Cache-Control",
            "Connection",
            "Date",
            "Pragma",
            "Trailer",
            "Transfer-Encoding",
            "Upgrade",
            "Via",
            "Warning",
            "Accept-Ranges",
            "Age",
            "ETag",
            "Location",
            "Proxy-Authenticate",
            "Retry-After",
            "Server",
            "Vary",
            "WWW-Authenticate"
    );

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
            public void setHeader(final String name, final String value) {
                if (WHITELIST_HEADERS.stream().anyMatch(e -> e.equalsIgnoreCase(name))) {
                    super.setHeader(name, value);
                }
            }

            public void addHeader(final String name, final String value) {
                if (WHITELIST_HEADERS.stream().anyMatch(e -> e.equalsIgnoreCase(name))) {
                    super.addHeader(name, value);
                }
            }
        });
    }

    @Override
    public void destroy() {

    }
}


This is a screenshot of the response from our Camel route once we sanitize the response.

Screen Shot 2016-04-13 at 4.36.28 PM.png

This is much better. These headers make sense in a HTTP response, and we haven’t inadvertently returned sensitive internal information.

You can find the source code for this project at GitHub.

You can find articles in this series here.

Unleash the power of your APIs with future-proof API management - Create your account and start your free trial today, brought to you in partnership with 3scale.

Topics:
camel ,wildfly swarm

Published at DZone with permission of Matthew Casperson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}