summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Khlebnikov <[email protected]>2025-07-10 08:48:39 +0300
committerrobot-piglet <[email protected]>2025-07-10 09:08:01 +0300
commit8b4cd6b8ec63e0abef8fdcded4487c33b52e0103 (patch)
tree37505c0fa53ae5c8ec52f1f10cee4b90ac648e89
parent6cf220c2123a9d3a02b2086413e29181144c4406 (diff)
yt/core/https: verify server certificate
- **yt/yt/core/test_framework: update and refactor test keys** Present certificate are expired: Issuer: C = CN, ST = Some-State, O = Internet Widgits Pty Ltd Validity Not Before: Nov 1 06:59:16 2014 GMT Not After : Oct 29 06:59:16 2024 GMT Subject: C = CN, ST = Some-State, O = Internet Widgits Pty Ltd Issuer: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 Validity Not Before: Feb 12 19:27:22 2018 GMT Not After : May 13 19:27:22 2018 GMT Subject: CN = cpp.manytask.org Issuer: O = Digital Signature Trust Co., CN = DST Root CA X3 Validity Not Before: Mar 17 16:40:46 2016 GMT Not After : Mar 17 16:40:46 2021 GMT Subject: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 Reuse test certificate from yt/yt/core/bus for "localhost". Issuer: C = RU, ST = Moscow, O = Yandex, CN = CA@localhost Validity Not Before: Jul 13 11:51:17 2023 GMT Not After : Jul 10 11:51:17 2033 GMT Subject: C = RU, ST = Moscow, O = Yandex, CN = localhost Issuer: C = RU, ST = Moscow, O = Yandex, CN = CA@localhost Validity Not Before: Jul 13 11:51:11 2023 GMT Not After : Jul 10 11:51:11 2033 GMT Subject: C = RU, ST = Moscow, O = Yandex, CN = CA@localhost - **yt/core/https: verify server certificate** NYT::NCrypto::TTlsConnection should verify server certificate and hostname. --- * Changelog entry Type: fix Component: misc-server Verify server certificate --- Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/1357 Co-authored-by: yuryalekseev <[email protected]> commit_hash:c88f00ab5fc82507b4b56c25cf25d18904aaec24
-rw-r--r--yt/yt/core/bus/unittests/ssl_ut.cpp31
-rw-r--r--yt/yt/core/bus/unittests/testdata/generate.sh37
-rw-r--r--yt/yt/core/bus/unittests/ya.make16
-rw-r--r--yt/yt/core/crypto/config.cpp2
-rw-r--r--yt/yt/core/crypto/config.h6
-rw-r--r--yt/yt/core/crypto/tls.cpp29
-rw-r--r--yt/yt/core/crypto/unittests/tls_ut.cpp8
-rw-r--r--yt/yt/core/http/unittests/http_ut.cpp38
-rw-r--r--yt/yt/core/rpc/unittests/lib/common.h2
-rw-r--r--yt/yt/core/test_framework/test_key.cpp34
-rw-r--r--yt/yt/core/test_framework/test_key.h118
-rw-r--r--yt/yt/core/test_framework/testdata/ca.pem (renamed from yt/yt/core/bus/unittests/testdata/ca.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/ca_ec.pem (renamed from yt/yt/core/bus/unittests/testdata/ca_ec.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/ca_with_ip_in_san.pem (renamed from yt/yt/core/bus/unittests/testdata/ca_with_ip_in_san.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/cert.pem (renamed from yt/yt/core/bus/unittests/testdata/cert.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/cert_ec.pem (renamed from yt/yt/core/bus/unittests/testdata/cert_ec.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/cert_with_ip_in_san.pem (renamed from yt/yt/core/bus/unittests/testdata/cert_with_ip_in_san.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/key.pem (renamed from yt/yt/core/bus/unittests/testdata/key.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/key_ec.pem (renamed from yt/yt/core/bus/unittests/testdata/key_ec.pem)0
-rw-r--r--yt/yt/core/test_framework/testdata/key_with_ip_in_san.pem (renamed from yt/yt/core/bus/unittests/testdata/key_with_ip_in_san.pem)0
-rw-r--r--yt/yt/core/test_framework/ya.make17
21 files changed, 173 insertions, 165 deletions
diff --git a/yt/yt/core/bus/unittests/ssl_ut.cpp b/yt/yt/core/bus/unittests/ssl_ut.cpp
index 9dbc9935d32..cd3bde3bbaf 100644
--- a/yt/yt/core/bus/unittests/ssl_ut.cpp
+++ b/yt/yt/core/bus/unittests/ssl_ut.cpp
@@ -1,4 +1,5 @@
#include <yt/yt/core/test_framework/framework.h>
+#include <yt/yt/core/test_framework/test_key.h>
#include <yt/yt/core/bus/bus.h>
#include <yt/yt/core/bus/client.h>
@@ -11,8 +12,6 @@
#include <library/cpp/testing/common/env.h>
#include <library/cpp/testing/common/network.h>
-#include <library/cpp/resource/resource.h>
-
namespace NYT::NBus {
namespace {
@@ -32,16 +31,6 @@ TSharedRefArray CreateMessage(int numParts, int partSize = 1)
return TSharedRefArray(std::move(parts), TSharedRefArray::TMoveParts{});
}
-TString CreatePemFile(TStringBuf name)
-{
- auto fileName = TString("testdata_") + name;
- auto output = TFileOutput(fileName);
- output.Write(NResource::Find(TString("/testdata/") + name));
- output.Finish();
-
- return fileName;
-}
-
////////////////////////////////////////////////////////////////////////////////
class TEmptyBusHandler
@@ -85,16 +74,16 @@ public:
AddressWithIpV4 = Format("127.0.0.1:%v", Port);
AddressWithIpV6 = Format("[::1]:%v", Port);
- CACert = TPemBlobConfig::CreateFileReference(CreatePemFile("ca.pem"));
- PrivateKey = TPemBlobConfig::CreateFileReference(CreatePemFile("key.pem"));
- CertificateChain = TPemBlobConfig::CreateFileReference(CreatePemFile("cert.pem"));
- CACertWithIPInSAN = TPemBlobConfig::CreateFileReference(CreatePemFile("ca_with_ip_in_san.pem"));
- PrivateKeyWithIpInSAN = TPemBlobConfig::CreateFileReference(CreatePemFile("key_with_ip_in_san.pem"));
- CertificateChainWithIpInSAN = TPemBlobConfig::CreateFileReference(CreatePemFile("cert_with_ip_in_san.pem"));
+ CACert = CreateTestKeyFile("ca.pem");
+ PrivateKey = CreateTestKeyFile("key.pem");
+ CertificateChain = CreateTestKeyFile("cert.pem");
+ CACertWithIPInSAN = CreateTestKeyFile("ca_with_ip_in_san.pem");
+ PrivateKeyWithIpInSAN = CreateTestKeyFile("key_with_ip_in_san.pem");
+ CertificateChainWithIpInSAN = CreateTestKeyFile("cert_with_ip_in_san.pem");
- CACertEC = TPemBlobConfig::CreateFileReference(CreatePemFile("ca_ec.pem"));
- PrivateKeyEC = TPemBlobConfig::CreateFileReference(CreatePemFile("key_ec.pem"));
- CertificateChainEC = TPemBlobConfig::CreateFileReference(CreatePemFile("cert_ec.pem"));
+ CACertEC = CreateTestKeyFile("ca_ec.pem");
+ PrivateKeyEC = CreateTestKeyFile("key_ec.pem");
+ CertificateChainEC = CreateTestKeyFile("cert_ec.pem");
}
};
diff --git a/yt/yt/core/bus/unittests/testdata/generate.sh b/yt/yt/core/bus/unittests/testdata/generate.sh
new file mode 100644
index 00000000000..816edc383cf
--- /dev/null
+++ b/yt/yt/core/bus/unittests/testdata/generate.sh
@@ -0,0 +1,37 @@
+openssl req -x509 -noenc -newkey rsa:4096 -keyout ca_key.pem -out ca.pem \
+ -days 3650 -subj "/C=RU/L=Moscow/O=Yandex/CN=Localhost CA" \
+ -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
+ -addext "keyUsage=keyCertSign"
+
+openssl req -new -x509 -noenc -newkey rsa:4096 -keyout key.pem -out cert.pem \
+ -CA ca.pem -CAkey ca_key.pem \
+ -days 3650 -subj "/C=RU/L=Moscow/O=Yandex/CN=localhost" \
+ -addext "basicConstraints=critical,CA:FALSE" \
+ -addext "keyUsage=digitalSignature,keyEncipherment" \
+ -addext "extendedKeyUsage=serverAuth,clientAuth"
+
+openssl req -x509 -noenc -newkey rsa:4096 -keyout ca_key_with_ip_in_san.pem -out ca_with_ip_in_san.pem \
+ -days 3650 -subj "/C=RU/L=Moscow/O=Yandex/CN=Localhost CA" \
+ -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
+ -addext "keyUsage=keyCertSign"
+
+openssl req -new -x509 -noenc -newkey rsa:4096 -keyout key_with_ip_in_san.pem -out cert_with_ip_in_san.pem \
+ -CA ca_with_ip_in_san.pem -CAkey ca_key_with_ip_in_san.pem \
+ -days 3650 -subj "/C=RU/L=Moscow/O=Yandex/CN=localhost" \
+ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1" \
+ -addext "basicConstraints=critical,CA:FALSE" \
+ -addext "keyUsage=digitalSignature,keyEncipherment" \
+ -addext "extendedKeyUsage=serverAuth,clientAuth"
+
+openssl req -x509 -noenc -newkey ec:<(openssl ecparam -name prime256v1) -keyout ca_key_ec.pem -out ca_ec.pem \
+ -days 3650 -subj "/C=RU/L=Moscow/O=Yandex/CN=Localhost CA" \
+ -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
+ -addext "keyUsage=keyCertSign"
+
+openssl req -new -x509 -noenc -newkey ec:<(openssl ecparam -name prime256v1) -keyout key_ec.pem -out cert_ec.pem \
+ -CA ca_ec.pem -CAkey ca_key_ec.pem \
+ -days 3650 -subj "/C=RU/L=Moscow/O=Yandex/CN=localhost" \
+ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1" \
+ -addext "basicConstraints=critical,CA:FALSE" \
+ -addext "keyUsage=digitalSignature,keyEncipherment" \
+ -addext "extendedKeyUsage=serverAuth,clientAuth"
diff --git a/yt/yt/core/bus/unittests/ya.make b/yt/yt/core/bus/unittests/ya.make
index 23a14408987..1cef8a8fe84 100644
--- a/yt/yt/core/bus/unittests/ya.make
+++ b/yt/yt/core/bus/unittests/ya.make
@@ -18,22 +18,6 @@ PEERDIR(
library/cpp/resource
)
-EXPLICIT_DATA()
-
-SET(TEST_DATA_DIR ${ARCADIA_ROOT}/yt/yt/core/bus/unittests/testdata)
-
-RESOURCE(
- ${TEST_DATA_DIR}/ca.pem /testdata/ca.pem
- ${TEST_DATA_DIR}/ca_ec.pem /testdata/ca_ec.pem
- ${TEST_DATA_DIR}/ca_with_ip_in_san.pem /testdata/ca_with_ip_in_san.pem
- ${TEST_DATA_DIR}/cert.pem /testdata/cert.pem
- ${TEST_DATA_DIR}/cert_ec.pem /testdata/cert_ec.pem
- ${TEST_DATA_DIR}/cert_with_ip_in_san.pem /testdata/cert_with_ip_in_san.pem
- ${TEST_DATA_DIR}/key.pem /testdata/key.pem
- ${TEST_DATA_DIR}/key_ec.pem /testdata/key_ec.pem
- ${TEST_DATA_DIR}/key_with_ip_in_san.pem /testdata/key_with_ip_in_san.pem
-)
-
REQUIREMENTS(
cpu:4
ram:4
diff --git a/yt/yt/core/crypto/config.cpp b/yt/yt/core/crypto/config.cpp
index 0981b952b9b..333d6a20368 100644
--- a/yt/yt/core/crypto/config.cpp
+++ b/yt/yt/core/crypto/config.cpp
@@ -72,6 +72,8 @@ void TSslContextConfig::Register(TRegistrar registrar)
.Optional();
registrar.Parameter("ssl_configuration_commands", &TThis::SslConfigurationCommands)
.Optional();
+ registrar.Parameter("insecure_skip_verify", &TThis::InsecureSkipVerify)
+ .Default(DefaultInsecureSkipVerify);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/core/crypto/config.h b/yt/yt/core/crypto/config.h
index d5bc6e8cf41..4f47e9af074 100644
--- a/yt/yt/core/crypto/config.h
+++ b/yt/yt/core/crypto/config.h
@@ -29,6 +29,9 @@ DEFINE_REFCOUNTED_TYPE(TPemBlobConfig)
////////////////////////////////////////////////////////////////////////////////
+//! FIXME: Enabled during migration, because this code has always been broken.
+constexpr bool DefaultInsecureSkipVerify = true;
+
struct TSslContextCommand
: public NYTree::TYsonStruct
{
@@ -56,6 +59,9 @@ struct TSslContextConfig
//! Commands for SSL context configuration handled by SSL_CONF_cmd.
std::vector<TSslContextCommandPtr> SslConfigurationCommands;
+ //! Trust everybody, never verify certificate, issue warning - for testing purpose.
+ bool InsecureSkipVerify;
+
REGISTER_YSON_STRUCT(TSslContextConfig);
static void Register(TRegistrar registrar);
diff --git a/yt/yt/core/crypto/tls.cpp b/yt/yt/core/crypto/tls.cpp
index bc9a1838f2c..039566ea935 100644
--- a/yt/yt/core/crypto/tls.cpp
+++ b/yt/yt/core/crypto/tls.cpp
@@ -26,6 +26,7 @@
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
+#include <openssl/x509v3.h>
namespace NYT::NCrypto {
@@ -183,6 +184,8 @@ struct TSslContextImpl
return SSL_get_SSL_CTX(ssl) == ActiveContext_.get();
}
+ DEFINE_BYVAL_RW_BOOLEAN_PROPERTY(InsecureSkipVerify, DefaultInsecureSkipVerify);
+
private:
YT_DECLARE_SPIN_LOCK(NThreading::TReaderWriterSpinLock, Lock_);
TSslCtxPtr Context_;
@@ -227,6 +230,10 @@ public:
void SetHost(const TString& host)
{
+ // Verify hostname in server certificate.
+ SSL_set_hostflags(Ssl_.get(), X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ SSL_set1_host(Ssl_.get(), host.c_str());
+
SSL_set_tlsext_host_name(Ssl_.get(), host.c_str());
}
@@ -234,8 +241,14 @@ public:
{
}
- void StartClient()
+ void StartClient(bool insecureSkipVerify)
{
+ YT_LOG_WARNING_IF(insecureSkipVerify, "Started insecure TLS client connection");
+ if (!insecureSkipVerify) {
+ // Require and verify server certificate.
+ SSL_set_verify(Ssl_.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
+ }
+
SSL_set_connect_state(Ssl_.get());
auto sslResult = SSL_do_handshake(Ssl_.get());
sslResult = SSL_get_error(Ssl_.get(), sslResult);
@@ -626,15 +639,20 @@ public:
TFuture<IConnectionPtr> Dial(const TNetworkAddress& remoteAddress, TDialerContextPtr context) override
{
- return Underlying_->Dial(remoteAddress)
- .Apply(BIND([ctx = Context_, poller = Poller_, context = std::move(context)] (const IConnectionPtr& underlying) -> IConnectionPtr {
+ return Underlying_->Dial(remoteAddress).Apply(BIND(
+ [
+ ctx = Context_,
+ poller = Poller_,
+ context = std::move(context),
+ insecureSkipVerify = Context_->IsInsecureSkipVerify()
+ ] (const IConnectionPtr& underlying) -> IConnectionPtr {
auto connection = New<TTlsConnection>(ctx, poller, underlying);
if (context && context->Host) {
connection->SetHost(*context->Host);
}
- connection->StartClient();
+ connection->StartClient(insecureSkipVerify);
return connection;
- }));
+ }));
}
private:
@@ -742,6 +760,7 @@ void TSslContext::ApplyConfig(const TSslContextConfigPtr& config, TCertificatePa
AddCertificateAuthority(config->CertificateAuthority, pathResolver);
AddCertificateChain(config->CertificateChain, pathResolver);
AddPrivateKey(config->PrivateKey, pathResolver);
+ Impl_->SetInsecureSkipVerify(config->InsecureSkipVerify);
}
void TSslContext::UseBuiltinOpenSslX509Store()
diff --git a/yt/yt/core/crypto/unittests/tls_ut.cpp b/yt/yt/core/crypto/unittests/tls_ut.cpp
index 6281d96b439..0bc8d297de8 100644
--- a/yt/yt/core/crypto/unittests/tls_ut.cpp
+++ b/yt/yt/core/crypto/unittests/tls_ut.cpp
@@ -35,8 +35,9 @@ public:
GrpcLock = NRpc::NGrpc::TDispatcher::Get()->GetLibraryLock();
Context = New<TSslContext>();
- Context->AddCertificate(TestCertificate);
- Context->AddPrivateKey(TestCertificate);
+ Context->AddCertificate(GetTestKeyContent("cert.pem"));
+ Context->AddPrivateKey(GetTestKeyContent("key.pem"));
+ Context->AddCertificateAuthority(GetTestKeyContent("ca.pem"));
Context->Commit();
Poller = CreateThreadPoolPoller(2, "TlsTest");
@@ -114,7 +115,8 @@ TEST(TTlsTestWithoutFixture, LoadCertificateChain)
{
auto grpcLock = NRpc::NGrpc::TDispatcher::Get()->GetLibraryLock();
auto context = New<TSslContext>();
- context->AddCertificateChain(TestCertificateChain);
+ auto certificateChain = GetTestKeyContent("ca.pem") + GetTestKeyContent("cert.pem");
+ context->AddCertificateChain(certificateChain);
context->Commit();
}
diff --git a/yt/yt/core/http/unittests/http_ut.cpp b/yt/yt/core/http/unittests/http_ut.cpp
index 0dea66e0419..ec0f0fd24c6 100644
--- a/yt/yt/core/http/unittests/http_ut.cpp
+++ b/yt/yt/core/http/unittests/http_ut.cpp
@@ -22,6 +22,8 @@
#include <yt/yt/core/net/listener.h>
#include <yt/yt/core/net/mock/dialer.h>
+#include <yt/yt/core/rpc/public.h>
+
#include <yt/yt/core/concurrency/async_stream.h>
#include <yt/yt/core/concurrency/poller.h>
#include <yt/yt/core/concurrency/scheduler.h>
@@ -626,9 +628,9 @@ private:
void SetUp() override
{
TestPort = NTesting::GetFreePort();
- TestUrl = Format("http://localhost:%v", TestPort);
Poller = CreateThreadPoolPoller(4, "HttpTest");
if (!GetParam()) {
+ TestUrl = Format("http://localhost:%v", TestPort);
ServerConfig = New<NHttp::TServerConfig>();
SetupServer(ServerConfig);
Server = NHttp::CreateServer(ServerConfig, Poller);
@@ -637,22 +639,19 @@ private:
SetupClient(clientConfig);
Client = NHttp::CreateClient(clientConfig, Poller);
} else {
+ TestUrl = Format("https://localhost:%v", TestPort);
auto serverConfig = New<NHttps::TServerConfig>();
serverConfig->Credentials = New<NHttps::TServerCredentialsConfig>();
- serverConfig->Credentials->PrivateKey = New<TPemBlobConfig>();
- serverConfig->Credentials->PrivateKey->Value = TestCertificate;
- serverConfig->Credentials->CertificateChain = New<TPemBlobConfig>();
- serverConfig->Credentials->CertificateChain->Value = TestCertificate;
+ serverConfig->Credentials->PrivateKey = CreateTestKeyBlob("key.pem");
+ serverConfig->Credentials->CertificateChain = CreateTestKeyBlob("cert.pem");
SetupServer(serverConfig);
ServerConfig = serverConfig;
Server = NHttps::CreateServer(serverConfig, Poller);
auto clientConfig = New<NHttps::TClientConfig>();
clientConfig->Credentials = New<NHttps::TClientCredentialsConfig>();
- clientConfig->Credentials->PrivateKey = New<TPemBlobConfig>();
- clientConfig->Credentials->PrivateKey->Value = TestCertificate;
- clientConfig->Credentials->CertificateChain = New<TPemBlobConfig>();
- clientConfig->Credentials->CertificateChain->Value = TestCertificate;
+ clientConfig->Credentials->InsecureSkipVerify = false;
+ clientConfig->Credentials->CertificateAuthority = CreateTestKeyBlob("ca.pem");
SetupClient(clientConfig);
Client = NHttps::CreateClient(clientConfig, Poller);
}
@@ -679,6 +678,27 @@ public:
}
};
+TEST_P(THttpServerTest, CertificateValidation)
+{
+ Server->AddHandler("/ok", New<TOKHttpHandler>());
+ Server->Start();
+
+ auto clientConfig = New<NHttps::TClientConfig>();
+ clientConfig->Credentials = New<NHttps::TClientCredentialsConfig>();
+ clientConfig->Credentials->InsecureSkipVerify = false;
+ auto client = NHttps::CreateClient(clientConfig, Poller);
+
+ auto result = WaitFor(client->Get(TestUrl + "/ok"));
+ EXPECT_THROW_WITH_ERROR_CODE(result.ThrowOnError(), NRpc::EErrorCode::SslError);
+ EXPECT_THROW_WITH_SUBSTRING(result.ThrowOnError(), "SSL_do_handshake failed");
+
+ if (GetParam()) {
+ auto result = WaitFor(Client->Get(Format("https://127.0.0.1:%v/ok", TestPort)));
+ EXPECT_THROW_WITH_ERROR_CODE(result.ThrowOnError(), NRpc::EErrorCode::SslError);
+ EXPECT_THROW_WITH_SUBSTRING(result.ThrowOnError(), "SSL_do_handshake failed");
+ }
+}
+
TEST_P(THttpServerTest, SimpleRequest)
{
Server->AddHandler("/ok", New<TOKHttpHandler>());
diff --git a/yt/yt/core/rpc/unittests/lib/common.h b/yt/yt/core/rpc/unittests/lib/common.h
index 050159f078a..ea4f07b18e8 100644
--- a/yt/yt/core/rpc/unittests/lib/common.h
+++ b/yt/yt/core/rpc/unittests/lib/common.h
@@ -499,6 +499,8 @@ public:
{
static auto poller = NConcurrency::CreateThreadPoolPoller(4, "HttpChannelTest");
auto credentials = New<NHttps::TClientCredentialsConfig>();
+ credentials->CertificateAuthority = New<NCrypto::TPemBlobConfig>();
+ credentials->CertificateAuthority->Value = RootCert;
credentials->PrivateKey = New<NCrypto::TPemBlobConfig>();
credentials->PrivateKey->Value = ClientKey;
credentials->CertificateChain = New<NCrypto::TPemBlobConfig>();
diff --git a/yt/yt/core/test_framework/test_key.cpp b/yt/yt/core/test_framework/test_key.cpp
new file mode 100644
index 00000000000..10fb8fa8aa2
--- /dev/null
+++ b/yt/yt/core/test_framework/test_key.cpp
@@ -0,0 +1,34 @@
+#include "test_key.h"
+
+#include <yt/yt/core/crypto/config.h>
+
+#include <library/cpp/resource/resource.h>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+TString GetTestKeyContent(TStringBuf name)
+{
+ return NResource::Find(TString("/testdata/") + name);
+}
+
+NCrypto::TPemBlobConfigPtr CreateTestKeyBlob(TStringBuf name)
+{
+ auto config = New<NCrypto::TPemBlobConfig>();
+ config->Value = GetTestKeyContent(name);
+ return config;
+}
+
+NCrypto::TPemBlobConfigPtr CreateTestKeyFile(TStringBuf name)
+{
+ auto fileName = TString("testdata_") + name;
+ auto output = TFileOutput(fileName);
+ output.Write(GetTestKeyContent(name));
+ output.Finish();
+ return NCrypto::TPemBlobConfig::CreateFileReference(fileName);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/yt/yt/core/test_framework/test_key.h b/yt/yt/core/test_framework/test_key.h
index b26c3e37383..d26d386a214 100644
--- a/yt/yt/core/test_framework/test_key.h
+++ b/yt/yt/core/test_framework/test_key.h
@@ -1,119 +1,15 @@
#pragma once
+#include <yt/yt/core/crypto/public.h>
+
namespace NYT {
-namespace {
-constexpr auto TestCertificate = R"EOF(
------BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+Z2mi8shZ3T0c
-5ItI4KwLfYFXxNr3dmIY+2DS9boD18T46Ccow3wW/15SCcI1BdD/pPBmOTpUWP0b
-B22l4gAOUIWfk/CAHuaD+pHAGMlolAMdscwDZPdaM3XEdu839y2gy6RL4Pxls8No
-sI5h2BTGl3YgjSxA+vKJE+/IXzjajfiKfGHuywPjwPpGl1juOgSaU6zqLf4MlUnq
-Daq7r5V9KtJh8dz46PB6c8ALGNM+dxMJSLMyDvT1/7d9aYBkBvpb3mxOu9agIDNn
-2AZ3AxYwA0ykBLmc5R6V0toqRIjfruvBHqQfcjsFaoKS6O+QjtA/eBTIzGajnyis
-1TfeJxURAgMBAAECggEARANIlq5GpuMCW3m/zy6CBjC0rRdiaBbff7D7qx+fbJP8
-hjTXGBaMEuLxXDikKLCFMWxHexxiG5MWBjunDSQnhPV6ZcBAnmNrUCWHPqkb+ME2
-Q7so9uVv/cZ4AM/DL6iZoeBcNcaOIf4OhSzcD1NSSIX96i7Dagq57AE1G8v30Qlb
-CDybxrkbW8D9TkPh57oH/VNuhGLsFp62BjleYtNqo+aknlnHCj09mFQ+N5cA8DuK
-0CcNFCy4C8oZvg9kVsfdypBr4IR0kXTArqMyjUgXe9KqOzf/GdHR9anWhOzHsy/b
-T1Nb+vF6fDm0o6WHWhfODoF4iklrdwRibAnme+zegQKBgQDzvt4KQLnG5jWxeCLn
-P+QR9q63H98oL3kKToyXPaJVL+I71GtZm4yhYP8KB+bTgrMHPhR5se63cySX2lMJ
-RRKkieeEFuDVKVHulRH39g9fMvvl/f97qwv2mAJhdNuIaIjLSVFjQ8WZ6UWvJczp
-sTAyhIxDGiOV00HaUp3BFFnEOQKBgQDH+gLGIsLlPAwuMpbSyuDJucMk0Jzo3+at
-6h19pu5JpfTWn71Zs0RL45x9BLwbx8oi+vjECjMiaE2OyKC6uObxpXRl5okWQ63E
-XBpbONB+fx2v2h1cuB7iJCJxJ6DPTL70torWtwCp+I7CcIT+J/2SqPhiKipWo0Sk
-R2dxeb1HmQKBgEU8mmXfLOZKzkWzEncNtwNDRy3NZ95KXd+HoHf1kf8Qsvq7xCKY
-BMJygv+ebvr1zVTpVXecC2sg0ewwoBWqATmr0o+6z/K84gEbZxdAVe181gDmvYOr
-eqJ5W3PDdfixeOoF0ZCY17B4isrNuf9HzaEL9au56RHOCI6zmQwXc8hBAoGBAMaI
-h0h+Kk+7FbynrOUJVbHwIrTiB2WLJFF1JGIi4F9ty21omWv8dcmB51KW6MoLx7qC
-v4ahObLnKlifBjNabq1pPe4MufzIpDNV3TTDavqq6KY1PQFYKhEJHsiINzaXUt1Q
-fPY+KQKWKeUQIHjS6wQ3jKCoi/AHl5Yg7anS2v/BAoGBAIi309nwDFJG/2UFSObA
-WC+V6T7qy62UlwFlBwsFCbxf9FmFQfoP6wwbQef35Wx2aDnZaSzoXKn/1jvG5e1e
-TFW7K9oC8JkeA//mnTAVrgkvkaHGZmd27zQYB1U3DsO3fLvEt62PZn8fyEwaczeM
-vOOkHciP4pIhAObg/uiO0V9I
------END PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIDXTCCAkWgAwIBAgIJAM9HYUREwVxFMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
-BAYTAkNOMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
-aWRnaXRzIFB0eSBMdGQwHhcNMTQxMTAxMDY1OTE2WhcNMjQxMDI5MDY1OTE2WjBF
-MQswCQYDVQQGEwJDTjETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
-ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAvmdpovLIWd09HOSLSOCsC32BV8Ta93ZiGPtg0vW6A9fE+OgnKMN8Fv9e
-UgnCNQXQ/6TwZjk6VFj9GwdtpeIADlCFn5PwgB7mg/qRwBjJaJQDHbHMA2T3WjN1
-xHbvN/ctoMukS+D8ZbPDaLCOYdgUxpd2II0sQPryiRPvyF842o34inxh7ssD48D6
-RpdY7joEmlOs6i3+DJVJ6g2qu6+VfSrSYfHc+OjwenPACxjTPncTCUizMg709f+3
-fWmAZAb6W95sTrvWoCAzZ9gGdwMWMANMpAS5nOUeldLaKkSI367rwR6kH3I7BWqC
-kujvkI7QP3gUyMxmo58orNU33icVEQIDAQABo1AwTjAdBgNVHQ4EFgQUJS1vm+Z3
-dm8z29qqdzeI94ZmoqwwHwYDVR0jBBgwFoAUJS1vm+Z3dm8z29qqdzeI94Zmoqww
-DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAl/6TWgvtFCcxue+YmpLz
-gcPckabL2dbgC7uxbIMgFEJUjtmHRpY1Tih8pKqqbdkPWhK2IBvyCqp7L1P5A4ib
-FTKRGogJSaWMjnh/w644yrmsjjo5uoAueqygwha+OAC3gtt6p844hb9KJTjaoMHC
-caaZ6jCAnfjAp2O/3bBpgXCy69UNlWizx8aXajn5a9ah/DrY8wZfI+ESRH3oMd/f
-hecgZLhdTPSkUJi/l6WK9wBuI8mVl+/Gesi8zgz8u+/BRZsxQoP9tBWUjOG396fm
-PCpapHzlchV1N1s0k+poxmoO/GI0GTPcIY3RhU6QJIQ0dtGCLZFVWchJms5u9GBg
-xw==
------END CERTIFICATE-----
-)EOF";
+////////////////////////////////////////////////////////////////////////////////
-constexpr auto TestCertificateChain = R"EOF(
------BEGIN CERTIFICATE-----
-MIIFAzCCA+ugAwIBAgISBLicszxolgnl1s6kGcTJNkfHMA0GCSqGSIb3DQEBCwUA
-MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
-ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODAyMTIxOTI3MjJaFw0x
-ODA1MTMxOTI3MjJaMBsxGTAXBgNVBAMTEGNwcC5tYW55dGFzay5vcmcwggEiMA0G
-CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnVsRLbwms7twqMfR+6MR2x9tPwhcj
-Ux6j3mLEdmd0+1YZBKT8ydTavXKCcbS4e9IW+Gh0fyQcyTuW57lW/saKPJW1jPaE
-K4rIt+NjE9GDb3a4skEyFXmTonNn67w/xvQZs3KcyxjAgyjPbtnVeteGnD/30Xku
-YIGC8ZIqD4s6z6VnTuKV+nObXhyXmWVvNEi5QHXj723jgdfrF1E4FJA5rBaX0yQ8
-7vgwMYr6+w5f+6g7IgYEHsR6vodNGIMLp5h+hhFdslyudxNxA+QiYdWGlJdN2sDZ
-IUMVZJEatn+V/x6ErVfVaGkQRti4FO6+vt6mO5VdrM2Ew0rClWaBDh6jAgMBAAGj
-ggIQMIICDDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
-AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFJWMeys3nYIBTHo1CLw/74WX
-SWioMB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEB
-BGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0
-Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0
-Lm9yZy8wGwYDVR0RBBQwEoIQY3BwLm1hbnl0YXNrLm9yZzCB/gYDVR0gBIH2MIHz
-MAgGBmeBDAECATCB5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6
-Ly9jcHMubGV0c2VuY3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2Vy
-dGlmaWNhdGUgbWF5IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0
-aWVzIGFuZCBvbmx5IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUg
-UG9saWN5IGZvdW5kIGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRv
-cnkvMA0GCSqGSIb3DQEBCwUAA4IBAQCMQSyJB7MiP0rcaBQtN8EoaDwHGMW6dync
-/fjIHXJa8zPhubrGGOPBhNSALrbjfMwLnw+g5lsPzG+Wg8/UiS1uITyKMhJXGQxy
-chdEYiyh3FVIi2tyjGlS6ozUmqANuRDdVEkGchzfKoPtQJbvsT/5LgBX33GgbkPf
-ZYP3+qSnErXYyP007jM3tYl+Zl9oYVxoGSOGtSEnrO7cxkv95I/AuVkIXi8y9Uk/
-qMsJ2qPTEspjA1+GP6u2DRHnuLJUbY8TfB/m5ObgxTbfKqQfuTNISfcIxuAnhaps
-s/R/p7FsgJwed0WSpPqd5JyNxRctGPIuRizgvWQs/5bxvIAWaTif
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
-MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
-DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
-SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
-GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
-q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
-SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
-Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
-a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
-/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
-AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
-CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
-bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
-c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
-VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
-ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
-MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
-Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
-AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
-uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
-wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
-X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
-PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
-KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
------END CERTIFICATE-----
-)EOF";
+TString GetTestKeyContent(TStringBuf name);
+NCrypto::TPemBlobConfigPtr CreateTestKeyBlob(TStringBuf name);
+NCrypto::TPemBlobConfigPtr CreateTestKeyFile(TStringBuf name);
+////////////////////////////////////////////////////////////////////////////////
-} // namespace
} // namespace NYT
diff --git a/yt/yt/core/bus/unittests/testdata/ca.pem b/yt/yt/core/test_framework/testdata/ca.pem
index 6a91723fe4f..6a91723fe4f 100644
--- a/yt/yt/core/bus/unittests/testdata/ca.pem
+++ b/yt/yt/core/test_framework/testdata/ca.pem
diff --git a/yt/yt/core/bus/unittests/testdata/ca_ec.pem b/yt/yt/core/test_framework/testdata/ca_ec.pem
index 73fbb2884d0..73fbb2884d0 100644
--- a/yt/yt/core/bus/unittests/testdata/ca_ec.pem
+++ b/yt/yt/core/test_framework/testdata/ca_ec.pem
diff --git a/yt/yt/core/bus/unittests/testdata/ca_with_ip_in_san.pem b/yt/yt/core/test_framework/testdata/ca_with_ip_in_san.pem
index 4fbccb3c3bc..4fbccb3c3bc 100644
--- a/yt/yt/core/bus/unittests/testdata/ca_with_ip_in_san.pem
+++ b/yt/yt/core/test_framework/testdata/ca_with_ip_in_san.pem
diff --git a/yt/yt/core/bus/unittests/testdata/cert.pem b/yt/yt/core/test_framework/testdata/cert.pem
index ffcb0da681b..ffcb0da681b 100644
--- a/yt/yt/core/bus/unittests/testdata/cert.pem
+++ b/yt/yt/core/test_framework/testdata/cert.pem
diff --git a/yt/yt/core/bus/unittests/testdata/cert_ec.pem b/yt/yt/core/test_framework/testdata/cert_ec.pem
index 27e2b46b02e..27e2b46b02e 100644
--- a/yt/yt/core/bus/unittests/testdata/cert_ec.pem
+++ b/yt/yt/core/test_framework/testdata/cert_ec.pem
diff --git a/yt/yt/core/bus/unittests/testdata/cert_with_ip_in_san.pem b/yt/yt/core/test_framework/testdata/cert_with_ip_in_san.pem
index 0c3b3cb4ae1..0c3b3cb4ae1 100644
--- a/yt/yt/core/bus/unittests/testdata/cert_with_ip_in_san.pem
+++ b/yt/yt/core/test_framework/testdata/cert_with_ip_in_san.pem
diff --git a/yt/yt/core/bus/unittests/testdata/key.pem b/yt/yt/core/test_framework/testdata/key.pem
index 2192f1c96f6..2192f1c96f6 100644
--- a/yt/yt/core/bus/unittests/testdata/key.pem
+++ b/yt/yt/core/test_framework/testdata/key.pem
diff --git a/yt/yt/core/bus/unittests/testdata/key_ec.pem b/yt/yt/core/test_framework/testdata/key_ec.pem
index 8000d1435c4..8000d1435c4 100644
--- a/yt/yt/core/bus/unittests/testdata/key_ec.pem
+++ b/yt/yt/core/test_framework/testdata/key_ec.pem
diff --git a/yt/yt/core/bus/unittests/testdata/key_with_ip_in_san.pem b/yt/yt/core/test_framework/testdata/key_with_ip_in_san.pem
index 2e314b8f7b4..2e314b8f7b4 100644
--- a/yt/yt/core/bus/unittests/testdata/key_with_ip_in_san.pem
+++ b/yt/yt/core/test_framework/testdata/key_with_ip_in_san.pem
diff --git a/yt/yt/core/test_framework/ya.make b/yt/yt/core/test_framework/ya.make
index 72ece8e1f47..34bbe479993 100644
--- a/yt/yt/core/test_framework/ya.make
+++ b/yt/yt/core/test_framework/ya.make
@@ -7,6 +7,7 @@ SRCS(
test_memory_tracker.cpp
test_proxy_service.cpp
test_server_host.cpp
+ test_key.cpp
GLOBAL framework.cpp
)
@@ -19,4 +20,20 @@ PEERDIR(
yt/yt/library/profiling/solomon
)
+EXPLICIT_DATA()
+
+SET(TEST_DATA_DIR ${ARCADIA_ROOT}/yt/yt/core/test_framework/testdata)
+
+RESOURCE(
+ ${TEST_DATA_DIR}/ca.pem /testdata/ca.pem
+ ${TEST_DATA_DIR}/ca_ec.pem /testdata/ca_ec.pem
+ ${TEST_DATA_DIR}/ca_with_ip_in_san.pem /testdata/ca_with_ip_in_san.pem
+ ${TEST_DATA_DIR}/cert.pem /testdata/cert.pem
+ ${TEST_DATA_DIR}/cert_ec.pem /testdata/cert_ec.pem
+ ${TEST_DATA_DIR}/cert_with_ip_in_san.pem /testdata/cert_with_ip_in_san.pem
+ ${TEST_DATA_DIR}/key.pem /testdata/key.pem
+ ${TEST_DATA_DIR}/key_ec.pem /testdata/key_ec.pem
+ ${TEST_DATA_DIR}/key_with_ip_in_san.pem /testdata/key_with_ip_in_san.pem
+)
+
END()