]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/parquet/encryption/file_key_wrapper.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / parquet / encryption / file_key_wrapper.cc
CommitLineData
1d09f67e
TL
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#include "parquet/encryption/file_key_wrapper.h"
19#include "parquet/encryption/encryption_internal.h"
20#include "parquet/encryption/key_material.h"
21#include "parquet/encryption/key_metadata.h"
22#include "parquet/encryption/key_toolkit_internal.h"
23#include "parquet/exception.h"
24
25namespace parquet {
26namespace encryption {
27
28FileKeyWrapper::FileKeyWrapper(KeyToolkit* key_toolkit,
29 const KmsConnectionConfig& kms_connection_config,
30 std::shared_ptr<FileKeyMaterialStore> key_material_store,
31 double cache_entry_lifetime_seconds, bool double_wrapping)
32 : kms_connection_config_(kms_connection_config),
33 key_material_store_(key_material_store),
34 cache_entry_lifetime_seconds_(cache_entry_lifetime_seconds),
35 double_wrapping_(double_wrapping) {
36 kms_connection_config_.SetDefaultIfEmpty();
37 // Check caches upon each file writing (clean once in cache_entry_lifetime_seconds_)
38 key_toolkit->kms_client_cache_per_token().CheckCacheForExpiredTokens(
39 cache_entry_lifetime_seconds_);
40 kms_client_ =
41 key_toolkit->GetKmsClient(kms_connection_config, cache_entry_lifetime_seconds_);
42
43 if (double_wrapping) {
44 key_toolkit->kek_write_cache_per_token().CheckCacheForExpiredTokens(
45 cache_entry_lifetime_seconds_);
46 kek_per_master_key_id_ =
47 key_toolkit->kek_write_cache_per_token().GetOrCreateInternalCache(
48 kms_connection_config.key_access_token(), cache_entry_lifetime_seconds_);
49 }
50}
51
52std::string FileKeyWrapper::GetEncryptionKeyMetadata(const std::string& data_key,
53 const std::string& master_key_id,
54 bool is_footer_key) {
55 if (kms_client_ == NULL) {
56 throw ParquetException("No KMS client available. See previous errors.");
57 }
58
59 std::string encoded_kek_id;
60 std::string encoded_wrapped_kek;
61 std::string encoded_wrapped_dek;
62 if (!double_wrapping_) {
63 encoded_wrapped_dek = kms_client_->WrapKey(data_key, master_key_id);
64 } else {
65 // Find in cache, or generate KEK for Master Key ID
66 KeyEncryptionKey key_encryption_key = kek_per_master_key_id_->GetOrInsert(
67 master_key_id, [this, master_key_id]() -> KeyEncryptionKey {
68 return this->CreateKeyEncryptionKey(master_key_id);
69 });
70 // Encrypt DEK with KEK
71 const std::string& aad = key_encryption_key.kek_id();
72 const std::string& kek_bytes = key_encryption_key.kek_bytes();
73 encoded_wrapped_dek = internal::EncryptKeyLocally(data_key, kek_bytes, aad);
74 encoded_kek_id = key_encryption_key.encoded_kek_id();
75 encoded_wrapped_kek = key_encryption_key.encoded_wrapped_kek();
76 }
77
78 bool store_key_material_internally = (NULL == key_material_store_);
79
80 std::string serialized_key_material =
81 KeyMaterial::SerializeToJson(is_footer_key, kms_connection_config_.kms_instance_id,
82 kms_connection_config_.kms_instance_url, master_key_id,
83 double_wrapping_, encoded_kek_id, encoded_wrapped_kek,
84 encoded_wrapped_dek, store_key_material_internally);
85
86 // Internal key material storage: key metadata and key material are the same
87 if (store_key_material_internally) {
88 return serialized_key_material;
89 } else {
90 throw ParquetException("External key material store is not supported yet.");
91 }
92}
93
94KeyEncryptionKey FileKeyWrapper::CreateKeyEncryptionKey(
95 const std::string& master_key_id) {
96 std::string kek_bytes(kKeyEncryptionKeyLength, '\0');
97 RandBytes(reinterpret_cast<uint8_t*>(&kek_bytes[0]), kKeyEncryptionKeyLength);
98
99 std::string kek_id(kKeyEncryptionKeyIdLength, '\0');
100 RandBytes(reinterpret_cast<uint8_t*>(&kek_id[0]), kKeyEncryptionKeyIdLength);
101
102 // Encrypt KEK with Master key
103 std::string encoded_wrapped_kek = kms_client_->WrapKey(kek_bytes, master_key_id);
104
105 return KeyEncryptionKey(kek_bytes, kek_id, encoded_wrapped_kek);
106}
107
108} // namespace encryption
109} // namespace parquet