#include #include #include #include using namespace crow; using namespace std; // Tests that the security headers are added correctly TEST(SecurityHeaders, TestHeadersExist) { App app; app.bindaddr("127.0.0.1").port(45451); BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); auto _ = async(launch::async, [&] { app.run(); }); asio::io_context is; std::array buf; std::string sendmsg; { // Retry a couple of times waiting for the server to come up // TODO(ed) This is really unfortunate, and should use some form of // mock asio::ip::tcp::socket c(is); for (int i = 0; i < 200; i++) { try { c.connect(asio::ip::tcp::endpoint( asio::ip::address::from_string("127.0.0.1"), 45451)); c.close(); break; } catch (const std::exception& e) { // do nothing. We expect this to fail while the server is // starting up } } } // Test correct login credentials sendmsg = "GET /\r\n\r\n"; asio::ip::tcp::socket c(is); c.connect(asio::ip::tcp::endpoint( asio::ip::address::from_string("127.0.0.1"), 45451)); c.send(asio::buffer(sendmsg)); c.receive(asio::buffer(buf)); c.close(); auto return_code = std::string(&buf[9], &buf[12]); EXPECT_EQ("200", return_code); std::string response(std::begin(buf), std::end(buf)); // This is a routine to split strings until a blank is hit // TODO(ed) this should really use the HTTP parser std::vector headers; std::string::size_type pos = 0; std::string::size_type prev = 0; while ((pos = response.find("\r\n", prev)) != std::string::npos) { auto this_string = response.substr(prev, pos - prev); if (this_string == "") { break; } headers.push_back(this_string); prev = pos + 2; } headers.push_back(response.substr(prev)); EXPECT_EQ(headers[0], "HTTP/1.1 200 OK"); EXPECT_THAT(headers, ::testing::Contains("Strict-Transport-Security: " "max-age=31536000; " "includeSubdomains; preload")); EXPECT_THAT(headers, ::testing::Contains("X-UA-Compatible: IE=11")); EXPECT_THAT(headers, ::testing::Contains("X-Frame-Options: DENY")); EXPECT_THAT(headers, ::testing::Contains("X-XSS-Protection: 1; mode=block")); EXPECT_THAT(headers, ::testing::Contains( "X-Content-Security-Policy: default-src 'self'")); app.stop(); }