This is an automated email from the ASF dual-hosted git repository.

asherman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit 59667b751b1aaac808c83a276e458e55ba116512
Author: Michael Smith <[email protected]>
AuthorDate: Wed Mar 29 11:21:15 2023 -0700

    IMPALA-12031: Add security-related HTTP headers
    
    Adds security-related headers
    - X-Content-Type-Options: nosniff
    - Cache-Control: no-store
    - Strict-Transport-Security: max-age=31536000; includeSubDomains
    
    These are primarily no-ops as Impala never serves HTTP and HTTPS at the
    same time, and does not provide any way to upload files.
    Strict-Transport-Security is only added when serving HTTPS.
    
    Testing:
    - manually interacted with web UI over HTTP and HTTPS, verified headers
      in responses
    - ran webserver-test
    
    Change-Id: I58e12961e7faa31f42bc2e6bd4de23b56e3dfd5f
    Reviewed-on: http://gerrit.cloudera.org:8080/19661
    Reviewed-by: Impala Public Jenkins <[email protected]>
    Tested-by: Impala Public Jenkins <[email protected]>
---
 be/src/util/webserver-test.cc | 25 +++++++++++++++++++++++++
 be/src/util/webserver.cc      |  7 +++++++
 2 files changed, 32 insertions(+)

diff --git a/be/src/util/webserver-test.cc b/be/src/util/webserver-test.cc
index 26ee1ee28..29256cbea 100644
--- a/be/src/util/webserver-test.cc
+++ b/be/src/util/webserver-test.cc
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#include <array>
+#include <memory>
 #include <string>
 #include <boost/asio.hpp>
 #include <boost/bind.hpp>
@@ -136,6 +138,19 @@ Status HttpGet(const string& host, const int32_t& port, 
const string& url_path,
   return HttpRequest{url_path, host, port}.Do(out, expected_code, method);
 }
 
+string exec(const char* cmd) {
+    std::array<char, 1024> buffer;
+    string result;
+    unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
+    if (!pipe) {
+      throw std::runtime_error(Substitute("popen() failed with $0", errno));
+    }
+    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
+      result += buffer.data();
+    }
+    return result;
+}
+
 TEST(Webserver, SmokeTest) {
   MetricGroup metrics("webserver-test");
   Webserver webserver("", FLAGS_webserver_port, &metrics);
@@ -144,6 +159,9 @@ TEST(Webserver, SmokeTest) {
 
   stringstream contents;
   ASSERT_OK(HttpGet("localhost", FLAGS_webserver_port, "/", &contents));
+  ASSERT_TRUE(contents.str().find("X-Content-Type-Options: nosniff") != 
string::npos);
+  ASSERT_TRUE(contents.str().find("Cache-Control: no-store") != string::npos);
+  ASSERT_TRUE(contents.str().find("Strict-Transport-Security: ") == 
string::npos);
 }
 
 void PostOnlyCallback(bool* success, const Webserver::WebRequest& req,
@@ -285,6 +303,13 @@ TEST(Webserver, SslTest) {
   MetricGroup metrics("webserver-test");
   Webserver webserver("", FLAGS_webserver_port, &metrics);
   ASSERT_OK(webserver.Start());
+  AddDefaultUrlCallbacks(&webserver);
+
+  string cmd = Substitute("curl -v -f -s --cacert $0 'https://localhost:$1' 
2>&1",
+      FLAGS_webserver_certificate_file, FLAGS_webserver_port);
+  string response = exec(cmd.c_str());
+  ASSERT_TRUE(response.find(
+      "Strict-Transport-Security: max-age=31536000; includeSubDomains") != 
string::npos);
 }
 
 TEST(Webserver, SslBadCertTest) {
diff --git a/be/src/util/webserver.cc b/be/src/util/webserver.cc
index 9d2716591..d5a754911 100644
--- a/be/src/util/webserver.cc
+++ b/be/src/util/webserver.cc
@@ -239,9 +239,16 @@ void SendResponse(struct sq_connection* connection, const 
string& response_code_
     oss << h << CRLF;
   }
   oss << "X-Frame-Options: " << FLAGS_webserver_x_frame_options << CRLF;
+  oss << "X-Content-Type-Options: nosniff" << CRLF;
+  oss << "Cache-Control: no-store" << CRLF;
   if (!FLAGS_disable_content_security_policy_header) {
     oss << "Content-Security-Policy: " << CSP_HEADER << CRLF;
   }
+
+  struct sq_request_info* request_info = sq_get_request_info(connection);
+  if (request_info->is_ssl) {
+    oss << "Strict-Transport-Security: max-age=31536000; includeSubDomains" << 
CRLF;
+  }
   oss << "Content-Type: " << content_type << CRLF;
   oss << "Content-Length: " << content.size() << CRLF;
   oss << CRLF;

Reply via email to