diff --git a/include/auth_manager.h b/include/auth_manager.h index d32872e7..6f7ef394 100644 --- a/include/auth_manager.h +++ b/include/auth_manager.h @@ -85,6 +85,8 @@ private: std::map api_keys; // stores key_value => key mapping Store *store; + std::string bootstrap_auth_key; + // Auto incrementing API KEY ID std::atomic next_api_key_id; @@ -112,7 +114,7 @@ public: AuthManager() = default; - Option init(Store *store); + Option init(Store* store, const std::string& bootstrap_auth_key); Option> list_keys() const; diff --git a/src/auth_manager.cpp b/src/auth_manager.cpp index 28017b3f..482ba50a 100644 --- a/src/auth_manager.cpp +++ b/src/auth_manager.cpp @@ -5,12 +5,13 @@ constexpr const char* AuthManager::DOCUMENTS_SEARCH_ACTION; constexpr const uint64_t api_key_t::FAR_FUTURE_TIMESTAMP; -Option AuthManager::init(Store *store) { +Option AuthManager::init(Store* store, const std::string& bootstrap_auth_key) { // This function must be idempotent, i.e. when called multiple times, must produce the same state without leaks //LOG(INFO) << "AuthManager::init()"; std::unique_lock lock(mutex); this->store = store; + this->bootstrap_auth_key = bootstrap_auth_key; std::string next_api_key_id_str; StoreStatus next_api_key_id_status = store->get(API_KEY_NEXT_ID_KEY, next_api_key_id_str); @@ -95,7 +96,7 @@ Option AuthManager::create_key(api_key_t& api_key) { //LOG(INFO) << "AuthManager::create_key()"; std::unique_lock lock(mutex); - if(api_keys.count(api_key.value) != 0) { + if(api_keys.count(api_key.value) != 0 || api_key.value == bootstrap_auth_key) { return Option(409, "API key generation conflict."); } diff --git a/src/collection_manager.cpp b/src/collection_manager.cpp index c504cd72..217c46a6 100644 --- a/src/collection_manager.cpp +++ b/src/collection_manager.cpp @@ -103,7 +103,7 @@ Option CollectionManager::load(const size_t collection_batch_size, const s // This function must be idempotent, i.e. when called multiple times, must produce the same state without leaks LOG(INFO) << "CollectionManager::load()"; - Option auth_init_op = auth_manager.init(store); + Option auth_init_op = auth_manager.init(store, bootstrap_auth_key); if(!auth_init_op.ok()) { LOG(ERROR) << "Auth manager init failed, error=" << auth_init_op.error(); } diff --git a/test/auth_manager_test.cpp b/test/auth_manager_test.cpp index 7be5147c..7fc033f7 100644 --- a/test/auth_manager_test.cpp +++ b/test/auth_manager_test.cpp @@ -17,7 +17,7 @@ protected: system(("rm -rf "+state_dir_path+" && mkdir -p "+state_dir_path).c_str()); store = new Store(state_dir_path); - auth_manager.init(store); + auth_manager.init(store, "bootstrap-key"); } virtual void SetUp() { @@ -54,6 +54,18 @@ TEST_F(AuthManagerTest, CreateListDeleteAPIKeys) { ASSERT_TRUE(insert_op.ok()); ASSERT_EQ(5, insert_op.get().value.size()); + // reject on conflict + insert_op = auth_manager.create_key(api_key2); + ASSERT_FALSE(insert_op.ok()); + ASSERT_EQ(409, insert_op.code()); + ASSERT_EQ("API key generation conflict.", insert_op.error()); + + api_key2.value = "bootstrap-key"; + insert_op = auth_manager.create_key(api_key2); + ASSERT_FALSE(insert_op.ok()); + ASSERT_EQ(409, insert_op.code()); + ASSERT_EQ("API key generation conflict.", insert_op.error()); + // get an individual key get_op = auth_manager.get_key(0); @@ -106,7 +118,7 @@ TEST_F(AuthManagerTest, CheckRestoreOfAPIKeys) { std::string key_value2 = auth_manager.create_key(api_key2).get().value; AuthManager auth_manager2; - auth_manager2.init(store); + auth_manager2.init(store, "bootstrap-key"); // list keys