Skip to content

Commit

Permalink
Add Lockbox Dockerfile
Browse files Browse the repository at this point in the history
  • Loading branch information
ssantos21 committed Dec 13, 2024
1 parent fd17ca7 commit 4d11299
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 51 deletions.
1 change: 1 addition & 0 deletions lockbox/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Settings.toml
24 changes: 24 additions & 0 deletions lockbox/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# general settings
# KEY_MANAGER can be one of: google_kms, hashicorp or filesystem
LOCKBOX_DATABASE_URL=postgresql://postgres:postgres@localhost/enclave
LOCKBOX_PORT=18080
KEY_MANAGER=google_kms

# filesystem settings
SEED_FILEPATH=./seed

# google_kms settings
GCLOUD_PROJECT_ID=mercury-441416
GCLOUD_PROJECT_NUMBER=100600525477
GCLOUD_LOCATION_ID=global
GCLOUD_SECRET_MANAGER_KEY_NAME=encrypted-key
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=
8 changes: 4 additions & 4 deletions lockbox/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ target_link_libraries(MercuryLockbox PRIVATE
OpenSSL::Crypto)

# Copy Settings.toml after building MercuryLockbox
add_custom_command(TARGET MercuryLockbox POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_SOURCE_DIR}/Settings.toml
$<TARGET_FILE_DIR:MercuryLockbox>/Settings.toml)
# add_custom_command(TARGET MercuryLockbox POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy_if_different
# ${CMAKE_SOURCE_DIR}/Settings.toml
# $<TARGET_FILE_DIR:MercuryLockbox>/Settings.toml)
46 changes: 46 additions & 0 deletions lockbox/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Start with Ubuntu as base image
FROM ubuntu:22.04

# Prevent interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive

