summaryrefslogtreecommitdiff
path: root/src/token_authorization_middleware_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/token_authorization_middleware_test.cpp')
-rw-r--r--src/token_authorization_middleware_test.cpp527
1 files changed, 281 insertions, 246 deletions
diff --git a/src/token_authorization_middleware_test.cpp b/src/token_authorization_middleware_test.cpp
index ab735b3a52..812a6d193e 100644
--- a/src/token_authorization_middleware_test.cpp
+++ b/src/token_authorization_middleware_test.cpp
@@ -1,287 +1,322 @@
#include "token_authorization_middleware.hpp"
+#include "webserver_common.hpp"
+
#include <condition_variable>
#include <future>
#include <mutex>
-#include "webserver_common.hpp"
+
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace crow;
-class TokenAuth : public ::testing::Test {
- public:
- TokenAuth()
- : lk(std::unique_lock<std::mutex>(m)),
- io(std::make_shared<boost::asio::io_service>()) {}
-
- std::mutex m;
- std::condition_variable cv;
- std::unique_lock<std::mutex> lk;
- std::shared_ptr<boost::asio::io_service> io;
- int testPort = 45451;
+class TokenAuth : public ::testing::Test
+{
+ public:
+ TokenAuth() :
+ lk(std::unique_lock<std::mutex>(m)),
+ io(std::make_shared<boost::asio::io_service>())
+ {
+ }
+
+ std::mutex m;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lk;
+ std::shared_ptr<boost::asio::io_service> io;
+ int testPort = 45451;
};
-TEST_F(TokenAuth, SpecialResourcesAreAcceptedWithoutAuth) {
- CrowApp app(io);
- crow::token_authorization::requestRoutes(app);
- BMCWEB_ROUTE(app, "/redfish/v1")
- ([]() { return boost::beast::http::status::ok; });
- auto _ = std::async(std::launch::async, [&] {
- app.port(testPort).run();
- cv.notify_one();
- io->run();
- });
-
- asio::io_service is;
- std::string sendmsg;
-
- static char buf[2048];
-
- // Homepage should be passed with no 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, 2048));
- c.close();
- EXPECT_EQ("200", std::string(buf + 9, buf + 12));
- }
+TEST_F(TokenAuth, SpecialResourcesAreAcceptedWithoutAuth)
+{
+ CrowApp app(io);
+ crow::token_authorization::requestRoutes(app);
+ BMCWEB_ROUTE(app, "/redfish/v1")
+ ([]() { return boost::beast::http::status::ok; });
+ auto _ = std::async(std::launch::async, [&] {
+ app.port(testPort).run();
+ cv.notify_one();
+ io->run();
+ });
+
+ asio::io_service is;
+ std::string sendmsg;
+
+ static char buf[2048];
+
+ // Homepage should be passed with no 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, 2048));
+ c.close();
+ EXPECT_EQ("200", std::string(buf + 9, buf + 12));
+ }
- // static should be passed with no credentials
- sendmsg = "GET /static/index.html\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, 2048));
- c.close();
- EXPECT_EQ("404", std::string(buf + 9, buf + 12));
- }
+ // static should be passed with no credentials
+ sendmsg = "GET /static/index.html\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, 2048));
+ c.close();
+ EXPECT_EQ("404", std::string(buf + 9, buf + 12));
+ }
- app.stop();
+ app.stop();
}
// Tests that Base64 basic strings work
-TEST(TokenAuthentication, TestRejectedResource) {
- App<crow::persistent_data::Middleware, crow::token_authorization::Middleware>
- app;
- app.bindaddr("127.0.0.1").port(45451);
- BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
- auto _ = async(std::launch::async, [&] { app.run(); });
-
- asio::io_service is;
- static char buf[2048];
-
- // Other resources should not be passed
- std::string sendmsg = "GET /foo\r\n\r\n";
- 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));
- } catch (std::exception e) {
- // do nothing
+TEST(TokenAuthentication, TestRejectedResource)
+{
+ App<crow::persistent_data::Middleware,
+ crow::token_authorization::Middleware>
+ app;
+ app.bindaddr("127.0.0.1").port(45451);
+ BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
+ auto _ = async(std::launch::async, [&] { app.run(); });
+
+ asio::io_service is;
+ static char buf[2048];
+
+ // Other resources should not be passed
+ std::string sendmsg = "GET /foo\r\n\r\n";
+ 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));
+ }
+ catch (std::exception e)
+ {
+ // do nothing
+ }
}
- }
- c.send(asio::buffer(sendmsg));
- c.receive(asio::buffer(buf, 2048));
- c.close();
- EXPECT_EQ("401", std::string(buf + 9, buf + 12));
+ c.send(asio::buffer(sendmsg));
+ c.receive(asio::buffer(buf, 2048));
+ c.close();
+ EXPECT_EQ("401", std::string(buf + 9, buf + 12));
- app.stop();
+ app.stop();
}
// Tests that Base64 basic strings work
-TEST(TokenAuthentication, TestGetLoginUrl) {
- App<crow::persistent_data::Middleware, crow::token_authorization::Middleware>
- app;
- app.bindaddr("127.0.0.1").port(45451);
- BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
- auto _ = async(std::launch::async, [&] { app.run(); });
-
- asio::io_service is;
- static char buf[2048];
-
- // Other resources should not be passed
- std::string sendmsg = "GET /login\r\n\r\n";
- 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));
- } catch (std::exception e) {
- // do nothing
+TEST(TokenAuthentication, TestGetLoginUrl)
+{
+ App<crow::persistent_data::Middleware,
+ crow::token_authorization::Middleware>
+ app;
+ app.bindaddr("127.0.0.1").port(45451);
+ BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
+ auto _ = async(std::launch::async, [&] { app.run(); });
+
+ asio::io_service is;
+ static char buf[2048];
+
+ // Other resources should not be passed
+ std::string sendmsg = "GET /login\r\n\r\n";
+ 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));
+ }
+ catch (std::exception e)
+ {
+ // do nothing
+ }
}
- }
- c.send(asio::buffer(sendmsg));
- c.receive(asio::buffer(buf, 2048));
- c.close();
- EXPECT_EQ("401", std::string(buf + 9, buf + 12));
+ c.send(asio::buffer(sendmsg));
+ c.receive(asio::buffer(buf, 2048));
+ c.close();
+ EXPECT_EQ("401", std::string(buf + 9, buf + 12));
- app.stop();
+ app.stop();
}
// Tests boundary conditions on login
-TEST(TokenAuthentication, TestPostBadLoginUrl) {
- App<crow::persistent_data::Middleware, crow::token_authorization::Middleware>
- app;
- app.bindaddr("127.0.0.1").port(45451);
- BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
- auto _ = async(std::launch::async, [&] { app.run(); });
-
- asio::io_service is;
- std::array<char, 2048> buf;
- std::string sendmsg;
-
- auto send_to_localhost = [&is, &buf](std::string sendmsg) {
- 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();
- };
-
- {
- // Retry a couple of times waiting for the server to come up
- asio::ip::tcp::socket c(is);
- for (int i = 0; i < 200; i++) {
- try {
+TEST(TokenAuthentication, TestPostBadLoginUrl)
+{
+ App<crow::persistent_data::Middleware,
+ crow::token_authorization::Middleware>
+ app;
+ app.bindaddr("127.0.0.1").port(45451);
+ BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
+ auto _ = async(std::launch::async, [&] { app.run(); });
+
+ asio::io_service is;
+ std::array<char, 2048> buf;
+ std::string sendmsg;
+
+ auto send_to_localhost = [&is, &buf](std::string sendmsg) {
+ 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();
- break;
- } catch (std::exception e) {
- // do nothing. We expect this to fail while the server is starting up
- }
+ };
+
+ {
+ // Retry a couple of times waiting for the server to come up
+ 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 (std::exception e)
+ {
+ // do nothing. We expect this to fail while the server is
+ // starting up
+ }
+ }
}
- }
-
- // Test blank login credentials
- sendmsg = "POST /login\r\nContent-Length:0\r\n\r\n\r\n";
- {
- send_to_localhost(sendmsg);
- auto return_code = std::string(&buf[9], &buf[12]);
- EXPECT_EQ("400", return_code);
- }
-
- // Test wrong login credentials
- sendmsg =
- "POST /login\r\nContent-Length:38\r\n\r\n{\"username\": \"foo\", "
- "\"password\": \"bar\"}\r\n";
- {
- send_to_localhost(sendmsg);
- auto return_code = std::string(&buf[9], &buf[12]);
- EXPECT_EQ("401", return_code);
- // TODO(ed) need to test more here. Response string?
- }
-
- // Test only sending a username
- sendmsg =
- "POST /login\r\nContent-Length:19\r\n\r\n{\"username\": \"foo\"}\r\n";
- {
- send_to_localhost(sendmsg);
- auto return_code = std::string(&buf[9], &buf[12]);
- EXPECT_EQ("400", return_code);
- }
-
- // Test only sending a password
- sendmsg =
- "POST /login\r\nContent-Length:19\r\n\r\n{\"password\": \"foo\"}\r\n";
- {
- send_to_localhost(sendmsg);
- auto return_code = std::string(&buf[9], &buf[12]);
- EXPECT_EQ("400", return_code);
- }
-
- app.stop();
-}
-// Test class that allows login for a fixed password.
-class KnownLoginAuthenticator {
- public:
- inline bool authenticate(const std::string& username,
- const std::string& password) {
- return (username == "dude") && (password == "foo");
- }
-};
+ // Test blank login credentials
+ sendmsg = "POST /login\r\nContent-Length:0\r\n\r\n\r\n";
+ {
+ send_to_localhost(sendmsg);
+ auto return_code = std::string(&buf[9], &buf[12]);
+ EXPECT_EQ("400", return_code);
+ }
-TEST(TokenAuthentication, TestSuccessfulLogin) {
- App<crow::persistent_data::Middleware, crow::token_authorization::Middleware>
- app;
- app.bindaddr("127.0.0.1").port(45451);
- BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
- auto _ = async(std::launch::async, [&] { app.run(); });
+ // Test wrong login credentials
+ sendmsg = "POST /login\r\nContent-Length:38\r\n\r\n{\"username\": \"foo\", "
+ "\"password\": \"bar\"}\r\n";
+ {
+ send_to_localhost(sendmsg);
+ auto return_code = std::string(&buf[9], &buf[12]);
+ EXPECT_EQ("401", return_code);
+ // TODO(ed) need to test more here. Response string?
+ }
- asio::io_service is;
- std::array<char, 2048> buf;
- std::string sendmsg;
+ // Test only sending a username
+ sendmsg =
+ "POST /login\r\nContent-Length:19\r\n\r\n{\"username\": \"foo\"}\r\n";
+ {
+ send_to_localhost(sendmsg);
+ auto return_code = std::string(&buf[9], &buf[12]);
+ EXPECT_EQ("400", return_code);
+ }
- auto send_to_localhost = [&is, &buf](std::string sendmsg) {
- 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();
- };
+ // Test only sending a password
+ sendmsg =
+ "POST /login\r\nContent-Length:19\r\n\r\n{\"password\": \"foo\"}\r\n";
+ {
+ send_to_localhost(sendmsg);
+ auto return_code = std::string(&buf[9], &buf[12]);
+ EXPECT_EQ("400", return_code);
+ }
- {
- // Retry a couple of times waiting for the server to come up
- asio::ip::tcp::socket c(is);
- for (int i = 0; i < 200; i++) {
- try {
+ app.stop();
+}
+
+// Test class that allows login for a fixed password.
+class KnownLoginAuthenticator
+{
+ public:
+ inline bool authenticate(const std::string& username,
+ const std::string& password)
+ {
+ return (username == "dude") && (password == "foo");
+ }
+};
+
+TEST(TokenAuthentication, TestSuccessfulLogin)
+{
+ App<crow::persistent_data::Middleware,
+ crow::token_authorization::Middleware>
+ app;
+ app.bindaddr("127.0.0.1").port(45451);
+ BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; });
+ auto _ = async(std::launch::async, [&] { app.run(); });
+
+ asio::io_service is;
+ std::array<char, 2048> buf;
+ std::string sendmsg;
+
+ auto send_to_localhost = [&is, &buf](std::string sendmsg) {
+ 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();
- break;
- } catch (std::exception e) {
- // do nothing. We expect this to fail while the server is starting up
- }
+ };
+
+ {
+ // Retry a couple of times waiting for the server to come up
+ 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 (std::exception e)
+ {
+ // do nothing. We expect this to fail while the server is
+ // starting up
+ }
+ }
}
- }
-
- // Test correct login credentials
- sendmsg =
- "POST /login\r\nContent-Length:40\r\n\r\n{\"username\": \"dude\", "
- "\"password\": \"foo\"}\r\n";
- {
- send_to_localhost(sendmsg);
- std::string response(std::begin(buf), std::end(buf));
- // This is a routine to split strings until a newline is hit
- // TODO(ed) this should really use the HTTP parser
- std::vector<std::string> headers;
- std::string::size_type pos = 0;
- std::string::size_type prev = 0;
- int content_length = 0;
- std::string content_encoding("");
- while ((pos = response.find("\r\n", prev)) != std::string::npos) {
- auto this_string = response.substr(prev, pos - prev);
- if (this_string == "") {
- prev = pos + 2;
- break;
- }
-
- headers.push_back(this_string);
- prev = pos + 2;
+
+ // Test correct login credentials
+ sendmsg =
+ "POST /login\r\nContent-Length:40\r\n\r\n{\"username\": \"dude\", "
+ "\"password\": \"foo\"}\r\n";
+ {
+ send_to_localhost(sendmsg);
+ std::string response(std::begin(buf), std::end(buf));
+ // This is a routine to split strings until a newline is hit
+ // TODO(ed) this should really use the HTTP parser
+ std::vector<std::string> headers;
+ std::string::size_type pos = 0;
+ std::string::size_type prev = 0;
+ int content_length = 0;
+ std::string content_encoding("");
+ while ((pos = response.find("\r\n", prev)) != std::string::npos)
+ {
+ auto this_string = response.substr(prev, pos - prev);
+ if (this_string == "")
+ {
+ prev = pos + 2;
+ break;
+ }
+
+ headers.push_back(this_string);
+ prev = pos + 2;
+ }
+ EXPECT_EQ(headers[0], "HTTP/1.1 200 OK");
+ EXPECT_THAT(headers,
+ testing::Contains("Content-Type: application/json"));
+ auto http_content = response.substr(prev);
}
- EXPECT_EQ(headers[0], "HTTP/1.1 200 OK");
- EXPECT_THAT(headers, testing::Contains("Content-Type: application/json"));
- auto http_content = response.substr(prev);
- }
-
- // Try to use those login credentials to access a resource
- sendmsg =
- "GET /\r\nAuthorization: token\r\n\r\n{\"username\": \"dude\", "
- "\"password\": \"dude\"}\r\n";
- {
- send_to_localhost(sendmsg);
- auto return_code = std::string(&buf[9], &buf[12]);
- EXPECT_EQ("200", return_code);
- }
-
- app.stop();
+
+ // Try to use those login credentials to access a resource
+ sendmsg = "GET /\r\nAuthorization: token\r\n\r\n{\"username\": \"dude\", "
+ "\"password\": \"dude\"}\r\n";
+ {
+ send_to_localhost(sendmsg);
+ auto return_code = std::string(&buf[9], &buf[12]);
+ EXPECT_EQ("200", return_code);
+ }
+
+ app.stop();
} \ No newline at end of file