Skip to content
This repository has been archived by the owner on Mar 3, 2020. It is now read-only.

Commit

Permalink
Fixing broken unit tests to incorporte changes to raft due to additio…
Browse files Browse the repository at this point in the history
…n of the security flag
  • Loading branch information
rnistuk committed Sep 3, 2018
1 parent c6841b2 commit 09b690d
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 41 deletions.
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ find_package(

if(Boost_FOUND)
message(STATUS "Boost: ${Boost_INCLUDE_DIRS}")

message(STATUS "***boost root ${BOOST_ROOT}")
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
endif()

Expand Down
2 changes: 1 addition & 1 deletion bootstrap/bootstrap_peers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ bootstrap_peers::initialize_peer_list(const Json::Value& root, bzn::peers_list_t

if (this->is_security_enabled())
{
// At this point we cannot validate uuid's as we do not have
// At this point we cannot validate uuids as we do not have
// signatures for all of them, so we simply ignore blacklisted
// uuids
if(bzn::utils::blacklist::is_blacklisted(uuid))
Expand Down
2 changes: 2 additions & 0 deletions mocks/mock_raft_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ namespace bzn
bool(const bzn::message& msg, const bzn::log_entry_type entry_type));
MOCK_METHOD1(register_commit_handler,
void(bzn::raft_base::commit_handler handler));
MOCK_METHOD0(get_security_enabled,
bool());
};

} // namespace bzn
63 changes: 40 additions & 23 deletions raft/raft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ raft::raft(
const bzn::peers_list_t& peers,
bzn::uuid_t uuid,
const std::string state_dir, size_t maximum_raft_storage,
bool whitelist_enabled
bool security_enabled
)
:timer(io_context->make_unique_steady_timer())
,uuid(std::move(uuid))
,node(std::move(node))
,state_dir(std::move(state_dir))
,whitelist_enabled(whitelist_enabled)
,security_enabled(security_enabled)
{
// we must have a list of peers!
if (peers.empty())
Expand Down Expand Up @@ -424,6 +424,34 @@ raft::send_session_error_message(std::shared_ptr<bzn::session_base> session, con
}


bool
raft::validate_new_peer(std::shared_ptr<bzn::session_base> session, const bzn::message &peer)
{
// uuid's are signed as text files, so we must append the end of line character
const auto uuid{this->get_uuid() + "\x0a"};
if (!peer.isMember("signature") || peer["signature"].asString().empty())
{
this->send_session_error_message(session, ERROR_INVALID_SIGNATURE);
return false;
}

const auto signature{peer["signature"].asString()};
if(!bzn::utils::crypto::verify_signature(bzn::utils::crypto::retrieve_bluzelle_public_key_from_contract(), signature, uuid))
{
this->send_session_error_message(session, ERROR_UNABLE_TO_VALIDATE_UUID);
return false;
}

if (utils::blacklist::is_blacklisted(this->get_uuid()))
{
this->send_session_error_message(session, ERROR_PEER_HAS_BEEN_BLACKLISTED);
return false;
}
return true;

}


void
raft::handle_add_peer(std::shared_ptr<bzn::session_base> session, const bzn::message &peer)
{
Expand Down Expand Up @@ -459,33 +487,22 @@ raft::handle_add_peer(std::shared_ptr<bzn::session_base> session, const bzn::mes
return;
}

if (this->whitelist_enabled)
if (this->security_enabled && !this->validate_new_peer(session, peer))
{
// uuid's are signed as text files, so we must append the end of line character
const auto uuid{this->get_uuid() + "\x0a"};
if (!peer.isMember("signature") || peer["signature"].asString().empty())
{
this->send_session_error_message(session, ERROR_INVALID_SIGNATURE);
return;
}

const auto signature{peer["signature"].asString()};
if(!bzn::utils::crypto::verify_signature(bzn::utils::crypto::retrieve_bluzelle_public_key_from_contract(), signature, uuid))
{
this->send_session_error_message(session, ERROR_UNABLE_TO_VALIDATE_UUID);
return;
}

if (utils::blacklist::is_blacklisted(this->get_uuid()))
{
this->send_session_error_message(session, ERROR_PEER_HAS_BEEN_BLACKLISTED);
return;
}
return;
}

this->peer_match_index[peer["uuid"].asString()] = 1;
this->append_log_unsafe(this->create_joint_quorum_by_adding_peer(last_quorum_entry.msg, peer),
bzn::log_entry_type::joint_quorum);

bzn::message msg;
msg["bzn-api"] = "raft";
msg["cmd"] = "add_peer";
msg["response"] = bzn::message();
msg["response"]["from"] = this->get_uuid();
msg["response"]["msg"] = SUCCESS_PEER_ADDED_TO_SWARM;
session->send_message(std::make_shared<bzn::message>(msg), true);
return;
}

Expand Down
11 changes: 8 additions & 3 deletions raft/raft.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace
const std::string ERROR_PEER_HAS_BEEN_BLACKLISTED = "ERROR_PEER_HAS_BEEN_BLACKLISTED";
const std::string ERROR_INVALID_SIGNATURE = "ERROR_INVALID_SIGNATURE";
const std::string ERROR_UNABLE_TO_VALIDATE_UUID ="ERROR_UNABLE_TO_VALIDATE_UUID";
const std::string SUCCESS_PEER_ADDED_TO_SWARM = "SUCCESS_PEER_ADDED_TO_SWARM";
}