# Install essential packages
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
curl \
git \
ninja-build \
pkg-config \
tar \
unzip \
zip \
libpq-dev \
autoconf \
automake \
libtool \
&& rm -rf /var/lib/apt/lists/*

# Set up working directory
WORKDIR /app

# Install vcpkg
RUN git clone https://github.com/Microsoft/vcpkg.git /opt/vcpkg && \
/opt/vcpkg/bootstrap-vcpkg.sh -disableMetrics

# Add vcpkg to PATH
ENV PATH="/opt/vcpkg:${PATH}"

# Set vcpkg root
ENV VCPKG_ROOT=/opt/vcpkg

# Copy your project files
COPY . .

# Create build directory and run cmake
RUN mkdir -p build && cd build
RUN cd build && cmake --preset=vcpkg ..
RUN cd build && cmake --build .

# Set the default command
CMD ["./build/MercuryLockbox"]
19 changes: 17 additions & 2 deletions lockbox/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Lockbox server

To run:
### 1. Running from source:

1. Install vcpkg package manager, following the instruction [here](https://learn.microsoft.com/en-us/vcpkg/get_started/get-started?pivots=shell-bash).
2. Install `ninja` build system (`sudo apt-get -y install ninja-build`).
Expand All @@ -13,4 +13,19 @@ $ cmake --build .
```
4. Set the desired key manager in `Settings.toml`. Currently, there are 3 available: `google_kms`, `hashicorp`, `filesystem`.

5. Then, to run the server: `./MercuryLockbox`.
5. Then, to run the server: `./MercuryLockbox`.

### 2. Running from Dockerfile:

1. Edit the `.env` file according to your personal settings.

2. Run `$ docker build -t mercury-lockbox .`
3. 1. For `filesystem` or `hashicorp` key manager, you can run `$ docker run --env-file .env mercury-lockbox`.
2. For `google_kms` key manager, you need to pass your service account key file at runtime:
```bash
docker run --env-file .env \
-v /path/to/service-account-key.json:/app/credentials.json \
-e GOOGLE_APPLICATION_CREDENTIALS=/app/credentials.json \
mercury-lockbox
```

30 changes: 30 additions & 0 deletions lockbox/include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,34 @@

namespace utils {

// config vars
struct config_var
{
std::string env_var;
std::string toml_var_1;
std::string toml_var_2;
};

static const config_var DATABASE_URL = {"LOCKBOX_DATABASE_URL", "general", "database_connection_string"};
static const config_var KEY_MANAGER = {"KEY_MANAGER", "general", "key_manager"};
static const config_var SERVER_PORT = {"LOCKBOX_PORT", "general", "server_port"};

static const config_var SEED_FILEPATH = {"SEED_FILEPATH", "filesystem", "seed_filepath"};

static const config_var GCLOUD_PROJECT_ID = {"GCLOUD_PROJECT_ID", "gcloud", "project_id"};
static const config_var GCLOUD_PROJECT_NUMBER = {"GCLOUD_PROJECT_NUMBER", "gcloud", "project_number"};
static const config_var GCLOUD_SECRET_MANAGER_KEY_NAME = {"GCLOUD_SECRET_MANAGER_KEY_NAME", "secretmanager", "key_name"};
static const config_var GCLOUD_LOCATION_ID = {"GCLOUD_LOCATION_ID", "gcloud", "location_id"};
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"};

struct chacha20_poly1305_encrypted_data {
size_t data_len;
unsigned char* data;
Expand All @@ -27,6 +55,8 @@ namespace utils {

uint16_t getServerPort();

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

} // namespace utils

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

std::string getDatabaseConnectionString() {
const char* value = std::getenv("ENCLAVE_DATABASE_URL");

if (value == nullptr) {
auto config = toml::parse_file("Settings.toml");
return config["general"]["database_connection_string"].as_string()->get();
} else {
return std::string(value);
}
return utils::getStringConfigVar(
utils::DATABASE_URL.env_var, utils::DATABASE_URL.toml_var_1, utils::DATABASE_URL.toml_var_2);
}

// Assumes the buffer is large enough. In a real application, ensure buffer safety.
Expand Down
10 changes: 2 additions & 8 deletions lockbox/src/filesystem_key_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,8 @@
namespace filesystem_key_manager {

std::string getSeedFilePath() {
const char* value = std::getenv("SEED_FILEPATH");

if (value == nullptr) {
auto config = toml::parse_file("Settings.toml");
return config["filesystem"]["seed_filepath"].as_string()->get();
} else {
return std::string(value);
}
return utils::getStringConfigVar(
utils::SEED_FILEPATH.env_var, utils::SEED_FILEPATH.toml_var_1, utils::SEED_FILEPATH.toml_var_2);
}

std::vector<uint8_t> get_seed() {
Expand Down
28 changes: 18 additions & 10 deletions lockbox/src/google_key_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
#include "google/cloud/location.h"
#include <iostream>
#include "utils.h"
#include <toml++/toml.h>

namespace key_manager {

std::string get_encrypted_secret() {

auto config = toml::parse_file("Settings.toml");
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_number = utils::getStringConfigVar(
utils::GCLOUD_PROJECT_NUMBER.env_var, utils::GCLOUD_PROJECT_NUMBER.toml_var_1, utils::GCLOUD_PROJECT_NUMBER.toml_var_2);

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 project_id = config["gcloud"]["project_id"].as_string()->get();
auto project_number = config["gcloud"]["project_number"].as_string()->get();
auto key_name = config["secretmanager"]["key_name"].as_string()->get();
auto version = 1;

namespace secretmanager = ::google::cloud::secretmanager_v1;
Expand All @@ -34,12 +37,17 @@ namespace key_manager {

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

auto config = toml::parse_file("Settings.toml");
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 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 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 location_id = config["gcloud"]["location_id"].as_string()->get();
auto project_id = config["gcloud"]["project_id"].as_string()->get();
auto key_ring = config["kms"]["ring"].as_string()->get();
auto crypto_key = config["kms"]["crypto_key"].as_string()->get();
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);

namespace kms = ::google::cloud::kms_v1;
auto client = kms::KeyManagementServiceClient(kms::MakeKeyManagementServiceConnection());
Expand Down
23 changes: 14 additions & 9 deletions lockbox/src/hashicorp_key_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
#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 = 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 = config["hashicorp"]["hcp_client_id"].as_string()->get();
const std::string client_secret = config["hashicorp"]["hcp_client_secret"].as_string()->get();
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);

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

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

auto config = toml::parse_file("Settings.toml");
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 = 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();
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 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 secret_name = utils::getStringConfigVar(
utils::HASHICORP_SECRET_NAME.env_var, utils::HASHICORP_SECRET_NAME.toml_var_1, utils::HASHICORP_SECRET_NAME.toml_var_2);

// Construct the URL
std::string url = "https://api.cloud.hashicorp.com/secrets/2023-11-28/organizations/" + organization_id +
Expand Down
10 changes: 2 additions & 8 deletions lockbox/src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,8 @@ namespace lockbox {
}

std::string getKeyManager() {
const char* value = std::getenv("KEY_MANAGER");

if (value == nullptr) {
auto config = toml::parse_file("Settings.toml");
return config["general"]["key_manager"].as_string()->get();
} else {
return std::string(value);
}
return utils::getStringConfigVar(
utils::KEY_MANAGER.env_var, utils::KEY_MANAGER.toml_var_1, utils::KEY_MANAGER.toml_var_2);
}

void start_server() {
Expand Down
15 changes: 13 additions & 2 deletions lockbox/src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,25 @@ namespace utils {
}

uint16_t getServerPort() {
const char* value = std::getenv("ENCLAVE_PORT");
const char* value = std::getenv(SERVER_PORT.env_var.c_str());

if (value == nullptr) {
auto config = toml::parse_file("Settings.toml");
int64_t server_port = config["general"]["server_port"].as_integer()->get();
int64_t server_port = config[SERVER_PORT.toml_var_1][SERVER_PORT.toml_var_2].as_integer()->get();
return convertInt64ToUint16(server_port);
} else {
return convertStringToUint16(value);
}
}

std::string getStringConfigVar(const std::string& env_var, const std::string& toml_var_1, const std::string& toml_var_2) {
const char* value = std::getenv(env_var.c_str());

if (value == nullptr) {
auto config = toml::parse_file("Settings.toml");
return config[toml_var_1][toml_var_2].as_string()->get();
} else {
return std::string(value);
}
}
}
4 changes: 4 additions & 0 deletions lockbox/vcpkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
{
"name": "openssl",
"version>=": "3.4.0"
},
{
"name": "cpr",
"version>=": "1.11.1"
}
]
}

0 comments on commit 4d11299

Please sign in to comment.