Skip to content

Commit

Permalink
feat core: support for TLS cert chains
Browse files Browse the repository at this point in the history
Fixes: #823, #757

Tests: протестировано CI

Pull Request resolved: #758
commit_hash:fa6d18b9e0e85521ae1a81e8afadf6ac5735b6f7
  • Loading branch information
aklyuchev86 authored and apolukhin committed Jan 9, 2025
1 parent f44b36e commit f9dd97a
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 28 deletions.
2 changes: 1 addition & 1 deletion core/include/userver/engine/io/tls_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class [[nodiscard]] TlsWrapper final : public RwBase {
/// Starts a TLS server on an opened socket
static TlsWrapper StartTlsServer(
Socket&& socket,
const crypto::Certificate& cert,
const crypto::CertificatesChain& cert_chain,
const crypto::PrivateKey& key,
Deadline deadline,
const std::vector<crypto::Certificate>& extra_cert_authorities = {}
Expand Down
2 changes: 1 addition & 1 deletion core/include/userver/server/component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ namespace components {
/// task_processor | task processor to process incoming requests | -
/// backlog | max count of new connections pending acceptance | 1024
/// tls.ca | paths to TLS CAs for client authentication | -
/// tls.cert | path to TLS server certificate | -
/// tls.cert | path to TLS server certificate or certificate chain | -
/// tls.private-key | path to TLS server certificate private key | -
/// tls.private-key-passphrase-name | passphrase name located in secdist's "passphrases" section | -
/// handler-defaults.max_url_size | max path/URL size or empty to not limit | 8192
Expand Down
2 changes: 1 addition & 1 deletion core/src/clients/http/client_crl_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ struct TlsServer {

auto tls_server = engine::io::TlsWrapper::StartTlsServer(
std::move(socket),
crypto::Certificate::LoadFromString(kServerCertificate),
crypto::LoadCertficatesChainFromString(kServerCertificate),
crypto::PrivateKey::LoadFromString(kRevokedServerPrivateKey),
deadline,
cas
Expand Down
25 changes: 23 additions & 2 deletions core/src/engine/io/tls_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ TlsWrapper TlsWrapper::StartTlsClient(

TlsWrapper TlsWrapper::StartTlsServer(
Socket&& socket,
const crypto::Certificate& cert,
const crypto::CertificatesChain& cert_chain,
const crypto::PrivateKey& key,
Deadline deadline,
const std::vector<crypto::Certificate>& extra_cert_authorities
Expand All @@ -513,10 +513,31 @@ TlsWrapper TlsWrapper::StartTlsServer(
LOG_INFO() << "Client SSL cert will not be verified";
}

if (1 != SSL_CTX_use_certificate(ssl_ctx.get(), cert.GetNative())) {
if (cert_chain.empty()) {
throw TlsException(crypto::FormatSslError("Empty certificate chain provided"));
}

if (1 != SSL_CTX_use_certificate(ssl_ctx.get(), cert_chain.begin()->GetNative())) {
throw TlsException(crypto::FormatSslError("Failed to set up server TLS wrapper: SSL_CTX_use_certificate"));
}

if (cert_chain.size() > 1) {
auto cert_it = std::next(cert_chain.begin());
for (; cert_it != cert_chain.end(); ++cert_it) {
// cast in openssl1.0 macro expansion
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
if (SSL_CTX_add_extra_chain_cert(ssl_ctx.get(), cert_it->GetNative()) <= 0) {
throw TlsException(
crypto::FormatSslError("Failed to set up server TLS wrapper: SSL_CTX_add_extra_chain_cert")
);
}

// After SSL_CTX_add_extra_chain_cert we should not free the cert
const auto ret = X509_up_ref(cert_it->GetNative());
UASSERT(ret == 1);
}
}

if (1 != SSL_CTX_use_PrivateKey(ssl_ctx.get(), key.GetNative())) {
throw TlsException(crypto::FormatSslError("Failed to set up server TLS wrapper: SSL_CTX_use_PrivateKey"));
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/engine/io/tls_wrapper_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ constexpr auto kDeadlineMaxTime = std::chrono::seconds{60};
[&reading, deadline](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
deadline
);
Expand Down Expand Up @@ -141,7 +141,7 @@ BENCHMARK(tls_write_all_buffered)->RangeMultiplier(2)->Range(1 << 6, 1 << 12)->U
[&reading, deadline](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
deadline
);
Expand Down
110 changes: 93 additions & 17 deletions core/src/engine/io/tls_wrapper_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,82 @@ Z49kghXJ5KAS4jOB6SxClxbR5Tpc1E3khduX6aGau1VOkgPJxfdqHHqsyUc1RH/Z
v2R63aFo/UfQSQ4dhC0o2Vy74DyLwnO3pH8wudfBJ8/LX/Uz/A==
-----END CERTIFICATE-----)";

// Certificates for testing were generated via the following command:
// openssl req -x509 -sha256 -nodes -newkey rsa:2048
// -days 3650 -subj '/CN=tlswrapper_test_other'
// -keyout testing_priv.key -out testing_cert.crt
//
// intermediate certificate was generated by
// openssl x509 -req -in <(openssl req -new -key testing_priv.key -subj "/CN=intermediate_test") -CA testing_cert.crt
// -CAkey testing_priv.key -CAcreateserial -out intermediate_cert.crt -days 1825 -sha256 full chain generated by cat
// intermediate_cert.crt testing_cert.crt > fullchain.crt NOTE: Ubuntu 20.04 requires RSA of at least 2048 length

constexpr auto chain_private_key = R"(-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtQd5O3Zow01ZC
vbuUv9s7jm48KwSmVje+k887w/h5fNR+lah44owNw6P/7RQ4uMmgGPxtIxdkZNvI
p5TjBcqMWK3OP4ReG3c/Ak+A1b6NOC5KborngfO0K9uzV/9Pa53UfcWoqSyqcc91
G7zzDGuYHOs3FKk53fTNaRUYd5UMX8zZkTdTPpOJWDWZHIOYr6sgt7Py+NtVp70D
zS4/qIHD68oTjTYwp8DCQ3qljoTvSoYudKC+Xnm9lXnc2INJXmxYUFZBkq5vMczY
0mNFw4PNyEQyfyEOseaPFrAF/AWIiQWmYfe6M4gitc9Ct4cu7+VdLqDN3/D2bsbG
ceKzCbZzAgMBAAECggEAO56m+UyYeqS+0kin/A/pSR1CIcJL31Fb7WC/tzlAj828
8bJePvr2ZuYj0TWr97je6RCwDH4+1nU+jFXejiC4CoOZi5ef3SJmbnBFG3hyEfZ7
N3HCqte1HRLaj2SAnrvRnAWLtvZAQIbZdNsOsjRb8gRBjLq3YQpX6zd14u2DhLYB
vQxVfONtOGeUx/UUiss2MpJfrqoUoGVb+/onG1yAEbtWOs0Ig/dljopvcgkeCz9J
mB2MD5yv5a7sLBOcgyTpvE6ODgXzs+ZtS3TybGS+ld2rFrDlcInY1zXSP5iaW6Z5
lSUeolx5w1lVjRcc9WdybEOYpkV76EqX4v9XbGIxAQKBgQDUUX36l3YQDkBgZOvb
FnQaGUUAUiRenJedW5FMKWxBh2tXNUIa3aw7GtPhf4/8JLCaFrYF4WLkDfb0CfSY
wbunEjqa1Fa/CFmuagBHg6ClIiGX2/p9t2iQEEMZA+qjeAeFgfYy86e4t1oRn6iA
EED7j/7szqZvWrHtcv4Z9HP0YwKBgQDQ5xY0i+ouWJ7nGWEZ2A2arixL6KSAPIlm
NAPoYZGTWYXl259vCrJmnqCRpqtCLkCwhtFbDewPtf1PTWYLJUUWcjdljpuKfPpu
sIseA3CSRIfggW1X3A/txtscWZQhctie+jU9BFqiSaG/Mto+GdH4BFT4oUFKmfA/
J2rEKVyqsQKBgDoTCEhxAWQm4cj8Ed9dZuh0nQEXdsdCQd5S241fjzLlXaD++lPq
6l9IWUhG4hVv27ZqG+PD4I7Mmw3pYzQdWby7KbiL+CZMnGsup2DoShqhGVs2Wm/k
qP8u04uWHKoV/Mix4avSJcBKtqI3b5mH2J52pp4TcEbpId33JDXpPYZNAoGBAMif
5jd41+LCwXj4asTDNe2DsI8GUlXFzb8V3VrjuUdmBq4GCkw+Xa8oUNUQ2BCrEv11
vMJR0JAWG7x5fLLfjEZOUt154+9Qr8J2UmT0sLwIjOYT5ssmUTXucKf9b8Hf5iJn
8ZE0CUcqp+hUEjzp1zj2EBTn6SiYRp6gYG0bvB9BAoGBANLAq1ZJw7JsZ6rCvduA
GgdtFZePPol1/iQX7YXgP0jP1i3gqRKa7M621u8Hunl5BAqQ/1fu/7qAExzDcmkn
OmJhJDUFdNcQ6+4LCpj5JVed/J1Tnh8vUaRbYV+9l0y5WolcuAY+hfJuB4K0mUXL
11/L+DCO5OYM9ud/kl+ttDWj
-----END PRIVATE KEY-----)";

constexpr auto cert_chain = R"(-----BEGIN CERTIFICATE-----
MIIC5TCCAc2gAwIBAgIUEAEQSbPfQymprdTsER15SJz+eaowDQYJKoZIhvcNAQEL
BQAwGjEYMBYGA1UEAwwPdGxzd3JhcHBlcl90ZXN0MB4XDTI1MDEwNDExMjgzMFoX
DTMwMDEwMzExMjgzMFowHDEaMBgGA1UEAwwRaW50ZXJtZWRpYXRlX3Rlc3QwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtQd5O3Zow01ZCvbuUv9s7jm48
KwSmVje+k887w/h5fNR+lah44owNw6P/7RQ4uMmgGPxtIxdkZNvIp5TjBcqMWK3O
P4ReG3c/Ak+A1b6NOC5KborngfO0K9uzV/9Pa53UfcWoqSyqcc91G7zzDGuYHOs3
FKk53fTNaRUYd5UMX8zZkTdTPpOJWDWZHIOYr6sgt7Py+NtVp70DzS4/qIHD68oT
jTYwp8DCQ3qljoTvSoYudKC+Xnm9lXnc2INJXmxYUFZBkq5vMczY0mNFw4PNyEQy
fyEOseaPFrAF/AWIiQWmYfe6M4gitc9Ct4cu7+VdLqDN3/D2bsbGceKzCbZzAgMB
AAGjITAfMB0GA1UdDgQWBBQBq2+OTbGp4TvtWVkYe4LfWybT+jANBgkqhkiG9w0B
AQsFAAOCAQEAYaebsazdrABtiJF+FmLwmX9RJkLBxf4cxuSHzhieNeOSyVecCAmF
eJ1/4VKSWpDKfIk6pG8CWFO3EUCkytCof/idlbTqoYZ/WckzsYGrzxPTGSLw1Oen
/vnDFEE6cnIqJEB6v3LzfQrLBXr57+I7/SvpSGin9DuxfTQplNAt8lxDuiwJZz0+
IrzRwLB9HzXo8xvG9v88L35SW8SwWds6R5hjpZ928qOP5JbosI6ccQ6fgu8hSy5D
H9ZIE4FyGrLTbA1reSjT43yBYBzX0H4JsQnzGjbraGk5HYLFETVKbCYurYo+4Rl5
sYDUeR5wwfcKZCH43JERoG4DVI7yIKIzZQ==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDFTCCAf2gAwIBAgIUXOIkjRBGF8HhB43My6tlrFcOoJcwDQYJKoZIhvcNAQEL
BQAwGjEYMBYGA1UEAwwPdGxzd3JhcHBlcl90ZXN0MB4XDTI1MDEwNDExMTMxMVoX
DTM1MDEwMjExMTMxMVowGjEYMBYGA1UEAwwPdGxzd3JhcHBlcl90ZXN0MIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArUHeTt2aMNNWQr27lL/bO45uPCsE
plY3vpPPO8P4eXzUfpWoeOKMDcOj/+0UOLjJoBj8bSMXZGTbyKeU4wXKjFitzj+E
Xht3PwJPgNW+jTguSm6K54HztCvbs1f/T2ud1H3FqKksqnHPdRu88wxrmBzrNxSp
Od30zWkVGHeVDF/M2ZE3Uz6TiVg1mRyDmK+rILez8vjbVae9A80uP6iBw+vKE402
MKfAwkN6pY6E70qGLnSgvl55vZV53NiDSV5sWFBWQZKubzHM2NJjRcODzchEMn8h
DrHmjxawBfwFiIkFpmH3ujOIIrXPQreHLu/lXS6gzd/w9m7GxnHiswm2cwIDAQAB
o1MwUTAdBgNVHQ4EFgQUAatvjk2xqeE77VlZGHuC31sm0/owHwYDVR0jBBgwFoAU
Aatvjk2xqeE77VlZGHuC31sm0/owDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B
AQsFAAOCAQEAOs+WfsO7k2zZS3CMAOHwxZzXy9PvdCzZFzJfjkKRh22zjZ1dmf8f
dlMGPqAENae3zuUd4ErFztNg6bGKW66j5JCQvfdqrj2XUUpTuJJWVcsvtxamDFz8
2h2+ky35xop4GLv3E9BPZvXSZ4wwiFbehI79tPwz3Qn4rsaowxM+bhMIgf+Wt4hS
nyLZGLR3MYH5wY6kCErZobxlXukvxS/+RTobvyo/9wbKjx1qaOXfuMKsFK3hpYzq
uwddqXEoNvE0VFCib7dsBnBUEeKhnVioD0vpDfvrCLNTm8VOg3xVz902WNnpgSdu
ud5lWYZNZ6ygIOvwFz1VST30jT4Lj3Bmrg==
-----END CERTIFICATE-----)";
constexpr auto kShortTimeout = std::chrono::milliseconds{10};

} // namespace
Expand All @@ -158,8 +234,8 @@ UTEST(TlsWrapper, InitListSmall) {
[deadline, kDataA, kDataB, kDataC, kDataD](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::PrivateKey::LoadFromString(key),
crypto::LoadCertficatesChainFromString(cert_chain),
crypto::PrivateKey::LoadFromString(chain_private_key),
deadline
);
if (tls_server.WriteAll({kDataA, kDataB, kDataC, kDataD}, deadline) !=
Expand Down Expand Up @@ -198,7 +274,7 @@ UTEST(TlsWrapper, InitListLarge) {
[deadline, kDataA, kDataB, kDataC, kDataD](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
deadline
);
Expand Down Expand Up @@ -234,7 +310,7 @@ UTEST(TlsWrapper, InitListSmallThenLarge) {
[deadline, kDataSmall, kDataLarge](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
deadline
);
Expand Down Expand Up @@ -266,7 +342,7 @@ UTEST_MT(TlsWrapper, Smoke, 2) {
try {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
test_deadline
);
Expand Down Expand Up @@ -313,7 +389,7 @@ UTEST_MT(TlsWrapper, DocTest, 2) {
[deadline](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
deadline
);
Expand Down Expand Up @@ -345,7 +421,7 @@ UTEST(TlsWrapper, Move) {
try {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
test_deadline
);
Expand Down Expand Up @@ -395,7 +471,7 @@ UTEST(TlsWrapper, ConnectTimeout) {
EXPECT_THROW(
static_cast<void>(io::TlsWrapper::StartTlsServer(
std::move(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
Deadline::FromDuration(kShortTimeout)
)),
Expand All @@ -414,7 +490,7 @@ UTEST_MT(TlsWrapper, IoTimeout, 2) {
[test_deadline, &timeout_happened](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
test_deadline
);
Expand Down Expand Up @@ -451,7 +527,7 @@ UTEST(TlsWrapper, Cancel) {
[test_deadline](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
test_deadline
);
Expand All @@ -478,7 +554,7 @@ UTEST_MT(TlsWrapper, CertKeyMismatch, 2) {
UEXPECT_THROW(
static_cast<void>(io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(other_key),
test_deadline
)),
Expand All @@ -505,7 +581,7 @@ UTEST_MT(TlsWrapper, NonTlsClient, 2) {
UEXPECT_THROW(
static_cast<void>(io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(other_key),
test_deadline
)),
Expand Down Expand Up @@ -546,7 +622,7 @@ UTEST_MT(TlsWrapper, DoubleSmoke, 4) {
[test_deadline](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
test_deadline
);
Expand All @@ -567,7 +643,7 @@ UTEST_MT(TlsWrapper, DoubleSmoke, 4) {
[test_deadline](auto&& server) {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(other_cert),
crypto::LoadCertficatesChainFromString(other_cert),
crypto::PrivateKey::LoadFromString(other_key),
test_deadline
);
Expand Down Expand Up @@ -620,7 +696,7 @@ UTEST(TlsWrapper, InvalidSocket) {
UEXPECT_THROW(static_cast<void>(io::TlsWrapper::StartTlsClient({}, {}, test_deadline)), io::TlsException);
UEXPECT_THROW(
static_cast<void>(io::TlsWrapper::StartTlsServer(
{}, crypto::Certificate::LoadFromString(cert), crypto::PrivateKey::LoadFromString(key), test_deadline
{}, crypto::LoadCertficatesChainFromString(cert), crypto::PrivateKey::LoadFromString(key), test_deadline
)),
io::TlsException
);
Expand All @@ -637,7 +713,7 @@ UTEST(TlsWrapper, PeerShutdown) {
try {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
test_deadline
);
Expand Down Expand Up @@ -679,7 +755,7 @@ UTEST(TlsWrapper, PeerDisconnect) {
try {
auto tls_server = io::TlsWrapper::StartTlsServer(
std::forward<decltype(server)>(server),
crypto::Certificate::LoadFromString(cert),
crypto::LoadCertficatesChainFromString(cert),
crypto::PrivateKey::LoadFromString(key),
test_deadline
);
Expand Down
2 changes: 1 addition & 1 deletion core/src/server/component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ additionalProperties: false
description: path to TLS CA
cert:
type: string
description: path to TLS certificate
description: path to TLS certificate chain
private-key:
type: string
description: path to TLS certificate private key
Expand Down
2 changes: 1 addition & 1 deletion core/src/server/net/listener_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ PortConfig Parse(const yaml_config::YamlConfig& value, formats::parse::To<PortCo
}
if (!cert_path.empty()) {
auto contents = fs::blocking::ReadFileContents(cert_path);
config.tls_cert = crypto::Certificate::LoadFromString(contents);
config.tls_cert_chain = crypto::LoadCertficatesChainFromString(contents);
config.tls = true;
}
if (!pkey_path.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/server/net/listener_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct PortConfig {
std::string address = "::";

bool tls{false};
crypto::Certificate tls_cert;
crypto::CertificatesChain tls_cert_chain;
std::string tls_private_key_path;
std::string tls_private_key_passphrase_name;
crypto::PrivateKey tls_private_key;
Expand Down
2 changes: 1 addition & 1 deletion core/src/server/net/listener_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void ListenerImpl::ProcessConnection(engine::io::Socket peer_socket, const PortC
if (port_config.tls) {
socket = std::make_unique<engine::io::TlsWrapper>(engine::io::TlsWrapper::StartTlsServer(
std::move(peer_socket),
port_config.tls_cert,
port_config.tls_cert_chain,
port_config.tls_private_key,
{},
port_config.tls_certificate_authorities
Expand Down
10 changes: 10 additions & 0 deletions universal/include/userver/crypto/certificate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/// @file userver/crypto/certificate.hpp
/// @brief @copybrief crypto::Certificate

#include <list>
#include <memory>
#include <optional>
#include <string>
Expand Down Expand Up @@ -44,6 +45,15 @@ class Certificate {
std::shared_ptr<NativeType> cert_;
};

using CertificatesChain = std::list<Certificate>;

/// Accepts a string that contains a chain of certificates (primary and intermediate), checks that
/// it's correct, loads it into OpenSSL structures and returns as a
/// list of 'Certificate's.
///
/// @throw crypto::KeyParseError if failed to load the certificate.
CertificatesChain LoadCertficatesChainFromString(std::string_view chain);

} // namespace crypto

USERVER_NAMESPACE_END
Loading

0 comments on commit f9dd97a

Please sign in to comment.