Expand All @@ -56,8 +57,8 @@ namespace bzn
const bzn::peers_list_t& peers,
bzn::uuid_t uuid,
const std::string state_dir,
size_t maximum_raft_storage = bzn::raft_log::DEFAULT_MAX_STORAGE_SIZE,
bool whitelist_enabled = false);
size_t maximum_raft_storage = bzn::DEFAULT_MAX_STORAGE_SIZE,
bool security_enabled = false);

bzn::raft_state get_state() override;

Expand All @@ -77,6 +78,8 @@ namespace bzn

bzn::message get_status() override;

bool get_security_enabled() override { return this->security_enabled; };

private:
friend class raft_log_base;
friend class raft_log;
Expand Down Expand Up @@ -160,6 +163,8 @@ namespace bzn

void send_session_error_message(std::shared_ptr<bzn::session_base> session, const std::string& error_message);

bool validate_new_peer(std::shared_ptr<bzn::session_base> session, const bzn::message &peer);

// raft state...
bzn::raft_state current_state = raft_state::follower;
uint32_t current_term = 0;
Expand Down Expand Up @@ -197,6 +202,6 @@ namespace bzn

bool enable_audit = true;

bool whitelist_enabled{false}; // TODO: RHN - this is only temporary, until whitelist is tested and in use.
bool security_enabled{false}; // TODO: RHN - this is only temporary, until the security functionality is tested and in use.
};
} // bzn
10 changes: 10 additions & 0 deletions raft/raft_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,16 @@ namespace bzn
*/
virtual void register_commit_handler(bzn::raft_base::commit_handler handler) = 0;


/**
* Returns the state of ht esecurity enabled flag. True if a peer added to the swarm via
* the add_peer ws command will be validated against the Bluzelle Private Key and node
* blacklist.
*
* @return boolean, state of security validation
*/
virtual bool get_security_enabled() = 0;

};


Expand Down
8 changes: 4 additions & 4 deletions raft/raft_log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@
#include <fstream>


