Skip to content

Commit 3e44e82

Browse files
Merge pull request ClickHouse#36724 from ClickHouse/backport/22.3/36487
Backport ClickHouse#36487 to 22.3: Add passphrase for certificates
2 parents 590a165 + d6f48d2 commit 3e44e82

File tree

5 files changed

+89
-74
lines changed

5 files changed

+89
-74
lines changed

src/Server/CertificateReloader.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ void CertificateReloader::tryLoad(const Poco::Util::AbstractConfiguration & conf
8181
{
8282
bool cert_file_changed = cert_file.changeIfModified(std::move(new_cert_path), log);
8383
bool key_file_changed = key_file.changeIfModified(std::move(new_key_path), log);
84+
std::string pass_phrase = config.getString("openSSL.server.privateKeyPassphraseHandler.options.password", "");
8485

8586
if (cert_file_changed || key_file_changed)
8687
{
8788
LOG_DEBUG(log, "Reloading certificate ({}) and key ({}).", cert_file.path, key_file.path);
88-
data.set(std::make_unique<const Data>(cert_file.path, key_file.path));
89+
data.set(std::make_unique<const Data>(cert_file.path, key_file.path, pass_phrase));
8990
LOG_INFO(log, "Reloaded certificate ({}) and key ({}).", cert_file.path, key_file.path);
9091
}
9192

@@ -104,8 +105,8 @@ void CertificateReloader::tryLoad(const Poco::Util::AbstractConfiguration & conf
104105
}
105106

106107

107-
CertificateReloader::Data::Data(std::string cert_path, std::string key_path)
108-
: cert(cert_path), key(/* public key */ "", /* private key */ key_path)
108+
CertificateReloader::Data::Data(std::string cert_path, std::string key_path, std::string pass_phrase)
109+
: cert(cert_path), key(/* public key */ "", /* private key */ key_path, pass_phrase)
109110
{
110111
}
111112

src/Server/CertificateReloader.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,14 @@ class CertificateReloader
5151
int setCertificate(SSL * ssl);
5252

5353
private:
54-
CertificateReloader()
55-
{
56-
}
54+
CertificateReloader() = default;
5755

5856
Poco::Logger * log = &Poco::Logger::get("CertificateReloader");
5957

6058
struct File
6159
{
6260
const char * description;
63-
File(const char * description_) : description(description_) {}
61+
explicit File(const char * description_) : description(description_) {}
6462

6563
std::string path;
6664
std::filesystem::file_time_type modification_time;
@@ -76,7 +74,7 @@ class CertificateReloader
7674
Poco::Crypto::X509Certificate cert;
7775
Poco::Crypto::EVPPKey key;
7876

79-
Data(std::string cert_path, std::string key_path);
77+
Data(std::string cert_path, std::string key_path, std::string pass_phrase);
8078
};
8179

8280
MultiVersion<Data> data;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDPDCCAiQCFBXNOvsLA+dqmX/TkYG9JXdD5m72MA0GCSqGSIb3DQEBCwUAMFox
3+
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
4+
cm5ldCBXaWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmNsaWNraG91c2UwIBcNMjIw
5+
NDIxMTAzNDU1WhgPMjEyMjAzMjgxMDM0NTVaMFkxCzAJBgNVBAYTAkFVMRMwEQYD
6+
VQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBM
7+
dGQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
8+
AQoCggEBAKaXz596N4NC2zZdIqdwZbSYAtNdBCsBVPt5YT9F640aF5zOogPZyxGP
9+
ENyOZwABi/7HhwFbH657xyRvi8lTau8dZL+0tbakyoIn1Tw6j+/3GXTjLduJSy6C
10+
mOf4OzsrFC8mYgU+7p5ijvWVlO9h5NMbLdAPSIB5WSHhmSORH5LgjoK6oMOYdRod
11+
GmfHqSbwPVwy3Li5SXlniCQmJsM0zl64LFbJ/NU+13qETmhBiDgmh0Svi+wzSzqZ
12+
q1PIX92T3k44IXNZbvF7lKbUOS9Xb3BoxA4cDqRcTx4x73xRDwodSmqiuQOC99HI
13+
A0C/tZJ25VNAGjLKukPSHqYscq2PAsUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
14+
IDQwjf/ja3TfOXrz+Gn1eErSKnWS3asjRT9rYWQsy3tzVUkMIcszrG+FqTR16g5H
15+
ZWyuEOi6KIRmda3SYKdLKmtQLrgx6/d/jvH5TQ0LTFZrp6vh0lo3pV+L6fLo1ZRD
16+
V1i8jW/7HHNyqJamUXOjwA0DpPOMkdtwuyV+rJ+2bTG1ZSK33O4Ae2CY5+dad6zy
17+
YI6b1c9flWfDznuNEMH7jDDjKgXwjZGeU53FiuuhHiNyRchsr/B9eIBsom8oykiD
18+
kch4cnAxx2E+m3hLYzupkXHOVQ5CNpVk8PGUCIGcyqDxPt+fOj1WbDQ9laEcfhmV
19+
kR+vHmzOqWZnHU4QeMqDig==
20+
-----END CERTIFICATE-----
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
Proc-Type: 4,ENCRYPTED
3+
DEK-Info: AES-256-CBC,4E14FF586022476CD22AAFB662BB0E40
4+
5+
dpJZKq5k+fMuC7XECfTSRjPeOEl9wNuVtZkcjEWaHN8ky4umND7ARyRyuU1Nk7cy
6+
fpCFlFKOqDfCkT5zVK/fB6pF32wqAI7sqeSuYPfQY0+L77yRdwM6L46WslzVKZYE
7+
lXD1AmqKT/LgF3+eBY5slkAAJo10zYDgKEwnoQVBp31YW2/+6oAGaY/O6x3p7aTG
8+
dw9CP+SFc0o8lPl1lsSovdNXDUiVCftvClog7hwyDv8AhHyGgynw3UJXX8UlyWu+
9+
Zz5zpgrvB2gvDLeoZZ6qjMGvtpEwlYBh4de9ZOsvQUpXEEfkQFtJV0j613OCQune
10+
LoTxKpYV1V/mZX4HPaJ1oC0OJ7XcliAOSS9K49YobTuz7Kg5Wg3bVGo9xRfYDjch
11+
rVeMP4u5RXSGuHL23FPMfK6EqcldrFyRwLaY/IV1Yl6UNUMKAphn/WMtWVuT3TiT
12+
QMCI2VRt7ItwZwwFn5RgyDweWdFf5v3AmN/lOhATDBqosahkPxDZ1VZ6OBPoJLPM
13+
UrDWH/lqrByeEjtAOwr5UsWKwLuJ8qUxQ4TchHwFKOwy6VsrRwMQ3ZWi2govPF9I
14+
W0sfLj5Ulfjx6zHdqnF48a1Elit4JH6inBEWFuj7bmlOotq+PHoeT61zAwW+gnrG
15+
3JTo3XnaE2WwRDpqvKYHWLv/J218rq8PtIaq9gjr55odPfIt8lkJ1XzF4WQ21rIJ
16+
GNWZ3xz4fxpvrKnQyAKGu0ZcdjA1nqs16oiVr+UnJoXmkM5yBCic4fZYwPTSQHYS
17+
ZxwaTzEjfeGxrSeLrN9CgoweucvogOvUjJOBcW/py80du8vWz0YyzMhg3o0YeGME
18+
C+Kts/YWxmyfw4DaWt8RtWCKl85hEmz8RODvkMLGtLzvVoSyLQWqp1NhGIlFtzXs
19+
7sPLulUeyD2avTC/RB/Pu9Nk80c0368BxCoeYbiFWZpaN70SJmCUE5H59J2d0olw
20+
5v2RVjLBi8wqnzoa0+2L8wnG7IQGadS97dj0eBR+JXNtoJhVrurS80RJ6B0bNxdu
21+
gX8otfnJYsZyK5hbEhcQqLdnyGhDEE8YHe7Hv9stWwLAFOfOMzyzC06lFS1eNiw4
22+
FJyXJUhDieb8EqetouAC8dNVXz4Q1zOTlGuAbGoKm5v0U5IhCQap9GUSW5QiUgOQ
23+
AEMs9aGfd91R+IcDf19mZptsQLYA6MGBN6fm+3O2iZImKIbF+ZZo0S6liFFmn6lm
24+
M+diTzaoiqgEkiXOuRhdQUMaiGV8BMZxv8qUH6/vyC3gSueoTio0f9PfASDYfvXD
25+
A3GuI87P6LF1it2UlN6ssFoXTZdfQQZwRmNuqOqw+BJOJHrR6trcXOCZOQ77Qnvd
26+
M5a348gIzluVUkExAPGCsySQWMx4Of5NBF28jEC3+TAwkRqBV2ZHmfGLWnvwaB+A
27+
YUeKtpWblfG1lsrDAdwL2dilU95oby+35sExX7M2dCrL9Y2P5oTCW3u12//ZSLeL
28+
Yhi1Rzol6LAuesZCVF0Zv/YYDhzAckJfT/qXK5B5pz9saswxCUBEpiKlLpVsjOFJ
29+
2bHm8NgOMD5b3cdh1kvts4wZe+giry7LHsn46f+9VqN+gA6XxeVsPyb4uO1KW3SN
30+
-----END RSA PRIVATE KEY-----

tests/integration/test_reload_certificate/test.py

Lines changed: 32 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,18 @@
1313
"configs/second.key",
1414
"configs/ECcert.crt",
1515
"configs/ECcert.key",
16+
"configs/WithPassPhrase.crt",
17+
"configs/WithPassPhrase.key",
1618
"configs/cert.xml",
1719
],
1820
)
21+
PASS_PHRASE_TEMPLATE = """<privateKeyPassphraseHandler>
22+
<name>KeyFileHandler</name>
23+
<options>
24+
<password>{pass_phrase}</password>
25+
</options>
26+
</privateKeyPassphraseHandler>
27+
"""
1928

