Skip to content

Commit

Permalink
quic: remove runtime guard and code for legacy cert handling
Browse files Browse the repository at this point in the history
Fixes envoyproxy#36612

Signed-off-by: Greg Greenway <[email protected]>
  • Loading branch information
ggreenway committed Oct 22, 2024
1 parent 5e94ec7 commit ee2e0f2
Show file tree
Hide file tree
Showing 8 changed files with 15 additions and 388 deletions.
3 changes: 3 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ removed_config_or_runtime:
- area: dns
change: |
Removed runtime flag ``envoy.reloadable_features.dns_reresolve_on_eai_again`` and legacy code paths.
- area: quic
change: |
Removed runtime flag ``envoy.restart_features.quic_handle_certs_with_shared_tls_code`` and legacy code paths.
- area: upstream
change: |
Removed runtime flag ``envoy.restart_features.allow_client_socket_creation_failure`` and legacy code paths.
Expand Down
97 changes: 0 additions & 97 deletions source/common/quic/envoy_quic_proof_source.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,45 +29,9 @@ EnvoyQuicProofSource::GetCertChain(const quic::QuicSocketAddress& server_address
return nullptr;
}

if (!res->transport_socket_factory_.handleCertsWithSharedTlsCode()) {
return legacyGetCertChain(*res);
}

return getTlsCertAndFilterChain(*res, hostname, cert_matched_sni).cert_;
}

quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain>
EnvoyQuicProofSource::legacyGetCertChain(const TransportSocketFactoryWithFilterChain& data) {
LegacyCertConfigWithFilterChain res = legacyGetTlsCertConfigAndFilterChain(data);
absl::optional<std::reference_wrapper<const Envoy::Ssl::TlsCertificateConfig>> cert_config_ref =
res.cert_config_;
if (!cert_config_ref.has_value()) {
return nullptr;
}
auto& cert_config = cert_config_ref.value().get();
const std::string& chain_str = cert_config.certificateChain();
std::stringstream pem_stream(chain_str);
std::vector<std::string> chain = quic::CertificateView::LoadPemFromStream(&pem_stream);

quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> cert_chain(
new quic::ProofSource::Chain(chain));
std::string error_details;
bssl::UniquePtr<X509> cert = parseDERCertificate(cert_chain->certs[0], &error_details);
if (cert == nullptr) {
ENVOY_LOG(warn, absl::StrCat("Invalid leaf cert: ", error_details));
return nullptr;
}

bssl::UniquePtr<EVP_PKEY> pub_key(X509_get_pubkey(cert.get()));
int sign_alg = deduceSignatureAlgorithmFromPublicKey(pub_key.get(), &error_details);
if (sign_alg == 0) {
ENVOY_LOG(warn, absl::StrCat("Failed to deduce signature algorithm from public key: ",
error_details));
return nullptr;
}
return cert_chain;
}

