Skip to content

Commit 4489b13

Browse files
committed
PS-11106 [9.7] Component Percona keyring encrypted file [0, file]
- created component_percona_keyring_encrypted_file based on component_keyring_file - cmake flag: WITH_COMPONENT_PERCONA_KEYRING_ENCRYPTED_FILE
1 parent fe2a875 commit 4489b13

153 files changed

Lines changed: 25740 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Copyright (c) 2021, 2025, Oracle and/or its affiliates.
2+
#
3+
# This program is free software; you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License, version 2.0,
5+
# as published by the Free Software Foundation.
6+
#
7+
# This program is designed to work with certain software (including
8+
# but not limited to OpenSSL) that is licensed under separate terms,
9+
# as designated in a particular file or component or in included license
10+
# documentation. The authors of MySQL hereby grant you an additional
11+
# permission to link the program and your derivative works with the
12+
# separately licensed software that they have either included with
13+
# the program or referenced in the documentation.
14+
#
15+
# This program is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License, version 2.0, for more details.
19+
#
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program; if not, write to the Free Software
22+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23+
24+
IF (NOT DEFINED WITH_COMPONENT_PERCONA_KEYRING_ENCRYPTED_FILE AND
25+
NOT DEFINED WITHOUT_COMPONENT_PERCONA_KEYRING_ENCRYPTED_FILE)
26+
SET(WITH_COMPONENT_PERCONA_KEYRING_ENCRYPTED_FILE 1)
27+
ENDIF()
28+
29+
IF(NOT WITH_COMPONENT_PERCONA_KEYRING_ENCRYPTED_FILE)
30+
RETURN()
31+
ENDIF()
32+
33+
ADD_DEFINITIONS(-DLOG_COMPONENT_TAG="component_percona_keyring_encrypted_file")
34+
35+
INCLUDE_DIRECTORIES(
36+
${CMAKE_CURRENT_SOURCE_DIR}
37+
${BOOST_PATCHES_DIR}
38+
${BOOST_INCLUDE_DIR}
39+
)
40+
41+
42+
SET(PERCONA_KEYRING_ENCRYPTED_FILE_SOURCE
43+
# Encryption handling
44+
service_implementation/keyring_encryption_service_definition.cc
45+
46+
# Generator handling
47+
service_implementation/keyring_generator_service_definition.cc
48+
49+
# Keyring load handling
50+
service_implementation/keyring_load_service_definition.cc
51+
52+
# Keys metadata iterator handling
53+
service_implementation/keyring_keys_metadata_iterator_service_definition.cc
54+
55+
# Metadata query handling
56+
service_implementation/keyring_metadata_query_service_definition.cc
57+
58+
# Reader handling
59+
service_implementation/keyring_reader_service_definition.cc
60+
61+
# Writer handling
62+
service_implementation/keyring_writer_service_definition.cc
63+
64+
# Backend handling
65+
backend/backend.cc
66+
67+
# Config handling
68+
config/config.cc
69+
70+
# Keyring file component handling
71+
percona_keyring_encrypted_file.cc
72+
73+
# Component callbacks
74+
component_callbacks.cc
75+
)
76+
77+
SET(PERCONA_KEYRING_ENCRYPTED_FILE_LIBRARIES
78+
keyring_common
79+
OpenSSL::SSL OpenSSL::Crypto
80+
)
81+
82+
MYSQL_ADD_COMPONENT(percona_keyring_encrypted_file
83+
${PERCONA_KEYRING_ENCRYPTED_FILE_SOURCE}
84+
LINK_LIBRARIES ${PERCONA_KEYRING_ENCRYPTED_FILE_LIBRARIES}
85+
MODULE_ONLY
86+
)
87+
88+
MY_TARGET_LINK_OPTIONS(component_percona_keyring_encrypted_file "${LINK_FLAG_NO_UNDEFINED}")
89+
90+
IF(APPLE)
91+
SET_TARGET_PROPERTIES(component_percona_keyring_encrypted_file PROPERTIES
92+
LINK_FLAGS "-undefined dynamic_lookup")
93+
ENDIF()
94+
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/* Copyright (c) 2021, 2025, Oracle and/or its affiliates.
2+
3+
This program is free software; you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License, version 2.0,
5+
as published by the Free Software Foundation.
6+
7+
This program is designed to work with certain software (including
8+
but not limited to OpenSSL) that is licensed under separate terms,
9+
as designated in a particular file or component or in included license
10+
documentation. The authors of MySQL hereby grant you an additional
11+
permission to link the program and your derivative works with the
12+
separately licensed software that they have either included with
13+
the program or referenced in the documentation.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU General Public License, version 2.0, for more details.
19+
20+
You should have received a copy of the GNU General Public License
21+
along with this program; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23+
24+
#include <fstream>
25+
#include <memory>
26+
27+
#include <components/keyrings/common/data_file/reader.h>
28+
#include <components/keyrings/common/data_file/writer.h>
29+
#include <components/keyrings/common/json_data/json_reader.h>
30+
#include <components/keyrings/common/json_data/json_writer.h>
31+
#include <components/keyrings/common/memstore/cache.h>
32+
#include <components/keyrings/common/memstore/iterator.h>
33+
#include <components/keyrings/common/utils/utils.h>
34+
#include "backend.h"
35+
#include "mysql/components/services/log_builtins.h"
36+
#include "mysqld_error.h"
37+
38+
namespace percona_keyring_encrypted_file {
39+
40+
namespace backend {
41+
42+
using keyring_common::data::Data;
43+
using keyring_common::data_file::File_reader;
44+
using keyring_common::data_file::File_writer;
45+
using keyring_common::json_data::Json_data_extension;
46+
using keyring_common::json_data::Json_reader;
47+
using keyring_common::json_data::Json_writer;
48+
using keyring_common::json_data::output_vector;
49+
using keyring_common::meta::Metadata;
50+
using keyring_common::utils::get_random_data;
51+
52+
Json_data_extension ext;
53+
54+
Keyring_file_backend::Keyring_file_backend(const std::string keyring_file_name,
55+
bool read_only)
56+
: keyring_file_name_(keyring_file_name),
57+
read_only_(read_only),
58+
json_writer_(),
59+
valid_(false) {
60+
if (keyring_file_name_.length() == 0) {
61+
LogComponentErr(ERROR_LEVEL, ER_KEYRING_COMPONENT_KEYRING_FILE_NAME_EMPTY);
62+
return;
63+
}
64+
std::string data;
65+
create_file_if_missing(keyring_file_name_);
66+
{
67+
/* Read the file */
68+
const File_reader file_reader(keyring_file_name_, read_only_, data);
69+
if (!file_reader.valid()) {
70+
LogComponentErr(ERROR_LEVEL,
71+
ER_KEYRING_COMPONENT_KEYRING_FILE_READ_FAILED,
72+
keyring_file_name_.c_str());
73+
return;
74+
}
75+
}
76+
77+
/* It is possible that file is empty and that's ok. */
78+
if (data.length()) {
79+
/* Read JSON data - format check */
80+
const Json_reader json_reader(data);
81+
if (!json_reader.valid()) {
82+
LogComponentErr(ERROR_LEVEL,
83+
ER_KEYRING_COMPONENT_KEYRING_FILE_INVALID_FORMAT,
84+
keyring_file_name_.c_str());
85+
return;
86+
}
87+
/* Cache */
88+
json_writer_.set_data(data);
89+
}
90+
valid_ = true;
91+
}
92+
93+
bool Keyring_file_backend::load_cache(
94+
keyring_common::operations::Keyring_operations<Keyring_file_backend>
95+
&operations) {
96+
if (json_writer_.num_elements() == 0) return false;
97+
const Json_reader json_reader(json_writer_.to_string());
98+
if (!json_reader.valid()) {
99+
LogComponentErr(ERROR_LEVEL,
100+
ER_KEYRING_COMPONENT_KEYRING_FILE_JSON_EXTRACT_FAILED);
101+
return true;
102+
}
103+
if (json_reader.num_elements() != json_writer_.num_elements()) {
104+
LogComponentErr(ERROR_LEVEL,
105+
ER_KEYRING_COMPONENT_KEYRING_FILE_JSON_EXTRACT_FAILED);
106+
return true;
107+
}
108+
for (size_t i = 0; i < json_reader.num_elements(); ++i) {
109+
std::unique_ptr<Json_data_extension> data_ext;
110+
Metadata metadata;
111+
Data data;
112+
if (json_reader.get_element(i, metadata, data, data_ext) == true) {
113+
LogComponentErr(ERROR_LEVEL,
114+
ER_KEYRING_COMPONENT_KEYRING_FILE_KEY_EXTRACT_FAILED);
115+
return true;
116+
}
117+
if (operations.insert(metadata, data) == true) return true;
118+
}
119+
return false;
120+
}
121+
122+
bool Keyring_file_backend::get(const Metadata &, Data &) const {
123+
/* Shouldn't have reached here. */
124+
return true;
125+
}
126+
127+
bool Keyring_file_backend::store(const Metadata &metadata, Data &data) {
128+
if (!metadata.valid() || !data.valid()) return true;
129+
if (json_writer_.add_element(metadata, data, ext)) return true;
130+
if (write_to_file()) {
131+
/* Erase stored entry */
132+
(void)json_writer_.remove_element(metadata, ext);
133+
return true;
134+
}
135+
return false;
136+
}
137+
138+
bool Keyring_file_backend::erase(const Metadata &metadata, Data &data) {
139+
if (!metadata.valid()) return true;
140+
if (json_writer_.remove_element(metadata, ext)) return true;
141+
if (write_to_file()) {
142+
/* Add entry back */
143+
(void)json_writer_.add_element(metadata, data, ext);
144+
return true;
145+
}
146+
return false;
147+
}
148+
149+
bool Keyring_file_backend::generate(const Metadata &metadata, Data &data,
150+
size_t length) {
151+
if (!metadata.valid()) return true;
152+
153+
const std::unique_ptr<unsigned char[]> key(new unsigned char[length]);
154+
if (!key) return true;
155+
if (!get_random_data(key, length)) return true;
156+
157+
pfs_string key_str;
158+
key_str.assign(reinterpret_cast<const char *>(key.get()), length);
159+
data.set_data(keyring_common::data::Sensitive_data{key_str});
160+
161+
return store(metadata, data);
162+
}
163+
164+
bool Keyring_file_backend::write_to_file() {
165+
/* Get JSON string from cache and feed it to file writer */
166+
const File_writer file_writer(keyring_file_name_, json_writer_.to_string());
167+
return !file_writer.valid();
168+
}
169+
170+
void Keyring_file_backend::create_file_if_missing(std::string file_name) {
171+
std::ifstream f(file_name.c_str());
172+
if (f.good())
173+
f.close();
174+
else {
175+
std::ofstream o(file_name.c_str());
176+
o.close();
177+
}
178+
}
179+
180+
} // namespace backend
181+
182+
} // namespace percona_keyring_encrypted_file

0 commit comments

Comments
 (0)