001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rest;
019
020import static org.hamcrest.CoreMatchers.not;
021import static org.hamcrest.MatcherAssert.assertThat;
022import static org.hamcrest.core.Is.is;
023import static org.hamcrest.core.IsEqual.equalTo;
024
025import org.apache.hadoop.hbase.HBaseClassTestRule;
026import org.apache.hadoop.hbase.HBaseTestingUtil;
027import org.apache.hadoop.hbase.rest.client.Client;
028import org.apache.hadoop.hbase.rest.client.Cluster;
029import org.apache.hadoop.hbase.rest.client.Response;
030import org.apache.hadoop.hbase.testclassification.MediumTests;
031import org.apache.hadoop.hbase.testclassification.RestTests;
032import org.junit.After;
033import org.junit.ClassRule;
034import org.junit.Test;
035import org.junit.experimental.categories.Category;
036
037@Category({ RestTests.class, MediumTests.class })
038public class TestSecurityHeadersFilter {
039
040  @ClassRule
041  public static final HBaseClassTestRule CLASS_RULE =
042    HBaseClassTestRule.forClass(TestSecurityHeadersFilter.class);
043
044  private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
045  private static final HBaseRESTTestingUtility REST_TEST_UTIL = new HBaseRESTTestingUtility();
046  private static Client client;
047
048  @After
049  public void tearDown() throws Exception {
050    REST_TEST_UTIL.shutdownServletContainer();
051    TEST_UTIL.shutdownMiniCluster();
052  }
053
054  @Test
055  public void testDefaultValues() throws Exception {
056    TEST_UTIL.startMiniCluster();
057    REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
058    client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort()));
059
060    String path = "/version/cluster";
061    Response response = client.get(path);
062    assertThat(response.getCode(), equalTo(200));
063
064    assertThat("Header 'X-Content-Type-Options' is missing from Rest response",
065      response.getHeader("X-Content-Type-Options"), is(not((String) null)));
066    assertThat("Header 'X-Content-Type-Options' has invalid default value",
067      response.getHeader("X-Content-Type-Options"), equalTo("nosniff"));
068
069    assertThat("Header 'X-XSS-Protection' is missing from Rest response",
070      response.getHeader("X-XSS-Protection"), is(not((String) null)));
071    assertThat("Header 'X-XSS-Protection' has invalid default value",
072      response.getHeader("X-XSS-Protection"), equalTo("1; mode=block"));
073
074    assertThat("Header 'Strict-Transport-Security' should be missing from Rest response,"
075      + "but it's present", response.getHeader("Strict-Transport-Security"), is((String) null));
076    assertThat(
077      "Header 'Content-Security-Policy' should be missing from Rest response," + "but it's present",
078      response.getHeader("Content-Security-Policy"), is((String) null));
079  }
080
081  @Test
082  public void testHstsAndCspSettings() throws Exception {
083    TEST_UTIL.getConfiguration().set("hbase.http.filter.hsts.value",
084      "max-age=63072000;includeSubDomains;preload");
085    TEST_UTIL.getConfiguration().set("hbase.http.filter.csp.value",
086      "default-src https: data: 'unsafe-inline' 'unsafe-eval'");
087    TEST_UTIL.startMiniCluster();
088    REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
089    client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort()));
090
091    String path = "/version/cluster";
092    Response response = client.get(path);
093    assertThat(response.getCode(), equalTo(200));
094
095    assertThat("Header 'Strict-Transport-Security' is missing from Rest response",
096      response.getHeader("Strict-Transport-Security"), is(not((String) null)));
097    assertThat("Header 'Strict-Transport-Security' has invalid value",
098      response.getHeader("Strict-Transport-Security"),
099      equalTo("max-age=63072000;includeSubDomains;preload"));
100
101    assertThat("Header 'Content-Security-Policy' is missing from Rest response",
102      response.getHeader("Content-Security-Policy"), is(not((String) null)));
103    assertThat("Header 'Content-Security-Policy' has invalid value",
104      response.getHeader("Content-Security-Policy"),
105      equalTo("default-src https: data: 'unsafe-inline' 'unsafe-eval'"));
106  }
107}