Configure the Ceph Object Gateway
=================================
-Edit the Ceph configuration file to add information about the Barbican server
-and Keystone user::
+Edit the Ceph configuration file to enable Barbican as a KMS and add information
+about the Barbican server and Keystone user::
+ rgw crypt s3 kms backend = barbican
rgw barbican url = http://barbican.example.com:9311
rgw keystone barbican user = rgwcrypt-user
rgw keystone barbican password = rgwcrypt-password
:Type: Boolean
:Default: ``true``
+
+Server-side encryption Settings
+===============================
+
+``rgw crypt s3 kms backend``
+
+:Description: Where the SSE-KMS encryption keys are stored. Supported KMS
+ systems are OpenStack Barbican (``barbican``, the default) and
+ HashiCorp Vault (``vault``).
+:Type: String
+:Default: None
+
+
Barbican Settings
=================
:Default: None
+HashiCorp Vault Settings
+========================
+
+``rgw crypt vault auth```
+
+:Description: Type of authentication method to be used. The only method
+ currently supported is ``token``.
+:Type: String
+:Default: ``token``
+
+``rgw crypt vault token file``
+
+:Description: If authentication method is ``token``, provide a path to the token
+ file, which should be readable only by Rados Gateway.
+:Type: String
+:Default: None
+
+``rgw crypt vault addr``
+
+:Description: Provide a URL to the Vault server secret path.
+:Type: String
+:Default: None
+
QoS settings
------------
This is implemented in S3 according to the `Amazon SSE-KMS`_ specification.
In principle, any key management service could be used here, but currently
-only integration with `Barbican`_ is implemented.
+only integration with `Barbican`_ and `Vault`_ are implemented.
-See `OpenStack Barbican Integration`_.
+See `OpenStack Barbican Integration`_ and `HashiCorp Vault Integration`_.
Automatic Encryption (for testing only)
=======================================
.. _Amazon SSE-C: https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html
.. _Amazon SSE-KMS: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html
.. _Barbican: https://wiki.openstack.org/wiki/Barbican
+.. _Vault: https://www.vaultproject.io/docs/
.. _OpenStack Barbican Integration: ../barbican
+.. _HashiCorp Vault Integration: ../vault
Export over NFS <nfs>
OpenStack Keystone Integration <keystone>
OpenStack Barbican Integration <barbican>
+ HashiCorp Vault Integration <vault>
Open Policy Agent Integration <opa>
Multi-tenancy <multitenancy>
Compression <compression>
--- /dev/null
+===========================
+HashiCorp Vault Integration
+===========================
+
+HashiCorp `Vault`_ can be used as a secure key management service for
+`Server-Side Encryption`_ (SSE-KMS).
+
+#. `Vault authentication`_
+#. `Create a key in Vault`_
+#. `Configure the Ceph Object Gateway`_
+#. `Upload object`_
+
+Vault authentication
+====================
+
+Vault provides several authentication mechanisms. Currently, the Object Gateway
+supports the `token authentication method`_ only.
+
+When authenticating with Vault using the token method, save the token in a
+plain-text file. The path to this file must be provided in the Gateway
+configuration file (see below). For security reasons, ensure the file is
+readable by the Object Gateway only.
+
+Create a key in Vault
+=====================
+
+Generate and save a 256-bit key in Vault. Vault provides several Secret
+Engines, which store, generate, and encrypt data. For instance, create a key
+in the `KV Secrets engine`_ using Vault's command line client::
+
+ export VAULT_ADDR='http://vaultserver:8200'
+ vault kv put secret/myproject/mybucketkey key=$(dd bs=32 count=1 if=/dev/urandom of=/dev/stdout 2>/dev/null | base64)
+
+Output::
+
+ ====== Metadata ======
+ Key Value
+ --- -----
+ created_time 2019-08-29T17:01:09.095824999Z
+ deletion_time n/a
+ destroyed false
+ version 1
+
+ === Data ===
+ Key Value
+ --- -----
+ key Ak5dRyLQjwX/wb7vo6Fq1qjsfk1dh2CiSicX+gLAhwk=
+
+The URL to the secret in Vault must be provided in the Gateway configuration
+file (see below).
+
+Configure the Ceph Object Gateway
+=================================
+
+Edit the Ceph configuration file to enable Vault as a KMS for server-side
+encryption::
+
+ rgw crypt s3 kms backend = vault
+ rgw crypt vault auth = token
+ rgw crypt vault addr = http://vaultserver:8200
+ rgw crypt vault token file = /path/to/token.file
+
+Upload object
+=============
+
+When uploading an object, provide the SSE key ID in the request. As an example,
+using the AWS command-line client::
+
+ aws --endpoint=http://radosgw:8000 s3 cp plaintext.txt s3://mybucket/encrypted.txt --sse=aws:kms --sse-kms-key-id /v1/secret/data/myproject/mybucketkey
+
+The object gateway will fetch the key from Vault (using the token for
+authentication), encrypt the object and store it in the bucket. Any request to
+downlod the object will require the correct key ID for the Gateway to
+successfully the decrypt it.
+
+.. _Server-Side Encryption: ../encryption
+.. _Vault: https://www.vaultproject.io/docs/
+.. _token authentication method: https://www.vaultproject.io/docs/auth/token.html
+.. _KV Secrets engine: https://www.vaultproject.io/docs/secrets/kv/
OPTION(rgw_trust_forwarded_https, OPT_BOOL) // trust Forwarded and X-Forwarded-Proto headers for ssl termination
OPTION(rgw_crypt_require_ssl, OPT_BOOL) // requests including encryption key headers must be sent over ssl
OPTION(rgw_crypt_default_encryption_key, OPT_STR) // base64 encoded key for encryption of rgw objects
+
+OPTION(rgw_crypt_s3_kms_backend, OPT_STR) // Where SSE-KMS encryption keys are stored
+OPTION(rgw_crypt_vault_auth, OPT_STR) // Type of authentication method to be used with Vault
+OPTION(rgw_crypt_vault_token_file, OPT_STR) // Path to the token file for Vault authentication
+OPTION(rgw_crypt_vault_addr, OPT_STR) // URL to Vault server endpoint
+
OPTION(rgw_crypt_s3_kms_encryption_keys, OPT_STR) // extra keys that may be used for aws:kms
// defined as map "key1=YmluCmJvb3N0CmJvb3N0LQ== key2=b3V0CnNyYwpUZXN0aW5nCg=="
OPTION(rgw_crypt_suppress_logs, OPT_BOOL) // suppress logs that might print customer key
.set_default("")
.set_description(""),
+ Option("rgw_crypt_s3_kms_backend", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+ .set_default("barbican")
+ .set_enum_allowed({"barbican", "vault", "testing"})
+ .set_description(
+ "Where the SSE-KMS encryption keys are stored. Supported KMS "
+ "systems are OpenStack Barbican ('barbican', the default) and HashiCorp "
+ "Vault ('vault')."),
+
Option("rgw_crypt_s3_kms_encryption_keys", Option::TYPE_STR, Option::LEVEL_DEV)
.set_default("")
.set_description(""),
+ Option("rgw_crypt_vault_auth", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+ .set_default("token")
+ .set_enum_allowed({"token"})
+ .set_description(
+ "Type of authentication method to be used with Vault. "
+ "The only currently supported method is 'token'.")
+ .add_see_also({
+ "rgw_crypt_s3_kms_backend",
+ "rgw_crypt_vault_addr",
+ "rgw_crypt_vault_token_file"}),
+
+ Option("rgw_crypt_vault_token_file", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+ .set_default("")
+ .set_description(
+ "If authentication method is 'token', provide a path to the token file, "
+ "which for security reasons should readable only by Rados Gateway.")
+ .add_see_also({
+ "rgw_crypt_s3_kms_backend",
+ "rgw_crypt_vault_auth",
+ "rgw_crypt_vault_addr"}),
+
+ Option("rgw_crypt_vault_addr", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+ .set_default("")
+ .set_description(
+ "Provide a URL to the Vault server secret path.")
+ .add_see_also({
+ "rgw_crypt_s3_kms_backend",
+ "rgw_crypt_vault_auth",
+ "rgw_crypt_vault_token_file"}),
+
Option("rgw_crypt_suppress_logs", Option::TYPE_BOOL, Option::LEVEL_ADVANCED)
.set_default(true)
.set_description("Suppress logs that might print client key"),
rgw_rest_sts.cc
rgw_perf_counters.cc
rgw_rest_iam.cc
- rgw_object_lock.cc)
+ rgw_object_lock.cc
+ rgw_kms.cc)
if(WITH_RADOSGW_AMQP_ENDPOINT)
list(APPEND librgw_common_srcs rgw_amqp.cc)
#include <rgw/rgw_rest_s3.h>
#include "include/ceph_assert.h"
#include <boost/utility/string_view.hpp>
-#include <rgw/rgw_keystone.h>
-#include "include/str_map.h"
#include "crypto/crypto_accel.h"
#include "crypto/crypto_plugin.h"
+#include "rgw/rgw_kms.h"
#include <openssl/evp.h>
return std::string(random, sizeof(random));
}
-static int get_barbican_url(CephContext * const cct,
- std::string& url)
-{
- url = cct->_conf->rgw_barbican_url;
- if (url.empty()) {
- ldout(cct, 0) << "ERROR: conf rgw_barbican_url is not set" << dendl;
- return -EINVAL;
- }
-
- if (url.back() != '/') {
- url.append("/");
- }
-
- return 0;
-}
-
-static int request_key_from_barbican(CephContext *cct,
- boost::string_view key_id,
- boost::string_view key_selector,
- const std::string& barbican_token,
- std::string& actual_key) {
- std::string secret_url;
- int res;
- res = get_barbican_url(cct, secret_url);
- if (res < 0) {
- return res;
- }
- secret_url += "v1/secrets/" + std::string(key_id);
-
- bufferlist secret_bl;
- RGWHTTPTransceiver secret_req(cct, "GET", secret_url, &secret_bl);
- secret_req.append_header("Accept", "application/octet-stream");
- secret_req.append_header("X-Auth-Token", barbican_token);
-
- res = secret_req.process(null_yield);
- if (res < 0) {
- return res;
- }
- if (secret_req.get_http_status() ==
- RGWHTTPTransceiver::HTTP_STATUS_UNAUTHORIZED) {
- return -EACCES;
- }
-
- if (secret_req.get_http_status() >=200 &&
- secret_req.get_http_status() < 300 &&
- secret_bl.length() == AES_256_KEYSIZE) {
- actual_key.assign(secret_bl.c_str(), secret_bl.length());
- memset(secret_bl.c_str(), 0, secret_bl.length());
- } else {
- res = -EACCES;
- }
- return res;
-}
-
-static map<string,string> get_str_map(const string &str) {
- map<string,string> m;
- get_str_map(str, &m, ";, \t");
- return m;
-}
-
-static int get_actual_key_from_kms(CephContext *cct,
- boost::string_view key_id,
- boost::string_view key_selector,
- std::string& actual_key)
-{
- int res = 0;
- ldout(cct, 20) << "Getting KMS encryption key for key=" << key_id << dendl;
- static map<string,string> str_map = get_str_map(
- cct->_conf->rgw_crypt_s3_kms_encryption_keys);
-
- map<string, string>::iterator it = str_map.find(std::string(key_id));
- if (it != str_map.end() ) {
- std::string master_key;
- try {
- master_key = from_base64((*it).second);
- } catch (...) {
- ldout(cct, 5) << "ERROR: get_actual_key_from_kms invalid encryption key id "
- << "which contains character that is not base64 encoded."
- << dendl;
- return -EINVAL;
- }
-
- if (master_key.length() == AES_256_KEYSIZE) {
- uint8_t _actual_key[AES_256_KEYSIZE];
- if (AES_256_ECB_encrypt(cct,
- reinterpret_cast<const uint8_t*>(master_key.c_str()), AES_256_KEYSIZE,
- reinterpret_cast<const uint8_t*>(key_selector.data()),
- _actual_key, AES_256_KEYSIZE)) {
- actual_key = std::string((char*)&_actual_key[0], AES_256_KEYSIZE);
- } else {
- res = -EIO;
- }
- memset(_actual_key, 0, sizeof(_actual_key));
- } else {
- ldout(cct, 20) << "Wrong size for key=" << key_id << dendl;
- res = -EIO;
- }
- } else {
- std::string token;
- if (rgw::keystone::Service::get_keystone_barbican_token(cct, token) < 0) {
- ldout(cct, 5) << "Failed to retrieve token for barbican" << dendl;
- res = -EINVAL;
- return res;
- }
-
- res = request_key_from_barbican(cct, key_id, key_selector, token, actual_key);
- if (res != 0) {
- ldout(cct, 5) << "Failed to retrieve secret from barbican:" << key_id << dendl;
- }
- }
- return res;
-}
-
static inline void set_attr(map<string, bufferlist>& attrs,
const char* key,
boost::string_view value)
--- /dev/null
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+/**
+ * Server-side encryption integrations with Key Management Systems (SSE-KMS)
+ */
+
+#include "include/str_map.h"
+#include "common/safe_io.h"
+#include "rgw/rgw_crypt.h"
+#include "rgw/rgw_keystone.h"
+#include "rgw/rgw_b64.h"
+#include "rgw/rgw_kms.h"
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rgw
+
+using namespace rgw;
+
+static map<string,string> get_str_map(const string &str) {
+ map<string,string> m;
+ get_str_map(str, &m, ";, \t");
+ return m;
+}
+
+static int get_actual_key_from_conf(CephContext *cct,
+ boost::string_view key_id,
+ boost::string_view key_selector,
+ std::string& actual_key)
+{
+ int res = 0;
+
+ static map<string,string> str_map = get_str_map(
+ cct->_conf->rgw_crypt_s3_kms_encryption_keys);
+
+ map<string, string>::iterator it = str_map.find(std::string(key_id));
+ if (it == str_map.end())
+ return -ERR_INVALID_ACCESS_KEY;
+
+ std::string master_key;
+ try {
+ master_key = from_base64((*it).second);
+ } catch (std::exception&) {
+ ldout(cct, 5) << "ERROR: get_actual_key_from_conf invalid encryption key id "
+ << "which contains character that is not base64 encoded."
+ << dendl;
+ return -EINVAL;
+ }
+
+ if (master_key.length() == AES_256_KEYSIZE) {
+ uint8_t _actual_key[AES_256_KEYSIZE];
+ if (AES_256_ECB_encrypt(cct,
+ reinterpret_cast<const uint8_t*>(master_key.c_str()), AES_256_KEYSIZE,
+ reinterpret_cast<const uint8_t*>(key_selector.data()),
+ _actual_key, AES_256_KEYSIZE)) {
+ actual_key = std::string((char*)&_actual_key[0], AES_256_KEYSIZE);
+ } else {
+ res = -EIO;
+ }
+ memset(_actual_key, 0, sizeof(_actual_key));
+ } else {
+ ldout(cct, 20) << "Wrong size for key=" << key_id << dendl;
+ res = -EIO;
+ }
+
+ return res;
+}
+
+static int get_barbican_url(CephContext * const cct,
+ std::string& url)
+{
+ url = cct->_conf->rgw_barbican_url;
+ if (url.empty()) {
+ ldout(cct, 0) << "ERROR: conf rgw_barbican_url is not set" << dendl;
+ return -EINVAL;
+ }
+
+ if (url.back() != '/') {
+ url.append("/");
+ }
+
+ return 0;
+}
+
+static int request_key_from_barbican(CephContext *cct,
+ boost::string_view key_id,
+ const std::string& barbican_token,
+ std::string& actual_key) {
+ std::string secret_url;
+ int res;
+ res = get_barbican_url(cct, secret_url);
+ if (res < 0) {
+ return res;
+ }
+ secret_url += "v1/secrets/" + std::string(key_id);
+
+ bufferlist secret_bl;
+ RGWHTTPTransceiver secret_req(cct, "GET", secret_url, &secret_bl);
+ secret_req.append_header("Accept", "application/octet-stream");
+ secret_req.append_header("X-Auth-Token", barbican_token);
+
+ res = secret_req.process(null_yield);
+ if (res < 0) {
+ return res;
+ }
+ if (secret_req.get_http_status() ==
+ RGWHTTPTransceiver::HTTP_STATUS_UNAUTHORIZED) {
+ return -EACCES;
+ }
+
+ if (secret_req.get_http_status() >=200 &&
+ secret_req.get_http_status() < 300 &&
+ secret_bl.length() == AES_256_KEYSIZE) {
+ actual_key.assign(secret_bl.c_str(), secret_bl.length());
+ secret_bl.zero();
+ } else {
+ res = -EACCES;
+ }
+ return res;
+}
+
+static int get_actual_key_from_barbican(CephContext *cct,
+ boost::string_view key_id,
+ std::string& actual_key)
+{
+ int res = 0;
+ std::string token;
+
+ if (rgw::keystone::Service::get_keystone_barbican_token(cct, token) < 0) {
+ ldout(cct, 5) << "Failed to retrieve token for Barbican" << dendl;
+ return -EINVAL;
+ }
+
+ res = request_key_from_barbican(cct, key_id, token, actual_key);
+ if (res != 0) {
+ ldout(cct, 5) << "Failed to retrieve secret from Barbican:" << key_id << dendl;
+ }
+ return res;
+}
+
+static int request_key_from_vault_with_token(CephContext *cct,
+ boost::string_view key_id,
+ bufferlist *secret_bl)
+{
+ std::string token_file, vault_addr, vault_token;
+ int res = 0;
+
+ token_file = cct->_conf->rgw_crypt_vault_token_file;
+ if (token_file.empty()) {
+ ldout(cct, 0) << "ERROR: Vault token file not set in rgw_crypt_vault_token_file" << dendl;
+ return -EINVAL;
+ }
+ ldout(cct, 20) << "Vault token file: " << token_file << dendl;
+
+ char buf[2048];
+ res = safe_read_file("", token_file.c_str(), buf, sizeof(buf));
+ if (res < 0) {
+ if (-ENOENT == res) {
+ ldout(cct, 0) << "ERROR: Token file '" << token_file << "' not found " << dendl;
+ } else if (-EACCES == res) {
+ ldout(cct, 0) << "ERROR: Permission denied reading token file" << dendl;
+ } else {
+ ldout(cct, 0) << "ERROR: Failed to read token file with error " << res << dendl;
+ }
+ return res;
+ }
+ // drop trailing newlines
+ while (res && isspace(buf[res-1])) {
+ --res;
+ }
+ vault_token = std::string{buf, static_cast<size_t>(res)};
+ memset(buf, 0, sizeof(buf));
+
+ vault_addr = cct->_conf->rgw_crypt_vault_addr;
+ if (vault_addr.empty()) {
+ ldout(cct, 0) << "ERROR: Vault address not set in rgw_crypt_vault_addr" << dendl;
+ return -EINVAL;
+ }
+
+ std::string secret_url = vault_addr + std::string(key_id);
+ RGWHTTPTransceiver secret_req(cct, "GET", secret_url, secret_bl);
+ secret_req.append_header("X-Vault-Token", vault_token);
+ vault_token.replace(0, vault_token.length(), vault_token.length(), '\000');
+ res = secret_req.process(null_yield);
+ if (res < 0) {
+ ldout(cct, 0) << "ERROR: Request to Vault failed with error " << res << dendl;
+ return res;
+ }
+
+ if (secret_req.get_http_status() ==
+ RGWHTTPTransceiver::HTTP_STATUS_UNAUTHORIZED) {
+ ldout(cct, 0) << "ERROR: Vault request failed authorization" << dendl;
+ return -EACCES;
+ }
+
+ ldout(cct, 20) << "Request to Vault returned " << res << " and HTTP status "
+ << secret_req.get_http_status() << dendl;
+ return res;
+}
+
+static int get_actual_key_from_vault(CephContext *cct,
+ boost::string_view key_id,
+ std::string& actual_key)
+{
+ int res = 0;
+ std::string auth;
+ bufferlist secret_bl;
+
+ auth = cct->_conf->rgw_crypt_vault_auth;
+ ldout(cct, 20) << "Vault authentication method: " << auth << dendl;
+
+ // Currently only token-based authentication is supported
+ if (RGW_SSE_KMS_VAULT_AUTH_TOKEN == auth) {
+ res = request_key_from_vault_with_token(cct, key_id, &secret_bl);
+ } else {
+ ldout(cct, 0) << "ERROR: Invalid rgw_crypt_vault_auth: " << auth << dendl;
+ return -EINVAL;
+ }
+
+ if (res < 0) {
+ return res;
+ }
+
+ JSONParser parser;
+ if (!parser.parse(secret_bl.c_str(), secret_bl.length())) {
+ ldout(cct, 0) << "ERROR: Failed to parse JSON response from Vault" << dendl;
+ return -EINVAL;
+ }
+ secret_bl.zero();
+
+ JSONObj *json_obj = &parser;
+ std::array<std::string, 3> elements = {"data", "data", "key"};
+ for(const auto& elem : elements) {
+ json_obj = json_obj->find_obj(elem);
+ if (!json_obj) {
+ ldout(cct, 0) << "ERROR: Key not found in JSON response from Vault" << dendl;
+ return -EINVAL;
+ }
+ }
+
+ std::string secret;
+ try {
+ secret = from_base64(json_obj->get_data());
+ } catch (std::exception&) {
+ ldout(cct, 0) << "ERROR: Failed to base64 decode key retrieved from Vault" << dendl;
+ return -EINVAL;
+ }
+
+ actual_key.assign(secret.c_str(), secret.length());
+ secret.replace(0, secret.length(), secret.length(), '\000');
+
+ return res;
+}
+
+int get_actual_key_from_kms(CephContext *cct,
+ boost::string_view key_id,
+ boost::string_view key_selector,
+ std::string& actual_key)
+{
+ std::string kms_backend;
+
+ kms_backend = cct->_conf->rgw_crypt_s3_kms_backend;
+ ldout(cct, 20) << "Getting KMS encryption key for key " << key_id << dendl;
+ ldout(cct, 20) << "SSE-KMS backend is " << kms_backend << dendl;
+
+ if (RGW_SSE_KMS_BACKEND_BARBICAN == kms_backend)
+ return get_actual_key_from_barbican(cct, key_id, actual_key);
+
+ if (RGW_SSE_KMS_BACKEND_VAULT == kms_backend)
+ return get_actual_key_from_vault(cct, key_id, actual_key);
+
+ if (RGW_SSE_KMS_BACKEND_TESTING == kms_backend)
+ return get_actual_key_from_conf(cct, key_id, key_selector, actual_key);
+
+ ldout(cct, 0) << "ERROR: Invalid rgw_crypt_s3_kms_backend: " << kms_backend << dendl;
+ return -EINVAL;
+}
--- /dev/null
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+/**
+ * Server-side encryption integrations with Key Management Systems (SSE-KMS)
+ */
+
+#ifndef CEPH_RGW_KMS_H
+#define CEPH_RGW_KMS_H
+
+static const std::string RGW_SSE_KMS_BACKEND_TESTING = "testing";
+static const std::string RGW_SSE_KMS_BACKEND_BARBICAN = "barbican";
+static const std::string RGW_SSE_KMS_BACKEND_VAULT = "vault";
+
+static const std::string RGW_SSE_KMS_VAULT_AUTH_TOKEN = "token";
+static const std::string RGW_SSE_KMS_VAULT_AUTH_AGENT = "agent";
+
+/**
+ * Retrieves the actual server-side encryption key from a KMS system given a
+ * key ID. Currently supported KMS systems are OpenStack Barbican and HashiCorp
+ * Vault, but keys can also be retrieved from Ceph configuration file (if
+ * kms is set to 'local').
+ *
+ * \params
+ * TODO
+ * \return
+ */
+int get_actual_key_from_kms(CephContext *cct,
+ boost::string_view key_id,
+ boost::string_view key_selector,
+ std::string& actual_key);
+
+#endif
target_link_libraries(unittest_rgw_arn ${rgw_libs})
+# unittest_rgw_kms
+add_executable(unittest_rgw_kms test_rgw_kms.cc)
+add_ceph_unittest(unittest_rgw_kms)
+
+target_link_libraries(unittest_rgw_kms ${rgw_libs})
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <gtest/gtest.h>
+#include "common/ceph_context.h"
+#include "rgw/rgw_common.h"
+#include "rgw/rgw_kms.cc"
+
+TEST(TestSSEKMS, vault_token_file_unset)
+{
+ CephContext *cct = (new CephContext(CEPH_ENTITY_TYPE_ANY))->get();
+
+ std::string key_id, actual_key;
+ bufferlist secret_bl;
+ ASSERT_EQ(
+ request_key_from_vault_with_token(cct, key_id, &secret_bl),
+ -EINVAL
+ );
+}
+
+TEST(TestSSEKMS, non_existent_vault_token_file)
+{
+ CephContext *cct = (new CephContext(CEPH_ENTITY_TYPE_ANY))->get();
+ cct->_conf.set_val("rgw_crypt_vault_token_file", "/nonexistent/file");
+
+ std::string key_id, key_selector, actual_key;
+ bufferlist secret_bl;
+ ASSERT_EQ(
+ request_key_from_vault_with_token(cct, key_id, &secret_bl),
+ -ENOENT
+ );
+}
admin socket = $CEPH_ASOK_DIR/\$name.\$pid.asok
; needed for s3tests
+ rgw crypt s3 kms backend = testing
rgw crypt s3 kms encryption keys = testkey-1=YmluCmJvb3N0CmJvb3N0LWJ1aWxkCmNlcGguY29uZgo= testkey-2=aWIKTWFrZWZpbGUKbWFuCm91dApzcmMKVGVzdGluZwo=
rgw crypt require ssl = false
; uncomment the following to set LC days as the value in seconds;
; needed for passing lc time based s3-tests (can be verbose)
; rgw lc debug interval = 10
+ ; The following settings are for SSE-KMS with Vault
+ ; rgw crypt s3 kms backend = vault
+ ; rgw crypt vault auth = token
+ ; rgw crypt vault addr = http://127.0.0.1:8200
+ ; rgw crypt vault token file = /path/to/token.file
+
$extra_conf
EOF