Skip to content

Commit

Permalink
Add hashicorp container key manager
Browse files Browse the repository at this point in the history
  • Loading branch information
ssantos21 committed Dec 24, 2024
1 parent 00b6dcd commit f7beb24
Show file tree
Hide file tree
Showing 15 changed files with 205 additions and 67 deletions.
58 changes: 56 additions & 2 deletions docker-compose-lockbox.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,49 @@
# This docker-compose file is an example of how to start the lockbox service and its dependencies.
# First, you start the vault service, if you use it. The command is:
# docker compose -f docker-compose-lockbox.yml --profile hashicorp-container up --build
# Then, you start the Lockbox and Mercury server services. The command is:
# docker compose -f docker-compose-lockbox.yml --profile mercury up --build
# The Mercury service will start the Lockbox service and the Mercury server. The Lockbox service will connect to the vault service to get the seed value.

# If you are not going to use the vault service, you do not need to run the first command.
# Change the environment variables to match your configuration.
services:

vault:
profiles:
- hashicorp-container
image: hashicorp/vault
environment:
- VAULT_DEV_ROOT_TOKEN_ID=2bbz80mr1zm0tfrjwxyq7f48ofgky848
ports:
- "8200:8200"

vault-init:
profiles:
- hashicorp-container
image: curlimages/curl
depends_on:
- vault
command: >
sh -c '
sleep 10 &&
curl --header "X-Vault-Token: 2bbz80mr1zm0tfrjwxyq7f48ofgky848" \
--header "Content-Type: application/json" \
--request POST \
--data '"'"'{"data": {"seed": "8b10a037120cf37441bd7623da2aa488c21889017ffb4f4d303b9dbcbada5bee"}}'"'"' \
http://vault:8200/v1/secret/data/mercury-seed &&
touch /tmp/healthy &&
tail -f /dev/null
'
healthcheck:
test: ["CMD-SHELL", "test -f /tmp/healthy"]
interval: 1s
timeout: 1s
retries: 30

lockbox:
profiles:
- mercury
build:
context: lockbox
dockerfile: ./Dockerfile
Expand All @@ -9,17 +52,24 @@ services:
environment:
- LOCKBOX_DATABASE_URL=postgres://postgres:postgres@db_lockbox:5432/enclave
- LOCKBOX_PORT=18080
- KEY_MANAGER=filesystem
- SEED_FILEPATH=./seed
- KEY_MANAGER=hashicorp_container
- HASHICORP_CONTAINER_TOKEN=2bbz80mr1zm0tfrjwxyq7f48ofgky848
- HASHICORP_CONTAINER_URL=http://vault:8200
- HASHICORP_CONTAINER_PATH=mercury-seed
- HASHICORP_CONTAINER_MOUNT_POINT=secret
- HASHICORP_CONTAINER_KEY_NAME=seed
ports:
- "18080:18080"

mercury-server:
profiles:
- mercury
build:
context: .
dockerfile: server/Dockerfile
depends_on:
- db_server
- lockbox
environment:
BITCOIN_NETWORK: regtest
LOCKHEIGHT_INIT: 1000
Expand Down Expand Up @@ -47,6 +97,8 @@ services:
- "8000:8000"

db_lockbox:
profiles:
- mercury
image: postgres:16.2
environment:
POSTGRES_PASSWORD: postgres
Expand All @@ -57,6 +109,8 @@ services:
- postgres_lockbox_data:/var/lib/postgresql/data

db_server:
profiles:
- mercury
image: postgres:16.2
environment:
POSTGRES_PASSWORD: postgres
Expand Down
20 changes: 13 additions & 7 deletions lockbox/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# general settings
# KEY_MANAGER can be one of: google_kms, hashicorp or filesystem
# KEY_MANAGER can be one of: google_kms, hashicorp_api, hashicorp_container or filesystem
LOCKBOX_DATABASE_URL=postgresql://postgres:postgres@localhost/enclave
LOCKBOX_PORT=18080
KEY_MANAGER=filesystem
Expand All @@ -16,9 +16,15 @@ GCLOUD_KMS_RING=enclave
GCLOUD_CRYPTO_KEY=sealing

# hashicorp settings
# HASHICORP_HCP_CLIENT_ID=
# HASHICORP_HCP_CLIENT_SECRET=
# HASHICORP_ORGANIZATION_ID=
# HASHICORP_PROJECT_ID=
# HASHICORP_APP_NAME=
# HASHICORP_SECRET_NAME=
# HASHICORP_API_HCP_CLIENT_ID=
# HASHICORP_API_HCP_CLIENT_SECRET=
# HASHICORP_API_ORGANIZATION_ID=
# HASHICORP_API_PROJECT_ID=
# HASHICORP_API_APP_NAME=
# HASHICORP_API_SECRET_NAME=

