Files
scylladb/ent/encryption/azure_host.hh
Nikos Dragazis a1aef456ac encryption: azure: Add override options
Extend `get_or_create_key()` to accept host options that override the
config options. This will be used to pass encryption options from the
table schema. Currently, only the master key can be overridden.

Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
2025-07-16 17:14:09 +03:00

119 lines
3.6 KiB
C++

/*
* Copyright (C) 2025 ScyllaDB
*
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#pragma once
#include <memory>
#include <seastar/http/reply.hh>
#include <seastar/core/future.hh>
#include <seastar/core/shared_ptr.hh>
#include "symmetric_key.hh"
namespace encryption {
class encryption_context;
class vault_error : public std::exception {
// The error response always contains a code and a message.
// https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#handling-errors
static constexpr char ERROR_KEY[] = "error";
static constexpr char ERROR_CODE_KEY[] = "code";
static constexpr char ERROR_MESSAGE_KEY[] = "message";
http::reply::status_type _status;
std::string _code, _msg;
public:
vault_error(const http::reply::status_type& status, std::string_view code, std::string_view msg)
: _status(status)
, _code(code)
, _msg(fmt::format("{}: {}", code, msg))
{}
const http::reply::status_type& status() const {
return _status;
}
const std::string& code() const {
return _code;
}
const char* what() const noexcept override {
return _msg.c_str();
}
static vault_error make_error(const http::reply::status_type& status, std::string_view result);
};
// Common error codes from Azure Key Vault:
// https://learn.microsoft.com/en-us/azure/key-vault/general/rest-error-codes
//
// Not to be confused with the more specialized 'innererror' codes:
// https://learn.microsoft.com/en-us/azure/key-vault/general/common-error-codes
namespace vault_errors {
[[maybe_unused]] static constexpr char Unauthorized[] = "Unauthorized";
[[maybe_unused]] static constexpr char Forbidden[] = "Forbidden";
[[maybe_unused]] static constexpr char Throttled[] = "Throttled";
[[maybe_unused]] static constexpr char KeyNotFound[] = "KeyNotFound";
}
class azure_host {
public:
class impl;
using id_type = bytes;
using key_ptr = shared_ptr<symmetric_key>;
using key_and_id_type = std::tuple<key_ptr, id_type>;
struct host_options {
std::string tenant_id;
std::string client_id;
std::string client_secret;
std::string client_cert;
std::string authority;
std::string imds_endpoint;
// Azure Key Vault Key to encrypt data keys with. Format: <vault name>/<keyname>
std::string master_key;
// TLS options
std::string truststore;
std::string priority_string;
std::optional<std::chrono::milliseconds> key_cache_expiry;
std::optional<std::chrono::milliseconds> key_cache_refresh;
};
azure_host(const std::string& name, const host_options&); // used for testing
azure_host(encryption_context&, const std::string& name, const host_options&);
azure_host(encryption_context&, const std::string& name, const std::unordered_map<sstring, sstring>&);
~azure_host();
/**
* Async initialization.
*
* Performs preliminary checks.
* Should precede any calls to the Key Management API.
*/
future<> init();
const host_options& options() const;
struct option_override {
std::optional<std::string> master_key;
};
/**
* Key Management API to create or retrieve data keys.
*
* Throws encryption::base_error derivatives to indicate failure conditions
* such as host misconfigurations, network issues, or authentication failures.
*/
future<key_and_id_type> get_or_create_key(const key_info&, const option_override* = nullptr);
future<key_ptr> get_key_by_id(const id_type&, const key_info&);
private:
std::unique_ptr<impl> _impl;
};
}