namespace bzn
{
namespace bzn {

const std::string MSG_ERROR_EMPTY_LOG_ENTRY_FILE{"Empty log entry file. Please delete .state folder."};
const std::string MSG_NO_PEERS_IN_LOG{"Unable to find peers in log entries."};
const std::string MSG_TRYING_TO_INSERT_INVALID_ENTRY{"Trying to insert an invalid log entry."};
const std::string MSG_UNABLE_TO_CREATE_LOG_PATH_NAMED{"Unable to create log path: "};
const std::string MSG_EXITING_DUE_TO_LOG_PATH_CREATION_FAILURE{"MSG_EXITING_DUE_TO_LOG_PATH_CREATION_FAILURE"};
const std::string MSG_ERROR_MAXIMUM_STORAGE_EXCEEDED{"Maximum storage has been exceeded, please update the options file."};
const size_t DEFAULT_MAX_STORAGE_SIZE{2147483648};

class raft_log
{
public:
// The default maximum allowed storage for a node is 2G
static const size_t DEFAULT_MAX_STORAGE_SIZE = 2147483648;
//const size_t DEFAULT_MAX_STORAGE_SIZE = 2147483648;

raft_log(const std::string& log_path, const size_t max_storage = bzn::raft_log::DEFAULT_MAX_STORAGE_SIZE);
raft_log(const std::string& log_path, const size_t max_storage = bzn::DEFAULT_MAX_STORAGE_SIZE);

const bzn::log_entry& entry_at(size_t i) const;
const bzn::log_entry& last_quorum_entry() const;
Expand Down
55 changes: 49 additions & 6 deletions raft/test/raft_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ namespace bzn
}

std::shared_ptr<bzn::raft>
start_raft(const bzn::peers_list_t& peer_list, bzn::asio::wait_handler& asio_wait_handler, bzn::message_handler bzn_msg_handler)
start_raft(const bzn::peers_list_t& peer_list, bzn::asio::wait_handler& asio_wait_handler, bzn::message_handler bzn_msg_handler, bool security_enabled = false)
{
auto mock_steady_timer = std::make_unique<NiceMock<bzn::asio::Mocksteady_timer_base>>();

Expand All @@ -321,7 +321,9 @@ namespace bzn
, this->mock_node
, peer_list
, TEST_NODE_UUID
, TEST_STATE_DIR);
, TEST_STATE_DIR
, bzn::DEFAULT_MAX_STORAGE_SIZE
, security_enabled);

//bzn::message_handler mh;
EXPECT_CALL(*mock_node, register_for_message("raft", _)).WillOnce(Invoke(
Expand Down Expand Up @@ -1193,7 +1195,6 @@ namespace bzn
}



TEST_F(raft_test, test_that_bad_add_or_remove_peer_requests_fail)
{
auto mock_steady_timer = std::make_unique<NiceMock<bzn::asio::Mocksteady_timer_base>>();
Expand Down Expand Up @@ -1563,12 +1564,22 @@ namespace bzn
auto raft = bzn::raft(std::make_shared<NiceMock<bzn::asio::Mockio_context_base>>(), nullptr, TEST_PEER_LIST, TEST_NODE_UUID, TEST_STATE_DIR);
auto peers = raft.get_all_peers();

auto mock_session = std::make_shared<bzn::Mocksession_base>();

EXPECT_EQ(TEST_PEER_LIST.size(), peers.size());
EXPECT_EQ(TEST_PEER_LIST,peers);

EXPECT_CALL(*mock_session, send_message(An<std::shared_ptr<bzn::message>>(),_))
.WillOnce(Invoke(
[&](const auto& msg, auto)
{
auto root = *msg.get();
EXPECT_EQ(root["response"]["msg"].asString(), SUCCESS_PEER_ADDED_TO_SWARM);
}));

// replace the last quorum with a joint quorum
raft.current_state = bzn::raft_state::leader;
raft.handle_ws_raft_messages(make_add_peer_request(), nullptr);
raft.handle_ws_raft_messages(make_add_peer_request(), mock_session);

const auto& active = raft.get_active_quorum();
EXPECT_EQ(active.size(), size_t(2));
Expand Down Expand Up @@ -1609,6 +1620,17 @@ namespace bzn
clean_state_folder();
auto raft = bzn::raft(std::make_shared<NiceMock<bzn::asio::Mockio_context_base>>(), nullptr, TEST_PEER_LIST, TEST_NODE_UUID, TEST_STATE_DIR);

auto mock_session = std::make_shared<bzn::Mocksession_base>();

EXPECT_CALL(*mock_session, send_message(An<std::shared_ptr<bzn::message>>(),_))
.WillOnce(Invoke(
[&](const auto& msg, auto)
{
auto root = *msg.get();
EXPECT_EQ(root["response"]["msg"].asString(), SUCCESS_PEER_ADDED_TO_SWARM);
}));


EXPECT_EQ(bzn::log_entry_type::single_quorum, raft.raft_log->last_quorum_entry().entry_type);

auto active_list = raft.get_active_quorum();
Expand Down Expand Up @@ -1636,7 +1658,7 @@ namespace bzn
// replace the last quorum with a joint quorum
bzn::message add_peer = make_add_peer_request();
raft.current_state = bzn::raft_state::leader;
raft.handle_ws_raft_messages(add_peer, nullptr);
raft.handle_ws_raft_messages(add_peer, mock_session);

active_list = raft.get_active_quorum();
EXPECT_EQ(active_list.size(), size_t(2));
Expand Down Expand Up @@ -1666,6 +1688,17 @@ namespace bzn
clean_state_folder();
auto raft = bzn::raft(std::make_shared<NiceMock<bzn::asio::Mockio_context_base>>(), nullptr, TEST_PEER_LIST, TEST_NODE_UUID, TEST_STATE_DIR);

auto mock_session = std::make_shared<bzn::Mocksession_base>();

EXPECT_CALL(*mock_session, send_message(An<std::shared_ptr<bzn::message>>(),_))
.WillOnce(Invoke(
[&](const auto& msg, auto)
{
auto root = *msg.get();
EXPECT_EQ(root["response"]["msg"].asString(), SUCCESS_PEER_ADDED_TO_SWARM);
}));


EXPECT_EQ(bzn::log_entry_type::single_quorum, raft.raft_log->last_quorum_entry().entry_type);

std::set<bzn::uuid_t> yes_votes;
Expand All @@ -1682,7 +1715,7 @@ namespace bzn
EXPECT_TRUE(raft.is_majority(yes_votes));

raft.current_state = bzn::raft_state::leader;
raft.handle_ws_raft_messages(make_add_peer_request(), nullptr);
raft.handle_ws_raft_messages(make_add_peer_request(), mock_session);

yes_votes.clear();
yes_votes.emplace(new_peer.uuid);
Expand Down Expand Up @@ -1838,4 +1871,14 @@ namespace bzn
EXPECT_EQ(raft->no_votes.size(),size_t(2));
EXPECT_EQ(raft->get_state(), bzn::raft_state::candidate);
}



TEST_F(raft_test, test_that_add_node_works_securely)
{


}


} // bzn
2 changes: 1 addition & 1 deletion utils/crypto.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace bzn::utils::crypto
* @param in/out vector of unsigned chars that will contain the decoded data
* @return integer value of 0 on success
*/
int base64_decode( const std::string& base64_message, std::vector<unsigned char>& decoded_message);
int base64_decode(const std::string& base64_message, std::vector<unsigned char>& decoded_message);


/**
Expand Down
2 changes: 1 addition & 1 deletion utils/test/utils_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace

// NOTE - not constant as the test shuffles the list before use to get five
// random uuids.
std::vector<std::string> blacklisted_uuids = {
std::vector<std::string> blacklisted_uuids {
"9dc2f619-2e77-49f7-9b20-5b55fd87ea44",
"51bfd541-ab3e-4f02-93c7-8c3328daccfa",
"f06ab617-7ccc-45fe-aee2-d4f5d175891b",
Expand Down

0 comments on commit 09b690d

Please sign in to comment.