HASHICORP_CONTAINER_TOKEN=2bbz80mr1zm0tfrjwxyq7f48ofgky848
HASHICORP_CONTAINER_URL=http://127.0.0.1:8200
HASHICORP_CONTAINER_PATH=mercury-seed
HASHICORP_CONTAINER_MOUNT_POINT=secret
HASHICORP_CONTAINER_KEY_NAME=seed
3 changes: 2 additions & 1 deletion lockbox/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ add_library(LockboxLibrary
src/server.cpp
src/utils.cpp
src/google_key_manager.cpp
src/hashicorp_key_manager.cpp
src/hashicorp_api_key_manager.cpp
src/hashicorp_container_key_manager.cpp
src/filesystem_key_manager.cpp
src/enclave.cpp
src/monocypher.c
Expand Down
10 changes: 8 additions & 2 deletions lockbox/Settings.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[general]
database_connection_string = "postgresql://postgres:postgres@localhost/enclave"
server_port = 18080
key_manager = "filesystem" # "google_kms", "hashicorp", "filesystem"
key_manager = "filesystem" # "google_kms", "hashicorp_container, "hashicorp_api", "filesystem"
[filesystem]
seed_filepath = "./seed"
[gcloud]
Expand All @@ -13,10 +13,16 @@ key_name = "encrypted-key"
[kms]
ring = "enclave"
crypto_key = "sealing"
[hashicorp]
[hashicorp_api]
hcp_client_id = ""
hcp_client_secret = ""
organization_id = ""
project_id = ""
app_name = ""
secret_name = ""
[hashicorp_container]
token = "2bbz80mr1zm0tfrjwxyq7f48ofgky848"
url = "http://127.0.0.1:8200"
path = "mercury-seed"
mount_point = "secret"
key_name = "seed"
11 changes: 11 additions & 0 deletions lockbox/include/hashicorp_api_key_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef HASHICORP_API_KEY_MANAGER_H
#define HASHICORP_API_KEY_MANAGER_H

#include <string>
#include <vector>

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

#endif // HASHICORP_API_KEY_MANAGER_H
11 changes: 11 additions & 0 deletions lockbox/include/hashicorp_container_key_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef HASHICORP_CONTAINER_KEY_MANAGER_H
#define HASHICORP_CONTAINER_KEY_MANAGER_H

#include <string>
#include <vector>

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

#endif // HASHICORP_CONTAINER_KEY_MANAGER_H
11 changes: 0 additions & 11 deletions lockbox/include/hashicorp_key_manager.h

This file was deleted.

20 changes: 14 additions & 6 deletions lockbox/include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@ namespace utils {
static const config_var GCLOUD_KMS_RING = {"GCLOUD_KMS_RING", "kms", "ring"};
static const config_var GCLOUD_CRYPTO_KEY = {"GCLOUD_CRYPTO_KEY", "kms", "crypto_key"};

static const config_var HASHICORP_HCP_CLIENT_ID = {"HASHICORP_HCP_CLIENT_ID", "hashicorp", "hcp_client_id"};
static const config_var HASHICORP_HCP_CLIENT_SECRET = {"HASHICORP_HCP_CLIENT_SECRET", "hashicorp", "hcp_client_secret"};
static const config_var HASHICORP_ORGANIZATION_ID = {"HASHICORP_ORGANIZATION_ID", "hashicorp", "organization_id"};
static const config_var HASHICORP_PROJECT_ID = {"HASHICORP_PROJECT_ID", "hashicorp", "project_id"};
static const config_var HASHICORP_APP_NAME = {"HASHICORP_APP_NAME", "hashicorp", "app_name"};
static const config_var HASHICORP_SECRET_NAME = {"HASHICORP_SECRET_NAME", "hashicorp", "secret_name"};
static const config_var HASHICORP_API_HCP_CLIENT_ID = {"HASHICORP_API_HCP_CLIENT_ID", "hashicorp_api", "hcp_client_id"};
static const config_var HASHICORP_API_HCP_CLIENT_SECRET = {"HASHICORP_API_HCP_CLIENT_SECRET", "hashicorp_api", "hcp_client_secret"};
static const config_var HASHICORP_API_ORGANIZATION_ID = {"HASHICORP_API_ORGANIZATION_ID", "hashicorp_api", "organization_id"};
static const config_var HASHICORP_API_PROJECT_ID = {"HASHICORP_API_PROJECT_ID", "hashicorp_api", "project_id"};
static const config_var HASHICORP_API_APP_NAME = {"HASHICORP_API_APP_NAME", "hashicorp_api", "app_name"};
static const config_var HASHICORP_API_SECRET_NAME = {"HASHICORP_API_SECRET_NAME", "hashicorp_api", "secret_name"};

static const config_var HASHICORP_CONTAINER_TOKEN = {"HASHICORP_CONTAINER_TOKEN", "hashicorp_container", "token"};
static const config_var HASHICORP_CONTAINER_URL = {"HASHICORP_CONTAINER_URL", "hashicorp_container", "url"};
static const config_var HASHICORP_CONTAINER_PATH = {"HASHICORP_CONTAINER_PATH", "hashicorp_container", "path"};
static const config_var HASHICORP_CONTAINER_MOUNT_POINT = {"HASHICORP_CONTAINER_MOUNT_POINT", "hashicorp_container", "mount_point"};
static const config_var HASHICORP_CONTAINER_KEY_NAME = {"HASHICORP_CONTAINER_KEY_NAME", "hashicorp_container", "key_name"};

struct chacha20_poly1305_encrypted_data {
size_t data_len;
Expand All @@ -57,6 +63,8 @@ namespace utils {

std::string getStringConfigVar(const std::string& env_var, const std::string& toml_var_1, const std::string& toml_var_2);

std::string getStringConfigVar(const config_var& config_variable);

} // namespace utils

#endif // UTILS_H
3 changes: 1 addition & 2 deletions lockbox/src/db_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
namespace db_manager {

std::string getDatabaseConnectionString() {
return utils::getStringConfigVar(
utils::DATABASE_URL.env_var, utils::DATABASE_URL.toml_var_1, utils::DATABASE_URL.toml_var_2);
return utils::getStringConfigVar(utils::DATABASE_URL);
}

// Assumes the buffer is large enough. In a real application, ensure buffer safety.
Expand Down
5 changes: 2 additions & 3 deletions lockbox/src/filesystem_key_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "hashicorp_key_manager.h"
#include "filesystem_key_manager.h"

#include <vector>
#include <stdexcept>
Expand All @@ -11,8 +11,7 @@
namespace filesystem_key_manager {

std::string getSeedFilePath() {
return utils::getStringConfigVar(
utils::SEED_FILEPATH.env_var, utils::SEED_FILEPATH.toml_var_1, utils::SEED_FILEPATH.toml_var_2);
return utils::getStringConfigVar(utils::SEED_FILEPATH);
}

std::vector<uint8_t> get_seed() {
Expand Down
21 changes: 7 additions & 14 deletions lockbox/src/google_key_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ namespace key_manager {

std::string get_encrypted_secret() {

auto project_id = utils::getStringConfigVar(
utils::GCLOUD_PROJECT_ID.env_var, utils::GCLOUD_PROJECT_ID.toml_var_1, utils::GCLOUD_PROJECT_ID.toml_var_2);
auto project_id = utils::getStringConfigVar(utils::GCLOUD_PROJECT_ID);

auto project_number = utils::getStringConfigVar(
utils::GCLOUD_PROJECT_NUMBER.env_var, utils::GCLOUD_PROJECT_NUMBER.toml_var_1, utils::GCLOUD_PROJECT_NUMBER.toml_var_2);
auto project_number = utils::getStringConfigVar(utils::GCLOUD_PROJECT_NUMBER);

auto key_name = utils::getStringConfigVar(
utils::GCLOUD_SECRET_MANAGER_KEY_NAME.env_var, utils::GCLOUD_SECRET_MANAGER_KEY_NAME.toml_var_1, utils::GCLOUD_SECRET_MANAGER_KEY_NAME.toml_var_2);
auto key_name = utils::getStringConfigVar(utils::GCLOUD_SECRET_MANAGER_KEY_NAME);

auto version = 1;

Expand All @@ -37,17 +34,13 @@ namespace key_manager {

std::string decrypt_secret(std::string const& encrypted_secret) {

auto location_id = utils::getStringConfigVar(
utils::GCLOUD_LOCATION_ID.env_var, utils::GCLOUD_LOCATION_ID.toml_var_1, utils::GCLOUD_LOCATION_ID.toml_var_2);
auto location_id = utils::getStringConfigVar(utils::GCLOUD_LOCATION_ID);

auto project_id = utils::getStringConfigVar(
utils::GCLOUD_PROJECT_ID.env_var, utils::GCLOUD_PROJECT_ID.toml_var_1, utils::GCLOUD_PROJECT_ID.toml_var_2);
auto project_id = utils::getStringConfigVar(utils::GCLOUD_PROJECT_ID);

auto key_ring = utils::getStringConfigVar(
utils::GCLOUD_KMS_RING.env_var, utils::GCLOUD_KMS_RING.toml_var_1, utils::GCLOUD_KMS_RING.toml_var_2);
auto key_ring = utils::getStringConfigVar(utils::GCLOUD_KMS_RING);

auto crypto_key = utils::getStringConfigVar(
utils::GCLOUD_CRYPTO_KEY.env_var, utils::GCLOUD_CRYPTO_KEY.toml_var_1, utils::GCLOUD_CRYPTO_KEY.toml_var_2);
auto crypto_key = utils::getStringConfigVar(utils::GCLOUD_CRYPTO_KEY);

namespace kms = ::google::cloud::kms_v1;
auto client = kms::KeyManagementServiceClient(kms::MakeKeyManagementServiceConnection());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
#include "hashicorp_key_manager.h"
#include "hashicorp_api_key_manager.h"

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

namespace hashicorp_key_manager {
namespace hashicorp_api_key_manager {

std::string get_access_token() {

const std::string client_id = utils::getStringConfigVar(
utils::HASHICORP_HCP_CLIENT_ID.env_var, utils::HASHICORP_HCP_CLIENT_ID.toml_var_1, utils::HASHICORP_HCP_CLIENT_ID.toml_var_2);
const std::string client_id = utils::getStringConfigVar(utils::HASHICORP_API_HCP_CLIENT_ID);

const std::string client_secret = utils::getStringConfigVar(
utils::HASHICORP_HCP_CLIENT_SECRET.env_var, utils::HASHICORP_HCP_CLIENT_SECRET.toml_var_1, utils::HASHICORP_HCP_CLIENT_SECRET.toml_var_2);
const std::string client_secret = utils::getStringConfigVar(utils::HASHICORP_API_HCP_CLIENT_SECRET);

// Make the HTTP POST request using cpr
cpr::Response response = cpr::Post(
Expand Down Expand Up @@ -50,17 +48,13 @@ namespace hashicorp_key_manager {

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

const std::string organization_id = utils::getStringConfigVar(
utils::HASHICORP_ORGANIZATION_ID.env_var, utils::HASHICORP_ORGANIZATION_ID.toml_var_1, utils::HASHICORP_ORGANIZATION_ID.toml_var_2);
const std::string organization_id = utils::getStringConfigVar(utils::HASHICORP_API_ORGANIZATION_ID);

const std::string project_id = utils::getStringConfigVar(
utils::HASHICORP_PROJECT_ID.env_var, utils::HASHICORP_PROJECT_ID.toml_var_1, utils::HASHICORP_PROJECT_ID.toml_var_2);
const std::string project_id = utils::getStringConfigVar(utils::HASHICORP_API_PROJECT_ID);

const std::string app_name = utils::getStringConfigVar(
utils::HASHICORP_APP_NAME.env_var, utils::HASHICORP_APP_NAME.toml_var_1, utils::HASHICORP_APP_NAME.toml_var_2);
const std::string app_name = utils::getStringConfigVar(utils::HASHICORP_API_APP_NAME);

const std::string secret_name = utils::getStringConfigVar(
utils::HASHICORP_SECRET_NAME.env_var, utils::HASHICORP_SECRET_NAME.toml_var_1, utils::HASHICORP_SECRET_NAME.toml_var_2);
const std::string secret_name = utils::getStringConfigVar(utils::HASHICORP_API_SECRET_NAME);

// Construct the URL
std::string url = "https://api.cloud.hashicorp.com/secrets/2023-11-28/organizations/" + organization_id +
Expand Down
49 changes: 49 additions & 0 deletions lockbox/src/hashicorp_container_key_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "hashicorp_container_key_manager.h"

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

namespace hashicorp_container_key_manager {

std::string get_secret() {

const std::string token = utils::getStringConfigVar(utils::HASHICORP_CONTAINER_TOKEN);
const std::string container_url = utils::getStringConfigVar(utils::HASHICORP_CONTAINER_URL);
const std::string container_path = utils::getStringConfigVar(utils::HASHICORP_CONTAINER_PATH);
const std::string mount_point = utils::getStringConfigVar(utils::HASHICORP_CONTAINER_MOUNT_POINT);
const std::string key_name = utils::getStringConfigVar(utils::HASHICORP_CONTAINER_KEY_NAME);

// Construct the URL
std::string url = container_url + "/v1/" + mount_point + "/data/" + container_path;

// Make the HTTP GET request using cpr
cpr::Response response = cpr::Get(
cpr::Url{url},
cpr::Header{{"X-Vault-Token", 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["data"]["data"][key_name].s();
}

std::vector<uint8_t> get_seed() {
auto secret = get_secret();

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

return serialized_secret;
}
}
Loading

0 comments on commit f7beb24

Please sign in to comment.