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.http; 019 020import static org.apache.hadoop.hbase.http.HttpServerFunctionalTest.createTestServer; 021import static org.apache.hadoop.hbase.http.HttpServerFunctionalTest.getServerURL; 022import static org.hamcrest.CoreMatchers.equalTo; 023import static org.hamcrest.CoreMatchers.is; 024import static org.hamcrest.CoreMatchers.not; 025import static org.hamcrest.MatcherAssert.assertThat; 026 027import java.io.IOException; 028import java.net.HttpURLConnection; 029import java.net.URL; 030import org.apache.hadoop.conf.Configuration; 031import org.apache.hadoop.hbase.HBaseClassTestRule; 032import org.apache.hadoop.hbase.testclassification.MediumTests; 033import org.hamcrest.core.Is; 034import org.hamcrest.core.IsEqual; 035import org.junit.After; 036import org.junit.ClassRule; 037import org.junit.Test; 038import org.junit.experimental.categories.Category; 039 040@Category({ HttpServerFunctionalTest.class, MediumTests.class }) 041public class TestSecurityHeadersFilter { 042 private static URL baseUrl; 043 private HttpServer http; 044 045 @ClassRule 046 public static final HBaseClassTestRule CLASS_RULE = 047 HBaseClassTestRule.forClass(TestSecurityHeadersFilter.class); 048 049 @After 050 public void tearDown() throws Exception { 051 http.stop(); 052 } 053 054 @Test 055 public void testDefaultValues() throws Exception { 056 http = createTestServer(); 057 http.start(); 058 baseUrl = getServerURL(http); 059 060 URL url = new URL(baseUrl, "/"); 061 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 062 assertThat(conn.getResponseCode(), equalTo(HttpURLConnection.HTTP_OK)); 063 064 assertThat("Header 'X-Content-Type-Options' is missing", 065 conn.getHeaderField("X-Content-Type-Options"), is(not((String) null))); 066 assertThat(conn.getHeaderField("X-Content-Type-Options"), equalTo("nosniff")); 067 assertThat("Header 'X-XSS-Protection' is missing", conn.getHeaderField("X-XSS-Protection"), 068 is(not((String) null))); 069 assertThat("Header 'X-XSS-Protection' has invalid value", 070 conn.getHeaderField("X-XSS-Protection"), equalTo("1; mode=block")); 071 072 assertThat( 073 "Header 'Strict-Transport-Security' should be missing from response," + "but it's present", 074 conn.getHeaderField("Strict-Transport-Security"), is((String) null)); 075 assertThat( 076 "Header 'Content-Security-Policy' should be missing from response," + "but it's present", 077 conn.getHeaderField("Content-Security-Policy"), is((String) null)); 078 } 079 080 @Test 081 public void testHstsAndCspSettings() throws IOException { 082 Configuration conf = new Configuration(); 083 conf.set("hbase.http.filter.hsts.value", "max-age=63072000;includeSubDomains;preload"); 084 conf.set("hbase.http.filter.csp.value", 085 "default-src https: data: 'unsafe-inline' 'unsafe-eval'"); 086 http = createTestServer(conf); 087 http.start(); 088 baseUrl = getServerURL(http); 089 090 URL url = new URL(baseUrl, "/"); 091 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 092 assertThat(conn.getResponseCode(), equalTo(HttpURLConnection.HTTP_OK)); 093 094 assertThat("Header 'Strict-Transport-Security' is missing from Rest response", 095 conn.getHeaderField("Strict-Transport-Security"), Is.is(not((String) null))); 096 assertThat("Header 'Strict-Transport-Security' has invalid value", 097 conn.getHeaderField("Strict-Transport-Security"), 098 IsEqual.equalTo("max-age=63072000;includeSubDomains;preload")); 099 100 assertThat("Header 'Content-Security-Policy' is missing from Rest response", 101 conn.getHeaderField("Content-Security-Policy"), Is.is(not((String) null))); 102 assertThat("Header 'Content-Security-Policy' has invalid value", 103 conn.getHeaderField("Content-Security-Policy"), 104 IsEqual.equalTo("default-src https: data: 'unsafe-inline' 'unsafe-eval'")); 105 } 106}