void EnvoyQuicProofSource::signPayload(
const quic::QuicSocketAddress& server_address, const quic::QuicSocketAddress& client_address,
const std::string& hostname, uint16_t signature_algorithm, absl::string_view in,
Expand All @@ -79,10 +43,6 @@ void EnvoyQuicProofSource::signPayload(
return;
}

if (!data->transport_socket_factory_.handleCertsWithSharedTlsCode()) {
return legacySignPayload(*data, signature_algorithm, in, std::move(callback));
}

CertWithFilterChain res =
getTlsCertAndFilterChain(*data, hostname, nullptr /* cert_matched_sni */);
if (res.private_key_ == nullptr) {
Expand Down Expand Up @@ -111,47 +71,6 @@ void EnvoyQuicProofSource::signPayload(
std::make_unique<EnvoyQuicProofSourceDetails>(res.filter_chain_.value().get()));
}

void EnvoyQuicProofSource::legacySignPayload(
const TransportSocketFactoryWithFilterChain& data, uint16_t signature_algorithm,
absl::string_view in, std::unique_ptr<quic::ProofSource::SignatureCallback> callback) {
LegacyCertConfigWithFilterChain res = legacyGetTlsCertConfigAndFilterChain(data);
absl::optional<std::reference_wrapper<const Envoy::Ssl::TlsCertificateConfig>> cert_config_ref =
res.cert_config_;
if (!cert_config_ref.has_value()) {
ENVOY_LOG(warn, "No matching filter chain found for handshake.");
callback->Run(false, "", nullptr);
return;
}
auto& cert_config = cert_config_ref.value().get();
// Load private key.
const std::string& pkey = cert_config.privateKey();
std::stringstream pem_str(pkey);
std::unique_ptr<quic::CertificatePrivateKey> pem_key =
quic::CertificatePrivateKey::LoadPemFromStream(&pem_str);
if (pem_key == nullptr) {
ENVOY_LOG(warn, "Failed to load private key.");
callback->Run(false, "", nullptr);
return;
}
// Verify the signature algorithm is as expected.
std::string error_details;
int sign_alg = deduceSignatureAlgorithmFromPublicKey(pem_key->private_key(), &error_details);
if (sign_alg != signature_algorithm) {
ENVOY_LOG(warn,
fmt::format("The signature algorithm {} from the private key is not expected: {}",
sign_alg, error_details));
callback->Run(false, "", nullptr);
return;
}

// Sign.
std::string sig = pem_key->Sign(in, signature_algorithm);
bool success = !sig.empty();
ASSERT(res.filter_chain_.has_value());
callback->Run(success, sig,
std::make_unique<EnvoyQuicProofSourceDetails>(res.filter_chain_.value().get()));
}

EnvoyQuicProofSource::CertWithFilterChain
EnvoyQuicProofSource::getTlsCertAndFilterChain(const TransportSocketFactoryWithFilterChain& data,
const std::string& hostname,
Expand All @@ -165,22 +84,6 @@ EnvoyQuicProofSource::getTlsCertAndFilterChain(const TransportSocketFactoryWithF
return {std::move(cert), std::move(key), data.filter_chain_};
}

EnvoyQuicProofSource::LegacyCertConfigWithFilterChain
EnvoyQuicProofSource::legacyGetTlsCertConfigAndFilterChain(
const TransportSocketFactoryWithFilterChain& data) {

std::vector<std::reference_wrapper<const Envoy::Ssl::TlsCertificateConfig>> tls_cert_configs =
data.transport_socket_factory_.legacyGetTlsCertificates();
if (tls_cert_configs.empty()) {
ENVOY_LOG(warn, "No certificate is configured in transport socket config.");
return {absl::nullopt, absl::nullopt};
}
// Only return the first TLS cert config.
// TODO(danzh) Choose based on supported cipher suites in TLS1.3 CHLO and prefer EC
// certs if supported.
return {tls_cert_configs[0].get(), data.filter_chain_};
}

absl::optional<EnvoyQuicProofSource::TransportSocketFactoryWithFilterChain>
EnvoyQuicProofSource::getTransportSocketAndFilterChain(
const quic::QuicSocketAddress& server_address, const quic::QuicSocketAddress& client_address,
Expand Down
14 changes: 0 additions & 14 deletions source/common/quic/envoy_quic_proof_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ class EnvoyQuicProofSource : public EnvoyQuicProofSourceBase {
const Network::FilterChain& filter_chain_;
};

quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain>
legacyGetCertChain(const TransportSocketFactoryWithFilterChain& data);
void legacySignPayload(const TransportSocketFactoryWithFilterChain& data,
uint16_t signature_algorithm, absl::string_view in,
std::unique_ptr<quic::ProofSource::SignatureCallback> callback);

struct CertWithFilterChain {
quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> cert_;
std::shared_ptr<quic::CertificatePrivateKey> private_key_;
Expand All @@ -55,14 +49,6 @@ class EnvoyQuicProofSource : public EnvoyQuicProofSourceBase {
CertWithFilterChain getTlsCertAndFilterChain(const TransportSocketFactoryWithFilterChain& data,
const std::string& hostname, bool* cert_matched_sni);

struct LegacyCertConfigWithFilterChain {
absl::optional<std::reference_wrapper<const Envoy::Ssl::TlsCertificateConfig>> cert_config_;
absl::optional<std::reference_wrapper<const Network::FilterChain>> filter_chain_;
};

LegacyCertConfigWithFilterChain
legacyGetTlsCertConfigAndFilterChain(const TransportSocketFactoryWithFilterChain& data);

absl::optional<TransportSocketFactoryWithFilterChain>
getTransportSocketAndFilterChain(const quic::QuicSocketAddress& server_address,
const quic::QuicSocketAddress& client_address,
Expand Down
30 changes: 12 additions & 18 deletions source/common/quic/quic_server_transport_socket_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,12 @@ QuicServerTransportSocketFactory::QuicServerTransportSocketFactory(
bool enable_early_data, Stats::Scope& scope, Ssl::ServerContextConfigPtr config,
Envoy::Ssl::ContextManager& manager, const std::vector<std::string>& server_names,
absl::Status& creation_status)
: QuicTransportSocketFactoryBase(scope, "server"),
handle_certs_with_shared_tls_code_(Runtime::runtimeFeatureEnabled(
"envoy.restart_features.quic_handle_certs_with_shared_tls_code")),
manager_(manager), stats_scope_(scope), config_(std::move(config)),
server_names_(server_names), enable_early_data_(enable_early_data) {
if (handle_certs_with_shared_tls_code_) {
auto ctx_or_error = createSslServerContext();
SET_AND_RETURN_IF_NOT_OK(ctx_or_error.status(), creation_status);
ssl_ctx_ = *ctx_or_error;
}
: QuicTransportSocketFactoryBase(scope, "server"), manager_(manager), stats_scope_(scope),
config_(std::move(config)), server_names_(server_names),
enable_early_data_(enable_early_data) {
auto ctx_or_error = createSslServerContext();
SET_AND_RETURN_IF_NOT_OK(ctx_or_error.status(), creation_status);
ssl_ctx_ = *ctx_or_error;
}

QuicServerTransportSocketFactory::~QuicServerTransportSocketFactory() {
Expand Down Expand Up @@ -184,15 +180,13 @@ QuicServerTransportSocketFactory::getTlsCertificateAndKey(absl::string_view sni,
absl::Status QuicServerTransportSocketFactory::onSecretUpdated() {
ENVOY_LOG(debug, "Secret is updated.");

if (handle_certs_with_shared_tls_code_) {
auto ctx_or_error = createSslServerContext();
RETURN_IF_NOT_OK(ctx_or_error.status());
{
absl::WriterMutexLock l(&ssl_ctx_mu_);
std::swap(*ctx_or_error, ssl_ctx_);
}
manager_.removeContext(*ctx_or_error);
auto ctx_or_error = createSslServerContext();
RETURN_IF_NOT_OK(ctx_or_error.status());
{
absl::WriterMutexLock l(&ssl_ctx_mu_);
std::swap(*ctx_or_error, ssl_ctx_);
}
manager_.removeContext(*ctx_or_error);

stats_.context_config_update_by_sds_.inc();
return absl::OkStatus();
Expand Down
3 changes: 0 additions & 3 deletions source/common/quic/quic_server_transport_socket_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ class QuicServerTransportSocketFactory : public Network::DownstreamTransportSock

bool earlyDataEnabled() const { return enable_early_data_; }

bool handleCertsWithSharedTlsCode() const { return handle_certs_with_shared_tls_code_; }

protected:
QuicServerTransportSocketFactory(bool enable_early_data, Stats::Scope& store,
Ssl::ServerContextConfigPtr config,
Expand All @@ -63,7 +61,6 @@ class QuicServerTransportSocketFactory : public Network::DownstreamTransportSock
private:
absl::StatusOr<Envoy::Ssl::ServerContextSharedPtr> createSslServerContext() const;

const bool handle_certs_with_shared_tls_code_;
Envoy::Ssl::ContextManager& manager_;
Stats::Scope& stats_scope_;
Ssl::ServerContextConfigPtr config_;
Expand Down
1 change: 0 additions & 1 deletion source/common/runtime/runtime_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ RUNTIME_GUARD(envoy_reloadable_features_xds_failover_to_primary_enabled);
RUNTIME_GUARD(envoy_reloadable_features_xdstp_path_avoid_colon_encoding);
RUNTIME_GUARD(envoy_restart_features_allow_slot_destroy_on_worker_threads);
RUNTIME_GUARD(envoy_restart_features_fix_dispatcher_approximate_now);
RUNTIME_GUARD(envoy_restart_features_quic_handle_certs_with_shared_tls_code);
RUNTIME_GUARD(envoy_restart_features_use_eds_cache_for_ads);

// Begin false flags. Most of them should come with a TODO to flip true.
Expand Down
Loading

0 comments on commit ee2e0f2

Please sign in to comment.