github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/c-deps/libroach/ccl/key_manager.h (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Licensed as a CockroachDB Enterprise file under the Cockroach Community 4 // License (the "License"); you may not use this file except in compliance with 5 // the License. You may obtain a copy of the License at 6 // 7 // https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt 8 9 #pragma once 10 11 #include <mutex> 12 #include <rocksdb/env.h> 13 #include <rocksdb/status.h> 14 #include <string> 15 #include "ccl/storageccl/engineccl/enginepbccl/key_registry.pb.h" 16 17 namespace enginepbccl = cockroach::ccl::storageccl::engineccl::enginepbccl; 18 19 // Constants must not be changed, they are used to build the persisted key registry. 20 // The key ID is 32 bytes (the length of the longest possible AES key). This is to easily 21 // tell if a store key file has the right length. 22 static const size_t kKeyIDLength = 32; 23 static const std::string kPlainKeyID = "plain"; 24 static const std::string kKeyRegistryFilename = "COCKROACHDB_DATA_KEYS"; 25 26 // Helpers are in a separate namespace to avoid pollution. 27 // These should only be used by the KeyManager and its tests. 28 namespace KeyManagerUtils { 29 30 // Read key from a file. 31 rocksdb::Status KeyFromFile(rocksdb::Env* env, const std::string& path, 32 enginepbccl::SecretKey* key); 33 34 // Generate a key based on the characteristics of `store_info`. 35 rocksdb::Status KeyFromKeyInfo(rocksdb::Env* env, const enginepbccl::KeyInfo& store_info, 36 enginepbccl::SecretKey* key); 37 38 // Validate a registry. This should be called before using a registry. 39 rocksdb::Status ValidateRegistry(enginepbccl::DataKeysRegistry* registry); 40 41 // Generate a new data key based on the currently active store key. 42 rocksdb::Status GenerateDataKey(rocksdb::Env* env, enginepbccl::DataKeysRegistry* reg); 43 44 }; // namespace KeyManagerUtils 45 46 // KeyManager is the basic implementation for a key manager. 47 // Specific subclasses will provide different methods of accessing keys. 48 class KeyManager { 49 public: 50 virtual ~KeyManager(); 51 52 // CurrentKeyInfo returns the KeyInfo about the active key. 53 // It does NOT include the key itself and can be logged, displayed, and stored. 54 std::unique_ptr<enginepbccl::KeyInfo> CurrentKeyInfo() { 55 auto key = CurrentKey(); 56 if (key == nullptr) { 57 return nullptr; 58 } 59 return std::unique_ptr<enginepbccl::KeyInfo>(new enginepbccl::KeyInfo(key->info())); 60 } 61 62 // CurrentKey returns the key itself. 63 // **WARNING**: this must not be logged, displayed, or stored outside the key registry. 64 virtual std::shared_ptr<enginepbccl::SecretKey> CurrentKey() = 0; 65 66 // GetKeyInfo returns the KeyInfo about the key the requested `id`. 67 // It does NOT include the key itself and can be logged, displayed, and stored. 68 std::unique_ptr<enginepbccl::KeyInfo> GetKeyInfo(const std::string& id) { 69 auto key = GetKey(id); 70 if (key == nullptr) { 71 return nullptr; 72 } 73 return std::unique_ptr<enginepbccl::KeyInfo>(new enginepbccl::KeyInfo(key->info())); 74 } 75 76 // GetKey returns the key with requested `id`. 77 // **WARNING**: this must not be logged, displayed, or stored outside the key registry. 78 virtual std::shared_ptr<enginepbccl::SecretKey> GetKey(const std::string& id) = 0; 79 }; 80 81 // FileKeyManager loads raw keys from files. 82 // Keys are only loaded at startup after object construction, but before use. 83 class FileKeyManager : public KeyManager { 84 public: 85 // `env` is owned by the caller. 86 explicit FileKeyManager(rocksdb::Env* env, std::shared_ptr<rocksdb::Logger> logger, 87 const std::string& active_key_path, const std::string& old_key_path); 88 89 virtual ~FileKeyManager(); 90 91 // LoadKeys tells the key manager to read and validate the key files. 92 // On error, existing keys held by the object are not overwritten. 93 rocksdb::Status LoadKeys(); 94 95 virtual std::shared_ptr<enginepbccl::SecretKey> CurrentKey() override; 96 virtual std::shared_ptr<enginepbccl::SecretKey> GetKey(const std::string& id) override; 97 98 private: 99 rocksdb::Env* env_; 100 std::shared_ptr<rocksdb::Logger> logger_; 101 std::string active_key_path_; 102 std::string old_key_path_; 103 // TODO(mberhault): protect keys by a mutex if we allow reload. 104 std::shared_ptr<enginepbccl::SecretKey> active_key_; 105 std::shared_ptr<enginepbccl::SecretKey> old_key_; 106 }; 107 108 // DataKeyManager generates and handles data keys and persists them to disk. 109 // The Env passed should be an encrypted env using store keys. 110 class DataKeyManager : public KeyManager { 111 public: 112 // `env` is owned by the caller and should be an encrypted Env. 113 // `db_dir` is the rocksdb directory. 114 // If read-only is true, the DataKeyManager can be used to lookup keys but cannot 115 // change any keys (eg: SetActiveStoreKeyInfo will fail). 116 explicit DataKeyManager(rocksdb::Env* env, std::shared_ptr<rocksdb::Logger> logger, 117 const std::string& db_dir, int64_t rotation_period, bool read_only); 118 119 virtual ~DataKeyManager(); 120 121 // LoadKeys tells the key manager to read and validate the key files. 122 // On error, existing keys held by the object are not overwritten. 123 rocksdb::Status LoadKeys(); 124 125 // SetActiveStoreKeyInfo takes the KeyInfo of the active store key 126 // and adds it to the registry. A new data key is generated if needed. 127 rocksdb::Status SetActiveStoreKeyInfo(std::unique_ptr<enginepbccl::KeyInfo> store_key); 128 129 // GetActiveStoreKeyInfo returns the KeyInfo for the active store key. 130 // The data key registry keeps the active store key information (but not the key) from 131 // the first time the active key was seen. Fields like creation_time will only 132 // be accurate here. 133 std::unique_ptr<enginepbccl::KeyInfo> GetActiveStoreKeyInfo(); 134 135 // GetScrubbedRegistry returns a copy of the key registry with key contents scrubbed. 136 std::unique_ptr<enginepbccl::DataKeysRegistry> GetScrubbedRegistry() const; 137 138 virtual std::shared_ptr<enginepbccl::SecretKey> CurrentKey() override; 139 virtual std::shared_ptr<enginepbccl::SecretKey> GetKey(const std::string& id) override; 140 141 private: 142 // Lookup registry_->active_data_key_id in the map. This should only be done after 143 // changing the registry, otherwise use current_key_. 144 std::shared_ptr<enginepbccl::SecretKey> CurrentKeyLocked(); 145 rocksdb::Status LoadKeysHelper(enginepbccl::DataKeysRegistry* registry); 146 // Write the given registry to disk. If successful, update registry_ and current_key_. 147 rocksdb::Status PersistRegistryLocked(std::unique_ptr<enginepbccl::DataKeysRegistry> reg); 148 // MaybeRotateKeyLocked generates a new data key if the active one has expired. 149 rocksdb::Status MaybeRotateKeyLocked(); 150 151 // These do not change after initialization. env_ is thread safe. 152 rocksdb::Env* env_; 153 std::shared_ptr<rocksdb::Logger> logger_; 154 std::unique_ptr<rocksdb::Directory> registry_dir_; 155 std::string registry_path_; 156 int64_t rotation_period_; 157 bool read_only_; 158 159 // The registry is read-only and can only be swapped for another one, it cannot be mutated in 160 // place. mu_ must be held for any registry access. 161 // current_key_ is the active data key (or nullptr if none present yet) and is updated every time 162 // registry_ is modified. 163 // TODO(mberhault): use a shared_mutex for multiple read-only holders. 164 mutable std::mutex mu_; 165 std::unique_ptr<enginepbccl::DataKeysRegistry> registry_; 166 std::shared_ptr<enginepbccl::SecretKey> current_key_; 167 };