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  };