2029

2130
@pytest.fixture(scope="module", autouse=True)
@@ -27,7 +36,7 @@ def started_cluster():
2736
cluster.shutdown()
2837

2938

30-
def change_config_to_key(name):
39+
def change_config_to_key(name, pass_phrase=""):
3140
"""
3241
* Generate config with certificate/key name from args.
3342
* Reload config.
@@ -48,21 +57,23 @@ def change_config_to_key(name):
4857
<cacheSessions>true</cacheSessions>
4958
<disableProtocols>sslv2,sslv3</disableProtocols>
5059
<preferServerCiphers>true</preferServerCiphers>
60+
{pass_phrase}
5161
</server>
5262
</openSSL>
5363
</clickhouse>
5464
EOF""".format(
55-
cur_name=name
65+
cur_name=name, pass_phrase=pass_phrase
5666
),
5767
]
5868
)
5969
node.query("SYSTEM RELOAD CONFIG")
6070

6171

62-
def test_first_than_second_cert():
63-
"""Consistently set first key and check that only it will be accepted, then repeat same for second key."""
72+
def check_certificate_switch(
73+
first, second, pass_phrase_first="", pass_phrase_second=""
74+
):
6475
# Set first key
65-
change_config_to_key("first")
76+
change_config_to_key(first, pass_phrase_first)
6677

