Skip to content

Commit

Permalink
Add support to Hashicorp Vault Secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
ssantos21 committed Dec 4, 2024
1 parent 9e4ba57 commit b3a687a
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 8 deletions.
1 change: 1 addition & 0 deletions lockbox/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ add_library(LockboxLibrary
src/server.cpp
src/utils.cpp
src/key_manager.cpp
src/hashicorp_key_manager.cpp
src/enclave.cpp
src/monocypher.c
src/db_manager.cpp)
Expand Down
2 changes: 1 addition & 1 deletion lockbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ $ cmake --preset=vcpkg ..
$ cmake --build .
```

4. Then, to run the server: `./MercuryLockbox`
4. Then, to run the server: `./MercuryLockbox --key_provider=google_kms` or `./MercuryLockbox --key_provider=hashicorp`.
9 changes: 8 additions & 1 deletion lockbox/Settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ location_id = "global"
key_name = "encrypted-key"
[kms]
ring = "enclave"
crypto_key = "sealing"
crypto_key = "sealing"
[hashicorp]
hcp_client_id = ""
hcp_client_secret = ""
organization_id = ""
project_id = ""
app_name = ""
secret_name = ""
11 changes: 11 additions & 0 deletions lockbox/include/hashicorp_key_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef HASHICORP_KEY_MANAGER_H
#define HASHICORP_KEY_MANAGER_H

#include <string>
#include <vector>

namespace hashicorp_key_manager {
std::vector<uint8_t> get_seed();
} // namespace key_manager

#endif // HASHICORP_KEY_MANAGER_H
4 changes: 3 additions & 1 deletion lockbox/include/server.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#ifndef SERVER_H
#define SERVER_H

#include <string>

namespace lockbox {
void start_server();
void start_server(const std::string& key_provider);
} // namespace lockbox

#endif // SERVER_H
98 changes: 98 additions & 0 deletions lockbox/src/hashicorp_key_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "hashicorp_key_manager.h"

#include <crow.h>
#include <cpr/cpr.h>
#include <iostream>
#include "utils.h"
#include <toml++/toml.h>

namespace hashicorp_key_manager {

std::string get_access_token() {

auto config = toml::parse_file("Settings.toml");

const std::string client_id = config["hashicorp"]["hcp_client_id"].as_string()->get();
const std::string client_secret = config["hashicorp"]["hcp_client_secret"].as_string()->get();

// Make the HTTP POST request using cpr
cpr::Response response = cpr::Post(
cpr::Url{"https://auth.idp.hashicorp.com/oauth2/token"},
cpr::Header{{"Content-Type", "application/x-www-form-urlencoded"}},
cpr::Payload{
{"client_id", client_id},
{"client_secret", client_secret},
{"grant_type", "client_credentials"},
{"audience", "https://api.hashicorp.cloud"}}
);

// Check for HTTP request success
if (response.status_code != 200) {
throw std::runtime_error("HTTP request failed with status code: " +
std::to_string(response.status_code) + "\nResponse: " + response.text);
}

// Parse the JSON response using CrowCPP
crow::json::rvalue json = crow::json::load(response.text);
if (!json) {
throw std::runtime_error("Failed to parse JSON response: " + response.text);
}

// Extract the access token
if (!json.has("access_token")) {
throw std::runtime_error("Response JSON does not contain 'access_token'. Response: " + response.text);
}

auto access_token = json["access_token"].s();

return access_token;
}

std::string get_secret(const std::string& hcp_api_token) {

auto config = toml::parse_file("Settings.toml");

const std::string organization_id = config["hashicorp"]["organization_id"].as_string()->get();
const std::string project_id = config["hashicorp"]["project_id"].as_string()->get();
const std::string app_name = config["hashicorp"]["app_name"].as_string()->get();
const std::string secret_name = config["hashicorp"]["secret_name"].as_string()->get();

// Construct the URL
std::string url = "https://api.cloud.hashicorp.com/secrets/2023-11-28/organizations/" + organization_id +
"/projects/" + project_id +
"/apps/" + app_name +
"/secrets/" + secret_name + ":open";

// Make the HTTP GET request using CPR
cpr::Response response = cpr::Get(
cpr::Url{url},
cpr::Header{{"Authorization", "Bearer " + hcp_api_token}}
);

// Check for HTTP request success
if (response.status_code != 200) {
throw std::runtime_error("HTTP request failed with status code: " +
std::to_string(response.status_code) + "\nResponse: " + response.text);
}

// Parse the JSON response using CrowCPP
crow::json::rvalue json = crow::json::load(response.text);
if (!json) {
throw std::runtime_error("Failed to parse JSON response: " + response.text);
}

return json["secret"]["static_version"]["value"].s();
}

std::vector<uint8_t> get_seed() {

auto access_token = get_access_token();

auto secret = get_secret(access_token);

std::vector<unsigned char> serialized_secret = utils::ParseHex(secret);

return serialized_secret;
}

}
14 changes: 12 additions & 2 deletions lockbox/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ int main(int argc, char *argv[]) {
CLI::App cli_app{"Lockbox Server"};
cli_app.set_version_flag("--version", std::string("0.0.1"));

CLI11_PARSE(cli_app, argc, argv);
// Add the mandatory key_provider option
std::string key_provider;
cli_app.add_option("--key_provider", key_provider, "Key provider (google_kms or hashicorp)")
->required() // Mark it as mandatory
->check(CLI::IsMember({"google_kms", "hashicorp"})); // Validate allowed values

lockbox::start_server();
try {
CLI11_PARSE(cli_app, argc, argv);
} catch (const CLI::ParseError &e) {
return cli_app.exit(e); // Exit gracefully on parse errors
}

lockbox::start_server(key_provider);

return 0;
}
17 changes: 14 additions & 3 deletions lockbox/src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "utils.h"
#include "enclave.h"
#include "key_manager.h"
#include "hashicorp_key_manager.h"
#include "db_manager.h"

namespace lockbox {
Expand Down Expand Up @@ -182,11 +183,21 @@ namespace lockbox {
return crow::response{result};
}

void start_server() {
void start_server(const std::string& key_provider) {

std::vector<uint8_t> seed = key_manager::get_seed();
std::vector<uint8_t> seed;

std::string seed_hex = utils::key_to_string(seed.data(), seed.size());
if (key_provider == "google_kms") {
seed = key_manager::get_seed();
} else if (key_provider == "hashicorp") {
seed = hashicorp_key_manager::get_seed();
} else {
throw std::runtime_error("Invalid key provider: " + key_provider);
}

/* std::string seed_hex = utils::key_to_string(seed.data(), seed.size());
std::cout << "Seed: " << seed_hex << std::endl; */

// Initialize Crow HTTP server
crow::SimpleApp app;
Expand Down

0 comments on commit b3a687a

Please sign in to comment.