diff --git a/test/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD b/test/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD index a3f4decb56851..2110a467bc779 100644 --- a/test/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD +++ b/test/extensions/transport_sockets/tls/cert_validator/spiffe/BUILD @@ -1,14 +1,17 @@ load( "//bazel:envoy_build_system.bzl", - "envoy_cc_test", "envoy_package", ) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) licenses(["notice"]) # Apache 2 envoy_package() -envoy_cc_test( +envoy_extension_cc_test( name = "spiffe_validator_test", srcs = [ "spiffe_validator_test.cc", @@ -16,6 +19,7 @@ envoy_cc_test( data = [ "//test/extensions/transport_sockets/tls/test_data:certs", ], + extension_name = "envoy.tls.cert_validator.spiffe", deps = [ "//source/extensions/transport_sockets/tls/cert_validator/spiffe:config", "//test/extensions/transport_sockets/tls:ssl_test_utils", @@ -26,3 +30,20 @@ envoy_cc_test( "//test/test_common:utility_lib", ], ) + +envoy_extension_cc_test( + name = "spiffe_validator_integration_test", + srcs = [ + "spiffe_validator_integration_test.cc", + "spiffe_validator_integration_test.h", + ], + data = [ + "//test/config/integration/certs", + "//test/extensions/transport_sockets/tls/test_data:certs", + ], + extension_name = "envoy.tls.cert_validator.spiffe", + deps = [ + "//source/extensions/transport_sockets/tls/cert_validator/spiffe:config", + "//test/integration:http_integration_lib", + ], +) diff --git a/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_integration_test.cc b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_integration_test.cc new file mode 100644 index 0000000000000..dd314b70a81b1 --- /dev/null +++ b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_integration_test.cc @@ -0,0 +1,140 @@ +#include "spiffe_validator_integration_test.h" + +#include + +#include "extensions/transport_sockets/tls/context_manager_impl.h" + +#include "test/integration/integration.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Ssl { + +void SslSPIFFECertValidatorIntegrationTest::initialize() { + config_helper_.addSslConfig( + ConfigHelper::ServerSslOptions().setRsaCert(true).setTlsV13(true).setCustomValidatorConfig( + custom_validator_config_)); + HttpIntegrationTest::initialize(); + + context_manager_ = + std::make_unique(timeSystem()); + registerTestServerPorts({"http"}); +} + +void SslSPIFFECertValidatorIntegrationTest::TearDown() { + HttpIntegrationTest::cleanupUpstreamAndDownstream(); + codec_client_.reset(); + context_manager_.reset(); +} + +Network::ClientConnectionPtr SslSPIFFECertValidatorIntegrationTest::makeSslClientConnection( + const ClientSslTransportOptions& options) { + ClientSslTransportOptions modified_options{options}; + modified_options.setTlsVersion(tls_version_); + + Network::Address::InstanceConstSharedPtr address = getSslAddress(version_, lookupPort("http")); + auto client_transport_socket_factory_ptr = + createClientSslTransportSocketFactory(modified_options, *context_manager_, *api_); + return dispatcher_->createClientConnection( + address, Network::Address::InstanceConstSharedPtr(), + client_transport_socket_factory_ptr->createTransportSocket({}), nullptr); +} + +void SslSPIFFECertValidatorIntegrationTest::checkVerifyErrorCouter(uint64_t value) { + Stats::CounterSharedPtr counter = + test_server_->counter(listenerStatPrefix("ssl.fail_verify_error")); + EXPECT_EQ(value, counter->value()); + counter->reset(); +} + +INSTANTIATE_TEST_SUITE_P( + IpVersionsClientVersions, SslSPIFFECertValidatorIntegrationTest, + testing::Combine( + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + testing::Values(envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2, + envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_3)), + SslSPIFFECertValidatorIntegrationTest::ipClientVersionTestParamsToString); + +// clientcert.pem's san is "spiffe://lyft.com/frontend-team" so it should be accepted. +TEST_P(SslSPIFFECertValidatorIntegrationTest, ServerRsaSPIFFEValidatorAccepted) { + auto typed_conf = new envoy::config::core::v3::TypedExtensionConfig(); + TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( +name: envoy.tls.cert_validator.spiffe +typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig + trust_domains: + - name: lyft.com + trust_bundle: + filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" + )EOF"), + *typed_conf); + + custom_validator_config_ = typed_conf; + ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { + return makeSslClientConnection({}); + }; + testRouterRequestAndResponseWithBody(1024, 512, false, false, &creator); + checkVerifyErrorCouter(0); +} + +// clientcert.pem's san is "spiffe://lyft.com/frontend-team" so it should be rejected. +TEST_P(SslSPIFFECertValidatorIntegrationTest, ServerRsaSPIFFEValidatorRejected1) { + auto typed_conf = new envoy::config::core::v3::TypedExtensionConfig(); + TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( +name: envoy.tls.cert_validator.spiffe +typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig + trust_domains: + - name: example.com + trust_bundle: + filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" + )EOF"), + *typed_conf); + custom_validator_config_ = typed_conf; + initialize(); + auto conn = makeSslClientConnection({}); + if (tls_version_ == envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2) { + auto codec = makeRawHttpConnection(std::move(conn), absl::nullopt); + EXPECT_FALSE(codec->connected()); + } else { + auto codec = makeHttpConnection(std::move(conn)); + ASSERT_TRUE(codec->waitForDisconnect()); + codec->close(); + } + checkVerifyErrorCouter(1); +} + +// clientcert.pem's san is "spiffe://lyft.com/frontend-team" but the corresponding trust bundle does +// not match with the client cert. So this should also be rejected. +TEST_P(SslSPIFFECertValidatorIntegrationTest, ServerRsaSPIFFEValidatorRejected2) { + auto typed_conf = new envoy::config::core::v3::TypedExtensionConfig(); + TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( +name: envoy.tls.cert_validator.spiffe +typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig + trust_domains: + - name: lyft.com + trust_bundle: + filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/fake_ca_cert.pem" + - name: example.com + trust_bundle: + filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" + )EOF"), + *typed_conf); + custom_validator_config_ = typed_conf; + initialize(); + auto conn = makeSslClientConnection({}); + if (tls_version_ == envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2) { + auto codec = makeRawHttpConnection(std::move(conn), absl::nullopt); + EXPECT_FALSE(codec->connected()); + } else { + auto codec = makeHttpConnection(std::move(conn)); + ASSERT_TRUE(codec->waitForDisconnect()); + codec->close(); + } + checkVerifyErrorCouter(1); +} + +} // namespace Ssl +} // namespace Envoy diff --git a/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_integration_test.h b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_integration_test.h new file mode 100644 index 0000000000000..85451f3a7440f --- /dev/null +++ b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_integration_test.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include "test/integration/http_integration.h" +#include "test/integration/server.h" +#include "test/integration/ssl_utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Ssl { + +class SslSPIFFECertValidatorIntegrationTest + : public testing::TestWithParam< + std::tuple>, + public HttpIntegrationTest { +public: + SslSPIFFECertValidatorIntegrationTest() + : HttpIntegrationTest(Http::CodecClient::Type::HTTP1, std::get<0>(GetParam())) {} + + void initialize() override; + void TearDown() override; + + virtual Network::ClientConnectionPtr + makeSslClientConnection(const ClientSslTransportOptions& options); + void checkVerifyErrorCouter(uint64_t value); + + static std::string ipClientVersionTestParamsToString( + const ::testing::TestParamInfo< + std::tuple>& + params) { + return fmt::format("{}_TLSv1_{}", + std::get<0>(params.param) == Network::Address::IpVersion::v4 ? "IPv4" + : "IPv6", + std::get<1>(params.param) - 1); + } + +protected: + envoy::config::core::v3::TypedExtensionConfig* custom_validator_config_{nullptr}; + std::unique_ptr context_manager_; + const envoy::extensions::transport_sockets::tls::v3::TlsParameters::TlsProtocol tls_version_{ + std::get<1>(GetParam())}; +}; + +} // namespace Ssl +} // namespace Envoy diff --git a/test/extensions/transport_sockets/tls/integration/BUILD b/test/extensions/transport_sockets/tls/integration/BUILD index bdcb06093e7d1..7486ec63da9d6 100644 --- a/test/extensions/transport_sockets/tls/integration/BUILD +++ b/test/extensions/transport_sockets/tls/integration/BUILD @@ -16,7 +16,6 @@ envoy_cc_test( ], data = [ "//test/config/integration/certs", - "//test/extensions/transport_sockets/tls/test_data:certs", ], deps = [ "//source/common/event:dispatcher_includes", @@ -27,7 +26,6 @@ envoy_cc_test( "//source/extensions/transport_sockets/tls:context_config_lib", "//source/extensions/transport_sockets/tls:context_lib", "//source/extensions/transport_sockets/tls:ssl_handshaker_lib", - "//source/extensions/transport_sockets/tls/cert_validator/spiffe:config", "//test/extensions/common/tap:common", "//test/integration:http_integration_lib", "//test/mocks/secret:secret_mocks", diff --git a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc index 1d76c8277e9bd..940d480899ae6 100644 --- a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc +++ b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc @@ -42,8 +42,8 @@ void SslIntegrationTestBase::initialize() { .setEcdsaCertOcspStaple(server_ecdsa_cert_ocsp_staple_) .setOcspStapleRequired(ocsp_staple_required_) .setTlsV13(server_tlsv1_3_) - .setExpectClientEcdsaCert(client_ecdsa_cert_) - .setCustomValidatorConfig(custom_validator_config_)); + .setExpectClientEcdsaCert(client_ecdsa_cert_)); + HttpIntegrationTest::initialize(); context_manager_ = @@ -354,102 +354,6 @@ TEST_P(SslCertficateIntegrationTest, ServerRsa) { checkStats(); } -// Server configured on SPIFFE certificate validation for mTLS -// clientcert.pem's san is "spiffe://lyft.com/frontend-team" so it should be accepted. -TEST_P(SslCertficateIntegrationTest, ServerRsaSPIFFEValidatorAccepted) { - auto typed_conf = new envoy::config::core::v3::TypedExtensionConfig(); - TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( -name: envoy.tls.cert_validator.spiffe -typed_config: - "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig - trust_domains: - - name: lyft.com - trust_bundle: - filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" - )EOF"), - *typed_conf); - - custom_validator_config_ = typed_conf; - server_rsa_cert_ = true; - ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { - return makeSslClientConnection({}); - }; - testRouterRequestAndResponseWithBody(1024, 512, false, false, &creator); - checkStats(); - Stats::CounterSharedPtr counter = - test_server_->counter(listenerStatPrefix("ssl.fail_verify_error")); - EXPECT_EQ(0, counter->value()); - counter->reset(); -} - -// Server configured on SPIFFE certificate validation for mTLS -// clientcert.pem's san is "spiffe://lyft.com/frontend-team" so it should be rejected. -TEST_P(SslCertficateIntegrationTest, ServerRsaSPIFFEValidatorRejected1) { - auto typed_conf = new envoy::config::core::v3::TypedExtensionConfig(); - TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( -name: envoy.tls.cert_validator.spiffe -typed_config: - "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig - trust_domains: - - name: example.com - trust_bundle: - filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" - )EOF"), - *typed_conf); - custom_validator_config_ = typed_conf; - server_rsa_cert_ = true; - initialize(); - auto conn = makeSslClientConnection({}); - if (tls_version_ == envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2) { - auto codec = makeRawHttpConnection(std::move(conn), absl::nullopt); - EXPECT_FALSE(codec->connected()); - } else { - auto codec = makeHttpConnection(std::move(conn)); - ASSERT_TRUE(codec->waitForDisconnect()); - codec->close(); - } - Stats::CounterSharedPtr counter = - test_server_->counter(listenerStatPrefix("ssl.fail_verify_error")); - EXPECT_EQ(1, counter->value()); - counter->reset(); -} - -// Server configured on SPIFFE certificate validation for mTLS -// clientcert.pem's san is "spiffe://lyft.com/frontend-team" but the corresponding trust bundle does -// not match with the client cert. So this should also be rejected. -TEST_P(SslCertficateIntegrationTest, ServerRsaSPIFFEValidatorRejected2) { - auto typed_conf = new envoy::config::core::v3::TypedExtensionConfig(); - TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( -name: envoy.tls.cert_validator.spiffe -typed_config: - "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig - trust_domains: - - name: lyft.com - trust_bundle: - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/fake_ca_cert.pem" - - name: example.com - trust_bundle: - filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" - )EOF"), - *typed_conf); - custom_validator_config_ = typed_conf; - server_rsa_cert_ = true; - initialize(); - auto conn = makeSslClientConnection({}); - if (tls_version_ == envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2) { - auto codec = makeRawHttpConnection(std::move(conn), absl::nullopt); - EXPECT_FALSE(codec->connected()); - } else { - auto codec = makeHttpConnection(std::move(conn)); - ASSERT_TRUE(codec->waitForDisconnect()); - codec->close(); - } - Stats::CounterSharedPtr counter = - test_server_->counter(listenerStatPrefix("ssl.fail_verify_error")); - EXPECT_EQ(1, counter->value()); - counter->reset(); -} - // Server with an ECDSA certificate and a client with RSA/ECDSA cipher suites works. TEST_P(SslCertficateIntegrationTest, ServerEcdsa) { server_rsa_cert_ = false; diff --git a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.h b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.h index 909f72dc08f3b..e7f615c54476c 100644 --- a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.h +++ b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.h @@ -29,7 +29,6 @@ class SslIntegrationTestBase : public HttpIntegrationTest { void checkStats(); protected: - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config_{nullptr}; bool server_tlsv1_3_{false}; bool server_rsa_cert_{true}; bool server_rsa_cert_ocsp_staple_{false};