6778
# Command with correct certificate
6879
assert (
@@ -71,9 +82,7 @@ def test_first_than_second_cert():
7182
"curl",
7283
"--silent",
7384
"--cacert",
74-
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(
75-
cur_name="first"
76-
),
85+
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(cur_name=first),
7786
"https://localhost:8443/",
7887
]
7988
)
@@ -90,7 +99,7 @@ def test_first_than_second_cert():
9099
"--silent",
91100
"--cacert",
92101
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(
93-
cur_name="second"
102+
cur_name=second
94103
),
95104
"https://localhost:8443/",
96105
]
@@ -100,7 +109,7 @@ def test_first_than_second_cert():
100109
assert True
101110

102111
# Change to other key
103-
change_config_to_key("second")
112+
change_config_to_key(second, pass_phrase_second)
104113

105114
# Command with correct certificate
106115
assert (
@@ -110,7 +119,7 @@ def test_first_than_second_cert():
110119
"--silent",
111120
"--cacert",
112121
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(
113-
cur_name="second"
122+
cur_name=second
114123
),
115124
"https://localhost:8443/",
116125
]
@@ -126,9 +135,7 @@ def test_first_than_second_cert():
126135
"curl",
127136
"--silent",
128137
"--cacert",
129-
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(
130-
cur_name="first"
131-
),
138+
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(cur_name=first),
132139
"https://localhost:8443/",
133140
]
134141
)
@@ -137,59 +144,18 @@ def test_first_than_second_cert():
137144
assert True
138145

139146

140-
def test_ECcert_reload():
141-
# Set first key
142-
change_config_to_key("first")
147+
def test_first_than_second_cert():
148+
"""Consistently set first key and check that only it will be accepted, then repeat same for second key."""
149+
check_certificate_switch("first", "second")
143150

144-
# Command with correct certificate
145-
assert (
146-
node.exec_in_container(
147-
[
148-
"curl",
149-
"--silent",
150-
"--cacert",
151-
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(
152-
cur_name="first"
153-
),
154-
"https://localhost:8443/",
155-
]
156-
)
157-
== "Ok.\n"
158-
)
159151

160-
# Change to other key
161-
change_config_to_key("ECcert")
152+
def test_ECcert_reload():
153+
"""Check EC certificate"""
154+
check_certificate_switch("first", "ECcert")
162155

163-
# Command with correct certificate
164-
assert (
165-
node.exec_in_container(
166-
[
167-
"curl",
168-
"--silent",
169-
"--cacert",
170-
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(
171-
cur_name="ECcert"
172-
),
173-
"https://localhost:8443/",
174-
]
175-
)
176-
== "Ok.\n"
177-
)
178156

179-
# Command with wrong certificate
180-
# Same as previous
181-
try:
182-
node.exec_in_container(
183-
[
184-
"curl",
185-
"--silent",
186-
"--cacert",
187-
"/etc/clickhouse-server/config.d/{cur_name}.crt".format(
188-
cur_name="first"
189-
),
190-
"https://localhost:8443/",
191-
]
192-
)
193-
assert False
194-
except:
195-
assert True
157+
def test_cert_with_pass_phrase():
158+
pass_phrase_for_cert = PASS_PHRASE_TEMPLATE.format(pass_phrase="test")
159+
check_certificate_switch(
160+
"first", "WithPassPhrase", pass_phrase_second=pass_phrase_for_cert
161+
)

0 commit comments

Comments
 (0)