From 1e3a53c063ee2a342f9449f23fdcd1c8ff9e418d Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Wed, 21 Aug 2024 16:22:34 -0400 Subject: [PATCH 01/53] tls-tests: updating the auto-generated certs for TLS tests (#35781) Signed-off-by: Adi Suissa-Peleg --- test/common/tls/ssl_socket_test.cc | 10 +- test/common/tls/test_data/ca_cert.crl | 16 +-- test/common/tls/test_data/ca_cert.pem | 34 +++--- test/common/tls/test_data/ca_cert_info.h | 13 ++- .../common/tls/test_data/ca_cert_with_crl.pem | 50 ++++----- test/common/tls/test_data/ca_certificates.pem | 68 ++++++------ test/common/tls/test_data/ca_key.pem | 55 ++++----- test/common/tls/test_data/certs.sh | 7 +- test/common/tls/test_data/expired_cert.pem | 32 +++--- test/common/tls/test_data/expired_cert_info.h | 13 ++- test/common/tls/test_data/expired_key.pem | 55 ++++----- .../tls/test_data/expired_san_uri_cert.pem | 34 +++--- .../tls/test_data/expired_san_uri_cert_info.h | 13 ++- .../tls/test_data/expired_san_uri_key.pem | 55 ++++----- .../tls/test_data/expired_spiffe_san_cert.pem | 34 +++--- .../test_data/expired_spiffe_san_cert_info.h | 13 ++- .../tls/test_data/expired_spiffe_san_key.pem | 55 ++++----- test/common/tls/test_data/extensions_cert.pem | 36 +++--- .../tls/test_data/extensions_cert_info.h | 13 ++- test/common/tls/test_data/extensions_key.pem | 55 ++++----- test/common/tls/test_data/fake_ca_cert.pem | 34 +++--- test/common/tls/test_data/fake_ca_cert_info.h | 13 ++- test/common/tls/test_data/fake_ca_key.pem | 55 ++++----- .../tls/test_data/intermediate_ca_cert.crl | 16 +-- .../tls/test_data/intermediate_ca_cert.pem | 36 +++--- .../test_data/intermediate_ca_cert_chain.crl | 32 +++--- .../test_data/intermediate_ca_cert_chain.pem | 70 ++++++------ .../intermediate_ca_cert_chain_with_crl.pem | 86 +++++++-------- ...ermediate_ca_cert_chain_with_crl_chain.pem | 102 ++++++++--------- .../tls/test_data/intermediate_ca_cert_info.h | 13 ++- .../tls/test_data/intermediate_ca_key.pem | 55 ++++----- .../tls/test_data/keyusage_cert_sign_cert.pem | 36 +++--- .../test_data/keyusage_cert_sign_cert_info.h | 13 ++- .../tls/test_data/keyusage_cert_sign_key.pem | 55 ++++----- .../tls/test_data/keyusage_crl_sign_cert.pem | 36 +++--- .../test_data/keyusage_crl_sign_cert_info.h | 13 ++- .../tls/test_data/keyusage_crl_sign_key.pem | 55 ++++----- .../tls/test_data/long_validity_cert.pem | 34 +++--- .../tls/test_data/long_validity_cert_info.h | 13 ++- .../tls/test_data/long_validity_key.pem | 55 ++++----- test/common/tls/test_data/no_san_cert.pem | 34 +++--- test/common/tls/test_data/no_san_cert_info.h | 20 ++-- test/common/tls/test_data/no_san_chain.pem | 70 ++++++------ test/common/tls/test_data/no_san_cn_cert.pem | 34 +++--- .../tls/test_data/no_san_cn_cert_info.h | 13 ++- test/common/tls/test_data/no_san_cn_key.pem | 55 ++++----- test/common/tls/test_data/no_san_key.pem | 55 ++++----- test/common/tls/test_data/no_subject_cert.pem | 34 +++--- .../tls/test_data/no_subject_cert_info.h | 13 ++- test/common/tls/test_data/no_subject_key.pem | 55 ++++----- .../tls/test_data/non_spiffe_san_cert.pem | 34 +++--- .../tls/test_data/non_spiffe_san_cert_info.h | 13 ++- .../tls/test_data/non_spiffe_san_key.pem | 55 ++++----- .../tls/test_data/password_protected_cert.pem | 34 +++--- .../test_data/password_protected_cert_info.h | 13 ++- .../test_data/password_protected_certkey.p12 | Bin 2669 -> 2835 bytes .../tls/test_data/password_protected_key.pem | 60 +++++----- test/common/tls/test_data/san_dns2_cert.pem | 32 +++--- .../common/tls/test_data/san_dns2_cert_info.h | 13 ++- test/common/tls/test_data/san_dns2_key.pem | 55 ++++----- test/common/tls/test_data/san_dns3_cert.pem | 36 +++--- .../common/tls/test_data/san_dns3_cert_info.h | 13 ++- .../tls/test_data/san_dns3_certkeychain.p12 | Bin 4738 -> 4753 bytes test/common/tls/test_data/san_dns3_chain.pem | 72 ++++++------ test/common/tls/test_data/san_dns3_key.pem | 55 ++++----- test/common/tls/test_data/san_dns4_cert.pem | 36 +++--- .../common/tls/test_data/san_dns4_cert_info.h | 13 ++- test/common/tls/test_data/san_dns4_key.pem | 55 ++++----- .../test_data/san_dns_and_othername_cert.pem | 34 +++--- .../san_dns_and_othername_cert_info.h | 13 ++- .../test_data/san_dns_and_othername_key.pem | 52 ++++----- test/common/tls/test_data/san_dns_cert.pem | 32 +++--- test/common/tls/test_data/san_dns_cert_info.h | 13 ++- .../tls/test_data/san_dns_ecdsa_1_cert.pem | 26 ++--- .../tls/test_data/san_dns_ecdsa_1_cert_info.h | 13 ++- .../tls/test_data/san_dns_ecdsa_1_key.pem | 6 +- .../tls/test_data/san_dns_ecdsa_2_cert.pem | 26 ++--- .../tls/test_data/san_dns_ecdsa_2_cert_info.h | 13 ++- .../tls/test_data/san_dns_ecdsa_2_key.pem | 6 +- test/common/tls/test_data/san_dns_key.pem | 55 ++++----- .../tls/test_data/san_dns_rsa_1_cert.pem | 34 +++--- .../tls/test_data/san_dns_rsa_1_cert_info.h | 13 ++- .../tls/test_data/san_dns_rsa_1_key.pem | 55 ++++----- .../tls/test_data/san_dns_rsa_2_cert.pem | 34 +++--- .../tls/test_data/san_dns_rsa_2_cert_info.h | 13 ++- .../tls/test_data/san_dns_rsa_2_key.pem | 55 ++++----- test/common/tls/test_data/san_ip_cert.pem | 34 +++--- test/common/tls/test_data/san_ip_cert_info.h | 13 ++- test/common/tls/test_data/san_ip_chain.pem | 70 ++++++------ test/common/tls/test_data/san_ip_key.pem | 55 ++++----- .../tls/test_data/san_multiple_dns_1_cert.pem | 34 +++--- .../test_data/san_multiple_dns_1_cert_info.h | 13 ++- .../tls/test_data/san_multiple_dns_1_key.pem | 55 ++++----- .../tls/test_data/san_multiple_dns_cert.pem | 34 +++--- .../test_data/san_multiple_dns_cert_info.h | 13 ++- .../tls/test_data/san_multiple_dns_key.pem | 55 ++++----- .../test_data/san_multiple_othername_cert.pem | 34 +++--- .../san_multiple_othername_cert_info.h | 13 ++- .../test_data/san_multiple_othername_key.pem | 52 ++++----- ...an_multiple_othername_string_type_cert.pem | 34 +++--- ...multiple_othername_string_type_cert_info.h | 13 ++- ...san_multiple_othername_string_type_key.pem | 52 ++++----- .../tls/test_data/san_only_dns_cert.pem | 34 +++--- .../tls/test_data/san_only_dns_cert_info.h | 13 ++- .../common/tls/test_data/san_only_dns_key.pem | 55 ++++----- .../tls/test_data/san_othername_cert.pem | 34 +++--- .../tls/test_data/san_othername_cert_info.h | 13 ++- .../tls/test_data/san_othername_key.pem | 52 ++++----- test/common/tls/test_data/san_uri_cert.pem | 34 +++--- test/common/tls/test_data/san_uri_cert_info.h | 13 ++- test/common/tls/test_data/san_uri_key.pem | 55 ++++----- .../tls/test_data/san_wildcard_dns_cert.pem | 34 +++--- .../test_data/san_wildcard_dns_cert_info.h | 13 ++- .../tls/test_data/san_wildcard_dns_key.pem | 55 ++++----- .../common/tls/test_data/selfsigned2_cert.pem | 34 +++--- .../tls/test_data/selfsigned2_cert_info.h | 13 ++- .../test_data/selfsigned2_ecdsa_p256_cert.pem | 18 +-- .../selfsigned2_ecdsa_p256_cert_info.h | 13 ++- test/common/tls/test_data/selfsigned_cert.pem | 34 +++--- .../tls/test_data/selfsigned_cert_info.h | 13 ++- .../test_data/selfsigned_ecdsa_p256_cert.pem | 18 +-- .../selfsigned_ecdsa_p256_cert_info.h | 13 ++- .../test_data/selfsigned_ecdsa_p256_key.pem | 6 +- .../test_data/selfsigned_ecdsa_p384_cert.pem | 22 ++-- .../selfsigned_ecdsa_p384_cert_info.h | 13 ++- .../selfsigned_ecdsa_p384_certkey.p12 | Bin 1185 -> 1201 bytes .../test_data/selfsigned_ecdsa_p384_key.pem | 8 +- test/common/tls/test_data/selfsigned_key.pem | 55 ++++----- .../test_data/selfsigned_rsa_1024_cert.pem | 24 ++-- .../test_data/selfsigned_rsa_1024_cert_info.h | 13 ++- .../test_data/selfsigned_rsa_1024_certkey.p12 | Bin 1712 -> 1729 bytes .../tls/test_data/selfsigned_rsa_1024_key.pem | 31 +++--- .../test_data/selfsigned_rsa_3072_cert.pem | 46 ++++---- .../test_data/selfsigned_rsa_3072_cert_info.h | 13 ++- .../tls/test_data/selfsigned_rsa_3072_key.pem | 79 ++++++------- .../test_data/selfsigned_rsa_4096_cert.pem | 56 +++++----- .../test_data/selfsigned_rsa_4096_cert_info.h | 13 ++- .../tls/test_data/selfsigned_rsa_4096_key.pem | 103 ++++++++--------- test/common/tls/test_data/spiffe_san_cert.pem | 34 +++--- .../tls/test_data/spiffe_san_cert_info.h | 13 ++- test/common/tls/test_data/spiffe_san_key.pem | 55 ++++----- ...spiffe_san_signed_by_intermediate_cert.pem | 36 +++--- ...ffe_san_signed_by_intermediate_cert_info.h | 13 ++- .../spiffe_san_signed_by_intermediate_key.pem | 55 ++++----- .../tls/test_data/test_long_cert_chain.pem | 104 +++++++++--------- .../common/tls/test_data/test_random_cert.pem | 36 +++--- test/common/tls/test_data/ticket_key_a | 2 +- test/common/tls/test_data/ticket_key_b | 2 +- .../common/tls/test_data/ticket_key_wrong_len | 2 +- test/common/tls/test_data/unittest_cert.pem | 42 +++---- .../common/tls/test_data/unittest_cert_info.h | 13 ++- test/common/tls/test_data/unittest_key.pem | 55 ++++----- .../spiffe/spiffe_validator_test.cc | 4 +- 153 files changed, 2553 insertions(+), 2478 deletions(-) diff --git a/test/common/tls/ssl_socket_test.cc b/test/common/tls/ssl_socket_test.cc index ba1ca0b65598..8cbaac3c7fd0 100644 --- a/test/common/tls/ssl_socket_test.cc +++ b/test/common/tls/ssl_socket_test.cc @@ -28,6 +28,7 @@ #include "test/common/tls/ssl_certs_test.h" #include "test/common/tls/test_data/ca_cert_info.h" #include "test/common/tls/test_data/extensions_cert_info.h" +#include "test/common/tls/test_data/intermediate_ca_cert_info.h" #include "test/common/tls/test_data/no_san_cert_info.h" #include "test/common/tls/test_data/password_protected_cert_info.h" #include "test/common/tls/test_data/san_dns2_cert_info.h" @@ -1176,9 +1177,12 @@ TEST_P(SslSocketTest, GetCertDigests) { )EOF"; TestUtilOptions test_options(client_ctx_yaml, server_ctx_yaml, true, version_); - std::vector sha256Digests = absl::StrSplit(TEST_NO_SAN_CERT_CHAIN_256_HASHES, ','); - std::vector sha1Digests = absl::StrSplit(TEST_NO_SAN_CERT_CHAIN_1_HASHES, ','); - std::vector serialNumbers = absl::StrSplit(TEST_NO_SAN_CERT_CHAIN_SERIALS, ','); + std::vector sha256Digests = {TEST_NO_SAN_CERT_256_HASH, + TEST_INTERMEDIATE_CA_CERT_256_HASH}; + std::vector sha1Digests = {TEST_NO_SAN_CERT_1_HASH, + TEST_INTERMEDIATE_CA_CERT_1_HASH}; + std::vector serialNumbers = {TEST_NO_SAN_CERT_SERIAL, + TEST_INTERMEDIATE_CA_CERT_SERIAL}; testUtil(test_options.setExpectedSha256Digests(sha256Digests) .setExpectedSha1Digests(sha1Digests) .setExpectedSerialNumber(TEST_NO_SAN_CERT_SERIAL) // test checks first serial # diff --git a/test/common/tls/test_data/ca_cert.crl b/test/common/tls/test_data/ca_cert.crl index 13eb59b391d4..c12f1817f5e7 100644 --- a/test/common/tls/test_data/ca_cert.crl +++ b/test/common/tls/test_data/ca_cert.crl @@ -2,12 +2,12 @@ MIIB+DCB4QIBATANBgkqhkiG9w0BAQsFADB2MQswCQYDVQQGEwJVUzETMBEGA1UE CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwE THlmdDEZMBcGA1UECwwQTHlmdCBFbmdpbmVlcmluZzEQMA4GA1UEAwwHVGVzdCBD -QRcNMjIwODIyMDc1MTM0WhcNMzIwODE5MDc1MTM0WjAnMCUCFHwlLHXpWqV6iPHx -xcw/9PqcWqTCFw0yMjA4MjIwNzUxMzRaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG -9w0BAQsFAAOCAQEArv50n9iLaX9Vei1ldedumBtvl3DomOUtHPxb2YOPRGd9EKWa -rNtZ9pWibwLLekNoc8zNhNw2KFDhA8i6/af6BuK2O3MNMw9gbHKJnILkXJapame1 -DkEEORABNuBRpgAWrQF6GaVkFp94NjfcGHbX8QCmYEueArEBEReZRtOHhNSjFdaP -JU+hiueoNtEcOg8mX3w8OnYq11Rwmf440veRxupgrbcL4W8sCg3IbydUUvy/R0Jo -3t9bRFYd2Jj4J0idxD7HSku8pCRjCmlQcicso+G/G6oqoduJ29O8hfliqp76mjeL -HSVSWUXy9f1yTr0BZ0/eY1yj84mtK8Tp3FRELg== +QRcNMjQwODIxMTkxNDExWhcNMzQwODE5MTkxNDExWjAnMCUCFDqzcIiLuhgHHdG+ +r3TnjGE+SQVlFw0yNDA4MjExOTE0MTFaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG +9w0BAQsFAAOCAQEAPe7WB3XT2rBs/2K+/G7s0EAeIlgdv2H/QXhBb3gLA+mUpLTH +cPgvkdnSEKw6x6g+erI1pAqew6ZiEbaSf4SLCYKTQhpzHH2cmwJ+chwplFnSIcVl +2FQOmQ1xf/lIZRf3hgPTGTzws6ptBoPGsOo+IqQ06+ggCAXXuHoNhHzKAkw3k5g+ +W+fPfQEUkJWCrDmM7Nhu50bf+cSPQl9qw4Z42K86pqp7w1sw5STo4Lp2MoKCT/3b +8X4wBB8hTvMdOJozwUjWnf8PbgXRTOfuoCR9eycLTbMUS1GazYKLfjMLESFR3rqp +tnY4u9DRKVqDzKPVPzz8BXzdJicwWlqVdO2I+w== -----END X509 CRL----- diff --git a/test/common/tls/test_data/ca_cert.pem b/test/common/tls/test_data/ca_cert.pem index a21dd343d1f1..6fe2f9937403 100644 --- a/test/common/tls/test_data/ca_cert.pem +++ b/test/common/tls/test_data/ca_cert.pem @@ -1,23 +1,23 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/ca_cert_info.h b/test/common/tls/test_data/ca_cert_info.h index 24c98350ce1a..0cd9a67ddd2f 100644 --- a/test/common/tls/test_data/ca_cert_info.h +++ b/test/common/tls/test_data/ca_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_CA_CERT_256_HASH[] = - "1d1f9e6825874456db7b5184862ad21bb91c6b8d20dd58a5c41ff39da74a1747"; -constexpr char TEST_CA_CERT_1_HASH[] = "4a7f37624073246a00eea254c22dde27ebe510c1"; -constexpr char TEST_CA_CERT_SPKI[] = "bW9U37Txj5HcJaW0nKLlOCdV+cJsbFZZRqRaG8O6dEo="; -constexpr char TEST_CA_CERT_SERIAL[] = "2da82a21c6a023a753dccff3152e075101222133"; -constexpr char TEST_CA_CERT_NOT_BEFORE[] = "Aug 22 07:51:28 2022 GMT"; -constexpr char TEST_CA_CERT_NOT_AFTER[] = "Aug 21 07:51:28 2024 GMT"; + "2c744b40ce28e2eea7ad41e505d39e89eff0c5ce11a943ded4f87e231bed3632"; +constexpr char TEST_CA_CERT_1_HASH[] = "936319da6877615ae6f968b7a7d182e90f669067"; +constexpr char TEST_CA_CERT_SPKI[] = "DDvY1NbGoGU6rrDRAN9qSlDcPeJyqmsgM4p7hIyTZVk="; +constexpr char TEST_CA_CERT_SERIAL[] = "34aac3658c934935a02ee3a011cdca4b7ca0a839"; +constexpr char TEST_CA_CERT_NOT_BEFORE[] = "Aug 21 19:14:02 2024 GMT"; +constexpr char TEST_CA_CERT_NOT_AFTER[] = "Aug 21 19:14:02 2026 GMT"; diff --git a/test/common/tls/test_data/ca_cert_with_crl.pem b/test/common/tls/test_data/ca_cert_with_crl.pem index 5bbefa63a9aa..b4321cb877e0 100644 --- a/test/common/tls/test_data/ca_cert_with_crl.pem +++ b/test/common/tls/test_data/ca_cert_with_crl.pem @@ -1,36 +1,36 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- -----BEGIN X509 CRL----- MIIB+DCB4QIBATANBgkqhkiG9w0BAQsFADB2MQswCQYDVQQGEwJVUzETMBEGA1UE CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwE THlmdDEZMBcGA1UECwwQTHlmdCBFbmdpbmVlcmluZzEQMA4GA1UEAwwHVGVzdCBD -QRcNMjIwODIyMDc1MTM0WhcNMzIwODE5MDc1MTM0WjAnMCUCFHwlLHXpWqV6iPHx -xcw/9PqcWqTCFw0yMjA4MjIwNzUxMzRaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG -9w0BAQsFAAOCAQEArv50n9iLaX9Vei1ldedumBtvl3DomOUtHPxb2YOPRGd9EKWa -rNtZ9pWibwLLekNoc8zNhNw2KFDhA8i6/af6BuK2O3MNMw9gbHKJnILkXJapame1 -DkEEORABNuBRpgAWrQF6GaVkFp94NjfcGHbX8QCmYEueArEBEReZRtOHhNSjFdaP -JU+hiueoNtEcOg8mX3w8OnYq11Rwmf440veRxupgrbcL4W8sCg3IbydUUvy/R0Jo -3t9bRFYd2Jj4J0idxD7HSku8pCRjCmlQcicso+G/G6oqoduJ29O8hfliqp76mjeL -HSVSWUXy9f1yTr0BZ0/eY1yj84mtK8Tp3FRELg== +QRcNMjQwODIxMTkxNDExWhcNMzQwODE5MTkxNDExWjAnMCUCFDqzcIiLuhgHHdG+ +r3TnjGE+SQVlFw0yNDA4MjExOTE0MTFaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG +9w0BAQsFAAOCAQEAPe7WB3XT2rBs/2K+/G7s0EAeIlgdv2H/QXhBb3gLA+mUpLTH +cPgvkdnSEKw6x6g+erI1pAqew6ZiEbaSf4SLCYKTQhpzHH2cmwJ+chwplFnSIcVl +2FQOmQ1xf/lIZRf3hgPTGTzws6ptBoPGsOo+IqQ06+ggCAXXuHoNhHzKAkw3k5g+ +W+fPfQEUkJWCrDmM7Nhu50bf+cSPQl9qw4Z42K86pqp7w1sw5STo4Lp2MoKCT/3b +8X4wBB8hTvMdOJozwUjWnf8PbgXRTOfuoCR9eycLTbMUS1GazYKLfjMLESFR3rqp +tnY4u9DRKVqDzKPVPzz8BXzdJicwWlqVdO2I+w== -----END X509 CRL----- diff --git a/test/common/tls/test_data/ca_certificates.pem b/test/common/tls/test_data/ca_certificates.pem index 96add61ff7a2..aee0f750631a 100644 --- a/test/common/tls/test_data/ca_certificates.pem +++ b/test/common/tls/test_data/ca_certificates.pem @@ -1,46 +1,46 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/ca_key.pem b/test/common/tls/test_data/ca_key.pem index 59e276c9e359..17c0073c8122 100644 --- a/test/common/tls/test_data/ca_key.pem +++ b/test/common/tls/test_data/ca_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA8oobPYmtqcntMgLrBSFcR8LtTtr6Kxu8pK67jGQHJziPqqrx -KP6RyR1DVx0upvzIGJWG3dfAU8h2TUgOF8IjbvjNFoX/MQRD6Myjws/ZJraruWM2 -5YRBoAApWXtr2VlRnyuu+VmTK+bA8T2T6rCsWdXUfECF9217B6qZeGTW4S9c4jk1 -vEKt5u6xKe1GvuN9GSRlpCcAJe+lZuKRfGVNRIf/Xj6DmpNbKWhORUEOLB1//A5I -t1NAKEi1+tsYXwDQLO9jiW3hzOVWO9BNYobIAxbarU/i6xfb2JkUNyuB2T303NcL -r7j0pqU3SLNO6nTiRa5pmiqO0U9MS8fwhe6iswIDAQABAoIBAEUiettSuG7ygStF -S6q9tKk79hsJLlBFasNij1FYXfWfGMykR3PRBMtYDQ7y4Y519a+UR8pKqqb3OEmV -JXc+Po1uXD90WKanOZhNZMyuJI71eQOyNT69MVujUCYSmU5uOGbvs8Od9eaIsyzQ -ya4XSDmfSx9T4RwDWBN6XJ7F175+DKB5+JjhgGsBKOYx0CL2txr0uoEW/RIh+3uZ -l+/YYdZ/qhYYXumnTn+S+/0SCrk3LEWDgCQtjSLVsMW57mx4HwwUguoZ13sWrJEf -24n03BxicG6uJwBN8xZZ2cPnTTscOXez90EU6H2nuiAV/Gmwj1gvFkgQFcQ9lOcq -5FDONjkCgYEA/OGviYRB2+jpdRQTL1llCsFFay4crcO9/kmJAb+R0prpxRb8ACLm -uNEm6FbHjif15vL4jDVaqvdY9C5fgiYLgY9w23EjrkfJxSMArvO8xZBtPh5w4pNP -b21+FH+CcUTdzXFJqWSYh1twqplcRMLnOR8mD/4qiSazqRqxZ4C+RJUCgYEA9YfF -o67v0tI+IlFC/TmvXj6MebP5fcuhRnQ7DK64da0QhdEZhoXo2K6KnBMJLFLl3ize -Wbi/ykKy8fK05NXi4dT8oju3qLAmKh2rhxyMH1iFnUFeSUgiRhI1wsC0N8DFAXmz -y9NTfjXPishcjjHYYwuq1gYW7+oCsBOkNjntcCcCgYAjIPbRk53SfrhvmypPGYv/ -wnlyOiWhvd9Ww8BUjdgj+YEf7+Fx42dJpURSYju2c7alLnt4frDprxKcWRTLb52J -kfOLiFv8idxtlj8yDonaqAWE65Wi4/PU9tDc6BmmwnpNX79r2J2XsAwmpsc6hhi4 -xqry7cva4ZVzmFGsnyXPQQKBgQDn9P64ZlpXVxwwG4kn5clRRdI8X9TCDRAtmTz3 -/FBzi65iXWq59eRGYI6+aBVwdFiJjuX46Vr3YA/iF6Lh1Vbkduy876HQkalcfG9B -06xlKKICMHE81hLbE/UKKjeXvFvhyvIbC2iDgZ6yxBr8kwaUe79HNrWQrgkgA05N -lGhGXQKBgAbDGCv4U3wC/kKihVQJm9iz0AmYvIxeK2L9l/6ZQArwC/HEqw0MQ3YI -Qkx2/y8AwGlNIgicRs2yGjJXRM6nuYzKaHBZhTS19RgMcB1ZXcdnXD8qAEgLsyE7 -g8KfbT57IxJbXa0hRks2Eub3UGfTAVmuT6RBFmzuIRTa/wVKgb55 ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCPd//RG/Gbp8DE +QLBUUvjWa/8g3ZEcdtK7SWmKg1BhEP2Klsqj/Eo71SsyLHLofnPGbaU4Oq6voHr8 +WLbZWTjQgTZ4m0l0Ysy1VBVg0IUZo4b91ZJwhj78Tdaarq1dvMairckZx6L0WNp7 +fL2To8YkDsCTccxVmEOWhAGJ8LzG00MH965p72SIhWdzl/6Rsh7d0vrx53mU2V4p +zYqu2Gj+OnIcoSDbHy0wzySzb3wMhwuU9Q+mkgA5f5kMpJblf3wetI77t73AMKEq +7EhRV4Kn8JKqXRRf+9/kK4eUE04hRwZnUkvreJBcOIR1PRppMvTP0dWDv1nNSpMI +McI4Yg21AgMBAAECggEABIGd6OkKSTvXK7LmdveWNlH1FQiwlqbKzrQrGv0t6Kaa +eCBtZAI4KLH05eIMh+303/4wqtf5Ba4yPrvgnmoVhUMRvW8POxchW+60rzJNg/Ul +d9KeA2fMEau2OmyTKHcV/CUeRG+HWEp0Ll3ILJt/zUEjXl48L1IViWRDEhycKViM +X75CbLf7LDFHAw6loXj+WwfGBpfe1Uex3KRk9hM2StymS0xmQbFC0ujcY4Y72I6y +AKgvstVF406MmgxFi748wnPqvjIgQHXSZZrzuKZP5EW6WxhZwX7r0VYAMunSOl7R +1nXJOpsUgD4k9s3//w5lcESpNzKOS4f68KR17izozwKBgQDBmDROy/p7mPacyFk8 +G8pGTMbOxmC9TkhrqMav9oVcyaoXB8DFQ4iLivzRTrVK/zYydIbt/g3mg2IU8JCq +xo84Qaq0Ex8BCs3riWnIwFZBuw4muvAlEJs3+Uy/vW8qKJSvt3cYkhRtdAMvB++S +GejfY9X5fVKsqTWCqRGx6CQrLwKBgQC9t1EwHQEsUY/C2stECAQY+7wDlQ+LElSd +JkXE1gaE48w3hTa4ervwKU/VHiLrvvZd9s63gzX5LkHXW7R2aPYMMAdIBcaiJX03 +aYDXSpyTvXzNNWp3UcfWdY6QAqm4IB0T7oT+ckmSW5k7sLY1SnPevnxj2LAE/f4/ +Pa8iNGeMWwKBgC5D34xNNwk+nwEM6DZzNb3jL0fPJONYx/nilckLkwd/skRat/js +kL84cf7bXnwTzbH1IyHRKyVBlLkIXKpTVXrORqtOPoSTPm7hogQ14udGerVKy4Uw +GMghrfPMo7phhFcR80ZN8s/Nf81HijtSMdLhGwvKpW1Z6s3U9cOchLhFAoGBAL0R +UW8SqNWjHxOA+yv8lSDU1+X2Crx9cyf+OW/WID8VyrLWJtepMV1BvpbU5tZsxJiW +XCMVN5fymplmgi2zouo4fzku0GtN00GC+m0UpYCzSgo0nrr1HKRFGeO5U6z1DCWO +AqqV+W5LrSWIkb4ASgOFcPAMxjbjbhtWfRAoi72bAoGAP4MF+23TmmlYmqqNgNRG +7hvSiCpt7KH+UzmaIa+Ssz1kNrZYErU8YI6C+vS8U2fXdGoTHQU+sZBSWb8NNBm8 +mKRMeL8dp3qAhWNiEbjIXlSjTz5Z2IlCXuqckRBERCy4W50TQuUIIwHiiL6QqmEc +eDr5Ts1+ZWhRG5XK9X4ouzE= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/certs.sh b/test/common/tls/test_data/certs.sh index cfc93a6abe45..d1ba810665bd 100755 --- a/test/common/tls/test_data/certs.sh +++ b/test/common/tls/test_data/certs.sh @@ -55,6 +55,7 @@ generate_info_header() { prefix="TEST_$(echo "$1" | tr '[:lower:]' '[:upper:]')" { echo "// NOLINT(namespace-envoy)" + echo "// This file is auto-generated by certs.sh." echo "constexpr char ${prefix}_CERT_256_HASH[] =" echo " \"$(openssl x509 -in "${1}_cert.pem" -outform DER | openssl dgst -sha256 | cut -d" " -f2)\";" echo "constexpr char ${prefix}_CERT_1_HASH[] = \"$(openssl x509 -in "${1}_cert.pem" -outform DER | openssl dgst -sha1 | cut -d" " -f2)\";" @@ -317,13 +318,13 @@ rm -f long_validity_cert.cfg # Generate expired_cert.pem as a self-signed, expired cert (will fail on macOS 10.13+ because of negative days value). cp -f selfsigned_cert.cfg expired_cert.cfg generate_rsa_key expired -generate_x509_cert expired ca -365 +generate_x509_cert expired ca -1 rm -f expired_cert.cfg # Generate expired_san_uri_cert.pem as a CA signed, expired cert (will fail on macOS 10.13+ because of negative days value). cp -f san_uri_cert.cfg expired_san_uri_cert.cfg generate_rsa_key expired_san_uri -generate_x509_cert expired_san_uri ca -365 +generate_x509_cert expired_san_uri ca -1 rm -f expired_san_uri_cert.cfg # Initialize information for root CRL process @@ -373,7 +374,7 @@ generate_x509_cert non_spiffe_san ca cp -f spiffe_san_cert.cfg expired_spiffe_san_cert.cfg generate_rsa_key expired_spiffe_san -generate_x509_cert expired_spiffe_san ca -365 +generate_x509_cert expired_spiffe_san ca -1 rm -f expired_spiffe_san_cert.cfg cp -f spiffe_san_cert.cfg spiffe_san_signed_by_intermediate_cert.cfg diff --git a/test/common/tls/test_data/expired_cert.pem b/test/common/tls/test_data/expired_cert.pem index 2c5f5ad4bbd9..c22e098a1824 100644 --- a/test/common/tls/test_data/expired_cert.pem +++ b/test/common/tls/test_data/expired_cert.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/expired_cert_info.h b/test/common/tls/test_data/expired_cert_info.h index c4274cbcbaea..9d3e9615c761 100644 --- a/test/common/tls/test_data/expired_cert_info.h +++ b/test/common/tls/test_data/expired_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_EXPIRED_CERT_256_HASH[] = - "fa3ed9a4f656f4dbe515d1da8119d2f97df906a382d45293c59769015c9fb898"; -constexpr char TEST_EXPIRED_CERT_1_HASH[] = "6719db4466772f274bad87d6a960be50f36e6048"; -constexpr char TEST_EXPIRED_CERT_SPKI[] = "RzuR6pYDMoIxb4eyci73h4VFxJIwzT20s6CfsuBvL+s="; -constexpr char TEST_EXPIRED_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4cb"; -constexpr char TEST_EXPIRED_CERT_NOT_BEFORE[] = "Aug 22 07:51:34 2022 GMT"; -constexpr char TEST_EXPIRED_CERT_NOT_AFTER[] = "Aug 22 07:51:34 2021 GMT"; + "1a18ff120179cb435b4c2735824089d0f98ce5e8dcb7ff559996a5cc4165fba8"; +constexpr char TEST_EXPIRED_CERT_1_HASH[] = "9b5cc295add5cd6a9fbe807e435ae3ce6fe4bf1e"; +constexpr char TEST_EXPIRED_CERT_SPKI[] = "v1rSJrjvwodXgF8mJ+dT2cf37afxzOa3Hlzed4i01NU="; +constexpr char TEST_EXPIRED_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490578"; +constexpr char TEST_EXPIRED_CERT_NOT_BEFORE[] = "Aug 21 19:14:10 2024 GMT"; +constexpr char TEST_EXPIRED_CERT_NOT_AFTER[] = "Aug 20 19:14:10 2024 GMT"; diff --git a/test/common/tls/test_data/expired_key.pem b/test/common/tls/test_data/expired_key.pem index 936e5e1b0cfa..e46cdda98fda 100644 --- a/test/common/tls/test_data/expired_key.pem +++ b/test/common/tls/test_data/expired_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA6AuuYh/VNa4Q0hjk0ztOvGtEhJNOqWkQDkxHmMQThzL1g3Zx -u9LRNZ0l7p0OoYdWDOr9xwWJYXQvXAUv896qtxDsip/FabRN1fNfW3ywQnq100i3 -VpEkCW0jXR/e/qOtabzR1QACkuOmUKYh0LfhuctgxjBsApIhxYVOzI4Q3NQt357G -DTWtegnU3F+lEizf+8abaPahooR1M5ynIp0ul6TC9yMmd5a2DRrwuyP63Tbl1baK -CuQlDaYQ/u03xaNsU5lTSG3Ch0gOLNItEhHxgvoGzUXIKhkr3Yrh3Z9Y0vpPjSeV -3uRR723zHifnrHVbHGzI9AJHEV1Fytos7NW6BQIDAQABAoIBACWRDpBQOwJPxeVd -pl4UMfELJLKZ7pg6rCDEdKrkw4yV0W2RFWSlAr29TVDOGHpKIMJCoQdBfDZMywYI -yPSgTd8JXGIs75bnW9qRZhS3oQmCOEGWeigHo1/rTVhcOovbD84YhZgIQmJpfJl9 -6+eQfXjI1kf/utzHr7P8mv8+2LgHSuGdOsnAjgXIuebsbPUo8vTah+V6iHln9wFc -jtEDhQ8KrWaEFVWPhgdmwYLyuMIcPgTkFFFYZpJrGDna0QlFVNjJdIL++fH0HmHH -gfMnx8aOgWiv2iZCFpC1N7QNoyngkPBkgF1mCxZK2yDZCS4HC3X7h6AlaH661wU4 -kkCPSkECgYEA9rpSlb058W0n6JrXRyAGaARgv62RUyH/KQNdDaaa+EH8FaG2212I -FEa+xmmMji7MNTzYNohMmEmKHZlFhrHzGAPNogsi80PV58f8zM/idqmjZ826xA5l -onoeD2Ts3LVfaRvM4ePx2hfx9+gRsuku0faEJbzsRoQhi0XtfTv7RA0CgYEA8MQb -S5oSnQ/Cg/uBOle7buYibRR3c8HlwI0B+M0SO0qdU3/zB1vC+dIE5VG7C3kRwA9i -Ot1w/rpSOT/YXGKH4z6DOmvfOTZFNxfRqrO9PA8viMWCKjpi+hiVr3R3cByMyiQ0 -tP79puIy1rA4OeaLprRWbiQYpAp5gLTmtxhTd9kCgYAxWvhmR+Itb36KQ19JNRjS -+f04msn1bVmTpL6amndprhl1YlIn87/i/nvvSPH7B1WGWNOPpRhdZmignyaPWU2d -wjUCc2Pccfd6VEE332YYArtTao4v5glixTb6MWBIjme1qQAFOAoLbLrUsrHHrmnV -SpEI05AYUxo6uBRX9wW+iQKBgQCXsUbtRB6UHFjWpQBPjPUHszFffnSgVzr1LSJf -6nyhJKqo8EVjjnnywlLZVLw/R0Fau5aNNfW6WBP0A/jChEXPdBRkG5Dh0AKd6oDs -RyBkFcFCMAaJqo2vuwucJwoVdbdyqIsYukt/+KZFQ3O5bzrvhlGqRU3NFNhmshNm -qon0SQKBgQCr8TfEGZ9cHSiMPhEw9o6OCro9PYf7ytF/79QLe1AT+AVD3uh6EeZ7 -rt5JnN3RQsjCWxkgPaxvMCh4rN5ehaNjj4GaTBsbQnhp1aCAA8DrAdOTaDjWLSrV -65CjMvUICa/WQ3uEt73FqOGYCnkONtTXxcWNUGqumvW0jJJXstv8MQ== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC0wka1eVg6QbjE +uKISD0HKWmHjkygypgvVPO4J+LgQtQdS7azLnkl2FnXBRHRDNdUBg6Bg4oCN/toI +r3X7xsS2GpHpv/5Op4Dpiro5wLU+gnqduz6zb4k5M3BjHHlw9qEHFirk0ConGh9l +c9+VswSQOotL1nzf0rZ107lqEYUa7xQshHB5s/eWhLFICd7AYyXOhUbnQ19RY+3S +QSO+4UAL4psgdSW/z3zCAH0a7iUQqR2WwjD6+UCFSLVchU8co0K/xIaymRpLdie+ +U6JZjhzrJKHL9Jh+HmCWQespgxGIAovpPQHR2vjj4fjY9NnpTRlpejPCa4UdZkLL +rRneXECxAgMBAAECggEAD4dPoAQ5TULrYsIKUVMcd6vxVCXGmqhLZLGn8PUcKfpF +U21d7n2uCa4nBlgRRVtc7dT/HIek294AoOWi9QLn0A2jCqHe8Oags1+CvVal82Vt +73pAKhXbQ+3cejU+ZRMY9RUFURQlhOewegyc8P04t4PCBv05i9hsKp3qZDd2WAB8 +E+wLCFdnZj0rB/9XJRPis6H5EhKC+IJ4w43jbYu1HPCdI3+xuRzYUhJrd1GJbccN +B/y4qdL0CuB0vDl2LAIM/jfC4/1oY1etESysr/mvovGHg1LvA8YG0eg6vYmPeVsB +lf17kyOs1gLKcGHeGfDuQbe4jG8eio4xxjmkRD5U6QKBgQDuNmxgUvDiARHRFV2S +Wc7jiQhFGuHIR/LFMeoPvtF43EXYRe44CrjnV3E1n+5j98E3pJx+cUFSoZT4cFNb +nj9eM8iXVEwhLQ/P2xH2EB/SP19xAZp3XMhR8zR3F01eAi/GGbs8SjNlDMBrj6TP +Ji/U0y6sy6/uuzuJ7xI3a1jSiQKBgQDCQZdFs/FPcuZrQ99B/195ETf5jJsyt+rh +RZfA/h4JdnSFyGANoVQbb6zrBLWjigBRhoJP87KDWDw7nZ7IKCQiAnX7avNOiJXr +ik6NiW3yEUG6dOIC86A5sDguuTHjEKvtXRohwnVRTGLMKEsdcR0t6ei7ciE94VFc +rmlhPD8S6QKBgARuSLfF8ysRAAbWkeX9+6Ypz1iRtm9mPzLByeu/DeBkoHv0WQj7 +0hKjgryPm/yKCDMDwdFsQ93ImZ/BXxuOJvmWlv2RmNTpJKkmFwBvrlfXy+urLvdX +Z3Z2wpwQd+Tuv3q80cm+S5Rul0mo41TjDfK0duLJ6xzSqLnZE4qqWX2ZAoGAZ5aa +mGzwjbFz9ldnQsZvnxvzgXvddxpkgmSeHChm1Bz63iyQLDSPqWHQEDOeuOrqaI8W +BpSp6SiwVgojlhDx08EEMWJDBOoJKGXEpe1XV/Kj3k5eB7zrAFhcXW4ckD1fsWAo +g0AzV3soZD5IcBbVvJozpWGjIGB7BrVrNJLv/6ECgYEAimBKljYGUyt35LHLkQfu +nQ2316MM4vvDLvsk28ITmzdggQB7J0VisIKydudONiju8afvizWGgQRpVTU9U5Un +ueQzOHQMSkpglsHU6o8lDkCH5tAJv6rSUmnNf9JF+kp7iB0J7Q1LxiZL6iXsQAbQ +w1bhnTWSf/E0beVwFUsI/Lg= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/expired_san_uri_cert.pem b/test/common/tls/test_data/expired_san_uri_cert.pem index c98807b5de31..1064bb2ee13d 100644 --- a/test/common/tls/test_data/expired_san_uri_cert.pem +++ b/test/common/tls/test_data/expired_san_uri_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -Nxeqet0CIdw= +dGVhbTAdBgNVHQ4EFgQUf3UW2uv/t4OlGpbQ1M836mCERjEwHwYDVR0jBBgwFoAU +D6DPJb1YF34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBAC4jfuPQnJwP +Im9D5oganYWk4ewfb9AZmy63dVfDzRm2dEefGtb7VMyTyPaTWc18eMBVJpmjB2Nu +Y0VvxqhmH/zbpQFcMz9I9XxZje5FvlIQZ8inI1KGRB96PL7QrX0ktGxKXqUoiEgy +CHMr375XTxPOUT6p9tEfcfw+4ImEpoJNlpV0KQNxrIoYVeGHGXJPrq7aGEoqf0T+ +l+zt5ixgZOB7/L3Dqe0Cez0rvXYqaAgqW5WhlEM+8+WFalLRmGMOcoccWtp+V81/ +XnAIH//DciDTF+/rx2lYFt4a03SM/bV/GPwTg34tKcp9oW7GpdQMpRmobjkDKjhC +DZNjCLs8SrU= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/expired_san_uri_cert_info.h b/test/common/tls/test_data/expired_san_uri_cert_info.h index d61383a8d83c..5147f4a90321 100644 --- a/test/common/tls/test_data/expired_san_uri_cert_info.h +++ b/test/common/tls/test_data/expired_san_uri_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_EXPIRED_SAN_URI_CERT_256_HASH[] = - "fd01280cbd5dce7b1d2a0d3fdb6fc4f154beaf76e14a7d948fc634f2df958d82"; -constexpr char TEST_EXPIRED_SAN_URI_CERT_1_HASH[] = "a3155aeba7473703978300c43987566087ed89bc"; -constexpr char TEST_EXPIRED_SAN_URI_CERT_SPKI[] = "xdMLHS1jpRh5aOsoY4eORCYm+SL1SbfOmX16GAtSxbw="; -constexpr char TEST_EXPIRED_SAN_URI_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4cc"; -constexpr char TEST_EXPIRED_SAN_URI_CERT_NOT_BEFORE[] = "Aug 22 07:51:34 2022 GMT"; -constexpr char TEST_EXPIRED_SAN_URI_CERT_NOT_AFTER[] = "Aug 22 07:51:34 2021 GMT"; + "bf88360f013e7c747450ba31c96e11f0175b06f6fc2db9afb593fa8ed9ce8708"; +constexpr char TEST_EXPIRED_SAN_URI_CERT_1_HASH[] = "9698c58eb32fc1534748f91d36f4ffa905959fc0"; +constexpr char TEST_EXPIRED_SAN_URI_CERT_SPKI[] = "7NzLX7cNKg3/u/kvwYTIG5qYlof8GlBrBadpcetPm5U="; +constexpr char TEST_EXPIRED_SAN_URI_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490579"; +constexpr char TEST_EXPIRED_SAN_URI_CERT_NOT_BEFORE[] = "Aug 21 19:14:10 2024 GMT"; +constexpr char TEST_EXPIRED_SAN_URI_CERT_NOT_AFTER[] = "Aug 20 19:14:10 2024 GMT"; diff --git a/test/common/tls/test_data/expired_san_uri_key.pem b/test/common/tls/test_data/expired_san_uri_key.pem index c119de56a0d2..b6aa927df333 100644 --- a/test/common/tls/test_data/expired_san_uri_key.pem +++ b/test/common/tls/test_data/expired_san_uri_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA5PLT5MvRNxvMdrlO3GcSR5kM0McsRBthGkiBFuKYDHbRG7Iw -Ohq9Z62vErk3ticcV3eAK5aFhlQM/tSANRbiW6Mu3hcSOtaX6R2i/avktOtM0GQV -zfddaYalvazq/axdPgKvKHEELL9zaQnO6gATYBDBXtlRmWcBVeGUuNXwRvbcjQT3 -lg0mlA5o8H8eRrdSIfdX6+rIeA8ojQ6T/cdNR50+ybEb3gdqF9RJrMX0ws7IS0Lc -mb6dBXkQmWRIkEMByPzhKV7qV/reZu9VPHrqPFvXWwb5Z9ULIuFTKTiiSA/ZKFrY -CtlEUG4jN/tjsB9FKSgo55+IGYGeF7grXEGXBwIDAQABAoIBAEd6nLco/xeygSJr -9ngPYgCigwLHvEVDOwzGqC7p7ciua9i2yCHL6WhuLGOvGfqvuUSBla2GIAfxQ+Fn -nON2UpODngVOtK1UBDeOvi1utkfZ0rCZHsmgOjTRCfvu+arbXn0Wv3Lj3gbOewzH -OCeMgIAUmxquxLAdHaifdhxDBvJQVvCnquDhdh24g1Vj/R8+pOhFuDopRL2ZNo2f -PFlJBkiSEIgAN9JynEN2L/fewtVzbSKr6ruBABLt5v/Vw8mHWoLa4v7tjsFNn8yE -XDRGICBltCgZ3iOjnyx8Bxd3TiBSTKVHylh06Pc0jIWImelWj8VYhVKI9MyhwEFS -efJDf1kCgYEA/hQ2nuCd9zPVo2EApnUm1+33oFT3r3jqRgpqjviNCp5Bs56NHFlb -gldKYLw3Fru3tEm4hhXKrr6IRQyG5x2PAYLGX22gol/0duZKGWXV3Jsl9rV5XSNc -9SSX5ETnKxJID/1Irm1Q+iIYSgColWk1mxRuUFyHrsm4eMS6IYNfYtMCgYEA5q35 -B4oAlR4z4QZTQlDpEfUbkwHXss2y48BDVIzZRpuXKQBqp0P7KExwF9UcajFNEicv -6VittVmlUEBr+uydTfTLfzIiOlIHXc3j3s6FRMyj72mvUE2bBUn6w/bxa02/UNyk -imCFyDvnbKoUESb9Xmlzb0hQsosYq8XjyScmkn0CgYEAwS5TPUdhM8RoihlF6kom -p4Tag0A3NmaEEY736A6ZBlq/b7d8aPKT/i0qcxSH+jPuABkRQHmvKl/Zsk5M/8pc -ofRxqbrrqKm2cPS1oEvqaBpaqhLe3O73Tbht+HRfI0N6IRYePekF6bkkqJeJllhx -FqFZIqbHzyC2rrQ9JSAC1VsCgYAj4ZfE1nB0wXfsXqGAxTkbs/aQDU9R3rEev/85 -HZeGZhlDJW9xiR9+CzW8X0fGNNj6I+JN9589gC44p2ykYT2urI8iv9eXHr9KlgYF -2DXel75ANT4xzYB5eCJrbPPsbvF9UHS/mXf1x2ud+W6ZpGjw0JJGEweKXhx+S4+8 -8DwNuQKBgCvUECTgb8SjSARyZGIrqVJP7Bj/FLJ3u4V8x7Qn115lsE5Q/jc/P4mF -cBdg3Ff3hFwdTWA3Qbg1cY/0kX0bers1dMTkPlpU7WF2zyJxFXKTRFJsAHWG6RK6 -66OLat9TRtdCV4uPA/4NQsvcdrNwxFz6V9BZTjMuVS7KAdlnq2gY ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcmLHMHVcxEsTa +kawNG0ro9cIHvQD2uKdgMNLmXRLERN+/aMOrPSztxIoMQM75lVC+E0bubRrjhidM +DjnciIqYJqiBRSexrzrp3YZVCL1Qn0iJDHSVqqnkevX8MdujTBHqjv4bsSXbWlmH +6CT6DQA90V4iAQQR2cBK0CvHAoK8RFoMHS6pbcTl9xLPPwGRLsE3uPE6c+OhLMp5 +9+sFNexzTSoFDyrsxe1UUCT02Rzg7Nf2lkN8BJRkU71LTaZh5GWZI/q6lCAqFEaq +wCGox/p/FdtpDXQTq+LOrrW7DuVqy/K7JQiRRdEXMfjssnmx44XcpR81t74oLSrZ +Bp1EfWI3AgMBAAECggEAFLGCPd29JMGLYKsfn6i6xNKHanoEnobBGyXmJgcyUBUO +t2iL5AL8givYsCbFA7N9Fbq+aA/C4PfgG3AnzC2tPdg9ufqs9/iyWk18lEeAmUQh +f5gahUIZzXDqpS2SjZjNaXQTSrFTr5lwvDrYe4ul3sBGlOjRfLcxJOBIUWyr3oTC +TBhaW0SUdqmBbSlf2Dz2M46qdaoUDZBNfUw+X5PSimEAFCF6ObQFdNY5DtPwyJeP +DzC6IV3ngt3n2dgKMVU0xd9Fm4Fua1x0f8eUFzwvz5oK71eNGyQG3eGXyZqyankJ +jcKGwwkjDc3p1je4M2KiYoQ+70N533eNWTdEOjU2sQKBgQD50MERPN9kbrRNpiv7 ++HLZxgOnRab7G9vavPsyoSbc1PC6nXRAahZp2xWcFsMAYyPlMPZAVdXkmfGA4f8J +KzFGmcLgJRz7Gj1d3jJ8mnknnoyLP8hL7+2ild/tkTn57AMK9MwSeIytkyEkxC5w +nJyQa6gxNzpyEX0sBTbJ5yk8DwKBgQDiDsKkG0aXOvDqxqsgpWJdu5OK2jPqKOAL +tmtGIJenqooSO1v9eX1FdaCowQeHNiPXCG0MEJG9JE+NDALRW4kIzLm2XywgrFkR +agTzjGbU/A8MuoKTPHjrHrrO3ABXmspNq5PPvzMPQX/7uFH/vivX64TvYV6YBwEl +A3CoXxNvWQKBgQCtIwY8GTFGXQdvbYS8bFPFJNyxWK/DB2rXbfS3AUN698YjwC6q +2hvQn7uZY5kgspVVKhrxOcw1VJAxX/Au/ZV4Neb/DBnK2kO/w9i/zRu83sDPXZRH +NPFAppj9AJLq6KyvMjwhbRUq03a8EY+SEqjb2xFFkt5Z4k8bbD2trx0/9wKBgQCG +kWzSzh3ehsrFp9BVFb6Rt8jj3nMLEJwWvNftHhfJSp74rXdcU8b740LpUkdN+S+q +oSxxAygOpR/qAd1njYrsvxpKcytMo+w9jpQ1+z13yjiXRivWxCfjJx7jZ1mYzN9j +DyFliRc3HLG4QggmKqnk1iIDcj4iWAEZbIvS3w4tuQKBgQDMZFSNvjasUXhdo9NL +BOlA8JjE8AHduKMuqXgW11rr2unmDakAQOaTJUx/vYHH6wBfCoyZWyh7SbjsN3jQ +10MByT0XyGlWNCh6xzzOP6GDxMVPLkbJ7iV7ZegU3r8skI+cPnrKjeROUc3+vjez +L2jMBZDl5sSMFrdp7/49Sd5hhw== +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/expired_spiffe_san_cert.pem b/test/common/tls/test_data/expired_spiffe_san_cert.pem index f317d9dc2ae9..b6dc52b85102 100644 --- a/test/common/tls/test_data/expired_spiffe_san_cert.pem +++ b/test/common/tls/test_data/expired_spiffe_san_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/expired_spiffe_san_cert_info.h b/test/common/tls/test_data/expired_spiffe_san_cert_info.h index 13bdb60a7808..97cf4d47ce07 100644 --- a/test/common/tls/test_data/expired_spiffe_san_cert_info.h +++ b/test/common/tls/test_data/expired_spiffe_san_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_256_HASH[] = - "ca0b974a36e22f59861763edd648c9df5ed8686244602ddfb4afec6c6e33e788"; -constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_1_HASH[] = "934616b2aa1234443cc791aa6ac6c6eab50a2295"; -constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_SPKI[] = "JqdVxFbouyM1dJQpZWyHmFWztwXhzdZGsI5XEfAdqX8="; -constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4d2"; -constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_NOT_BEFORE[] = "Aug 22 07:51:35 2022 GMT"; -constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_NOT_AFTER[] = "Aug 22 07:51:35 2021 GMT"; + "8aff2a33d4590fe0429dac72ad69503e93f7595b3b69e2b6a55df1822225a7b2"; +constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_1_HASH[] = "c2b0e8d5c6c0b83ce4dd8d4bbc2b06a2ec48ddb2"; +constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_SPKI[] = "K3gq9jkn3AdRaL6lUxQyuLwSe+fjtGjXVvzIw102PsA="; +constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e49057f"; +constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_NOT_BEFORE[] = "Aug 21 19:14:12 2024 GMT"; +constexpr char TEST_EXPIRED_SPIFFE_SAN_CERT_NOT_AFTER[] = "Aug 20 19:14:12 2024 GMT"; diff --git a/test/common/tls/test_data/expired_spiffe_san_key.pem b/test/common/tls/test_data/expired_spiffe_san_key.pem index ba60730463fc..c8644c3563f2 100644 --- a/test/common/tls/test_data/expired_spiffe_san_key.pem +++ b/test/common/tls/test_data/expired_spiffe_san_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAvQUsRvNYBHFKjqMs/I+BXLNThf8pxgbQN3FmzpNOXXXi+mHN -6ukNkDlMlianWjK6CKOtopE+AtuQ1pEOZz6XXMS+kMq38FRVu9p37Qyo4Ci0Fcle -QnuoFa8O8x0vofmZQ9UbUmyDjCSyvEaY4QQStig9s8MbPyrNFXF09dG1poFmf28u -xlAeYn3osHkRW4CECk1sIgbKVPnCAIzYb4YyTN1sj02cYr4o/qUwygBkfkPoT62F -O9r6Oh5Z58He4HZU+gSS2BN/6VllUg5bhNkLLLqYvMg1ZtU6hTo7rRejkUxSrdZU -ObV9Tc3etDt0GYiUVL1gQ7Z1h+obAXPIUkP2XwIDAQABAoIBAGFOam7UEzmmQOWR -JzWVgtkAED1pEE47b7E7Fdu+hZcjewe+lc0a0LqwZLbfi0Op3Y9ZA6gu8SdzdOqg -njOUS0OcnSXY1jxIjiI444gK/lz3V03n7jh3hB41kpKhMcZGwhnjeT9DUa0xrzmx -dj5QZHmV2b3S8RHhrNYfJEDwBn2COYtanrlwMpKaO8KXpJVP1LhGxTvBn9DdrCev -DbIuBc0Ro7WYQKj7lAYVYsGUCy9WQa9ciEvoaj5Dc5zWslU0nntC7UmBAQakTm5p -sZVZJCZiPM/P5pdTTDjt3fF1Qqfu6tyOFxQ/31GsT6Yrm9t0p59JTmBW1ayQFw3N -QIsD+YECgYEA3oLJoEWvphupAFJzI92yDMaVJlqwNAPQZV4+LenmtzLZcPyR3sdd -G5eU3whbKdesYqFX8UBQwvhuBpREhe+mLeovMz5MBp/dC5RPOEK+kHu6NvpYyUq1 -L7safI9TZ2nZjf05Ts29btP0+Ocyv9JzX+Bn+VAMIQFUww0w3TP32SECgYEA2XgC -XvyXNmhk9Avdt9pgI0fxSqlIoPOXeC7TYgSZykPrize1m5LRc50rekS2YxlPSv/L -0KbmNc9L0Ty9IzBYyEpDwf9B4KL/WtQRuWodznr87YsJzWR0JlEQ9W96me5n5X0d -YW4Kc+3t85tx+nE8usaMggcv98aoQWdeBQ08X38CgYA0od8riBBKTFSnfNk7bJ9H -Iln5Xo47X4OV1rsChUdLoj2I2lVuyt2dPze5ofJebWObWOrCaCIyXC06ZSvoOo2m -YrSTfHLjRkE1EfnDJxaIepvLkWAbDQ7aoXlcaVKjLYiGa5V4rHXYl05k6ds5QICF -90Dg2ixkSjpQgPhD+pzvwQKBgQCETxiaM/HH/3HUbVfDIRC2xnGOrDns+udgDpU7 -IHN09SfcttM+SPA3+BrYs++HkYGFruWRF8oeWPXW4q5sN2D80vowkJ3DD0hvOXFj -LqXd10QFPj+DgCeOnGnF+cJM3xjFLf7vJSUk7VCFk0CgT77UIDKidb8AcBQ0XrB8 -QFZH/wKBgQC95LQc8ifjdtei/Vv36CpAh49ohjg7+sT9+aoqGCVvX5SJ6g6sJP+G -CRYcYuyDOQC3zVEOsDIwqib6Q9Ntm690bwZt/cZXUIM9Vp4vuGP/GHro8XNiwMld -tLmvs5COkapuqMkY3symFKjLQtOauIDlqwpnZvqVY9vICo0X3YiEHw== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDC5gt5AiKN942n +82dJhGYyuSuFeVm9V+lX7WHmw/8PMNEkG7gASbUK7Tzp423k4t/Ljr8GLw7ZOenw +le9O5RdmNaiTgNITJC6GD2fCTQu49cJI5Rq7OSiN/SHsCrydc8CwGyJEn86Uo9dq +fsQkm/fAz5domv62zLeZK9C33Exahhu/ftWdzjKfrkpObSNC++oxbIjoCvgfKfdm +HsUHHW8AdlkdYuWi3OtsnL9iX0Z6YlW1jQ2+DgohpF6gHo1tqF2DX0TcSy+VCif0 +zjMznO/LEH8POORhc3GFXOmSvb3wGHoRLN//Nhatx/zeki0TGQHn1dm9IzsThRoX +wp8UAq2jAgMBAAECggEAJskE63XjToE/LXcgzN6OP/XdlVhK5YVDKH5TB0tlzK4Y +UKk7esMwRhZkEt9xlSUZCDdGCIMA33XI+lm8H+UzPOHcxE3UgH6oy4DxUxdmB87Q +dRUytqNvUKJZR9HzKxpH9EPSE/oBcE8SpVzIx8hKC5LEPMrreZFP0CmKBazPfQvt ++WNZYTyh1mUmkL30ak3a7i/RMRbKUCb7QgVI8a8K4tR/AzLjDRW0klO7Y3u1aE1c +Hnts1IGN02rDcDlelsZAtDSnTOSJs9i1XZ2I9xy1A7ynBYgRAAHXsi3uu7h0XLoE +/y2S6zTb9s0OlxLSGYI+v71HzVpOpw63WHSqEGfXMQKBgQDxdS8JVuY6UdO/GrZ0 +o2ajxrlMdaFcDKWZ9BWtx6OAEQVkN5JXi6dRJCpFrg4NIPwb+Yq9WYmMSNxFLa7c +mqJx9roETD96lE06OHT8ZBXGkLQ4KBA8qiX5OdD3Q2HfwcjRga6BSf7b/HVRPX3I +vT8nTYnTUSKIKGUniteF7IAEpQKBgQDOowIhiIt/LHcVvq0Kj11E7Jbneazy0EOF +0nEk7g5RCwMn3Dzcw4lEixnWQBe7r1HNnx/PZJapU0sqEquzLUysQcEYfUifmY97 +zaS8E//+d7AJxmV+iH2lIIcFeX+XQhbvthyx1y2WkAMlZ4ADhOoP9FCCbL8ZWr8/ +ZOobSuIupwKBgQC6TcewNhvILfDqyGq1joqYnbHF3BFX2+4+3sWHY721B+0YCYTi +BcBg7D2trAHtgWDlGONC/H4T/vfubLQ6RRpIQq3+uPJV223HGV6yi2r93hMgLVFx +7XsFVOX2k0hGhNg1RxFlcrmx9ZZzy7VtGRBMfBh3M2golLqQCyIGlJemfQKBgCNB +sOVj1NlYDuGI7SF2IKXX8E+CdT3gxwSYSXHRpGOzi1BLxZ6tRkiJq1jhCqudWEnL +MrRCJ2qwqYx+LwmdWw2xEm9JQRDqNI8dIVRt3Snf5gtk7IBQbY+1IxSODHUUc7Fm +0zKM0lx0KfVB2ZfAH+ek+e+m+lwrHaKFZ2RMvJbVAoGAMhT7ZGXOoJSBXbatJC7C +rJMl+2NVr1qRDZE/DPlHDlLazDKXYgizUAnMQ6bw4MHVHdZMpfJ6LcgBqMegekQQ +FCG713KEGMAYgy2CHz4lEjGYQaCXJwUlzKALY6Ih3AVZZwqQHn+OQ/7t509IS0Zf +J5KjsbDN9dHsnc5DwnScY5g= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/extensions_cert.pem b/test/common/tls/test_data/extensions_cert.pem index c98180a7dce7..834945a35ef3 100644 --- a/test/common/tls/test_data/extensions_cert.pem +++ b/test/common/tls/test_data/extensions_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -vO6aOHiOv3k= +BggrBgEFBQcDATAdBgNVHQ4EFgQUicr+2Bk1/afrxiN+Ql8FRA29WXEwHwYDVR0j +BBgwFoAUD6DPJb1YF34IHnaYZclDrx9PhVYwFgYHKgMEBQYHCAQLDAlTb21ldGhp +bmcwEAYHKgMEBQYHCQQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAXtE5YbtEws +F2qS8NhbMxpqymvb6QcwOhf0HPAzcJokZuowuwCYjakA1HZzkFBZK7FFrtUwRo+m +Ia3fmXkTCK/oP5oG7Bv6UWMXOCtZqil63S9NyIPdn6ILMWQ6goCxjgDOu8/+Fw/A +3wvBY8/aLsePmyir+fD/M3wwJ71D/7jkhJcAo0Hslmx+65SULaK+IL2Zu6UPiBT4 +u0IW2gQMker2bjEChJDlbr+xcntDolcKvmREonJbikojTAa+lxIemToxxl+eliAT +b1vxqEhqXM++Gg871SDoLP9v7OYhbpJiumXu0QcMXjaEkblGibmwLW7CHO4O/b2e +hzsWIe48KTc= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/extensions_cert_info.h b/test/common/tls/test_data/extensions_cert_info.h index 75cb19f3fcc9..1398b3510a0c 100644 --- a/test/common/tls/test_data/extensions_cert_info.h +++ b/test/common/tls/test_data/extensions_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_EXTENSIONS_CERT_256_HASH[] = - "959d3c72dc0dc5e29ad9843715d0871be9d61953b420763278b4e57d12f19f3f"; -constexpr char TEST_EXTENSIONS_CERT_1_HASH[] = "ddc3e7d2330351f759ce3e7b342bed6d8ee09c34"; -constexpr char TEST_EXTENSIONS_CERT_SPKI[] = "34CDXNJ77muosk23FgbzwsyrFYul8BVi/56S6oVz4aE="; -constexpr char TEST_EXTENSIONS_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4c8"; -constexpr char TEST_EXTENSIONS_CERT_NOT_BEFORE[] = "Aug 22 07:51:31 2022 GMT"; -constexpr char TEST_EXTENSIONS_CERT_NOT_AFTER[] = "Aug 21 07:51:31 2024 GMT"; + "ffc4fda43ba46afffbb5fddeaa5c3b627984d60e173c2fc7f406692b7f1b24f8"; +constexpr char TEST_EXTENSIONS_CERT_1_HASH[] = "177b4c5cbf598d805606174139ad122f33cfa1da"; +constexpr char TEST_EXTENSIONS_CERT_SPKI[] = "cZ0Pr1fLI8fxH5LTLoFD+dluhe+eCxR3AWHfZmuiRP8="; +constexpr char TEST_EXTENSIONS_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490575"; +constexpr char TEST_EXTENSIONS_CERT_NOT_BEFORE[] = "Aug 21 19:14:08 2024 GMT"; +constexpr char TEST_EXTENSIONS_CERT_NOT_AFTER[] = "Aug 21 19:14:08 2026 GMT"; diff --git a/test/common/tls/test_data/extensions_key.pem b/test/common/tls/test_data/extensions_key.pem index 66bcb15abc01..51002f764eb3 100644 --- a/test/common/tls/test_data/extensions_key.pem +++ b/test/common/tls/test_data/extensions_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAt0VSzYs0Eo8mgT2cdH/c36xd+sCMmoJME1jNuwTX++RES7KP -eR2SnSbFe8kLssy2iT79dT0wYOnTBiaRZyUg5TD/tfM1lnEz23ZzOyIaMl/7ziha -zhmU7nZVX+OuTkG/AIoUK/9aJhNBspg/IHCXDeyz38G6D2ivQLDWr9/U9MifXfG+ -rPG2I3DsgxegEWjxJ4q6O+iFtySJWJcRGNjqHyToZsE7B7O9wZfJRD68Oc2X79rj -l5wPJxQn5fkTP8NGXkWulzY+nM45bHPFZxeR8eqFQb3LGMT57/lEQnNCnJ/NVe80 -rWiCq1TwXWX7NiU2hrhOHmviwEjtfUiZYpYntQIDAQABAoIBAQCcUCNMrrMONUxZ -JQyBjOD9YY2SppIF4qYyRibKoVn6PPpHOhgG7EM1iHEdoB87NEFoE/KoATV3I1fa -QiD4QYGqGb2wGa0WEJ1zTLcBs5d2acliT6cLbGRLc2Bj9dSgaJEZS6viztu75+a8 -BgCpkX404TOV4CzqoZYAbhPeU+HVmKol01yq3JMjNxFN7UE0XbgRm7BGRinrelzn -TCcRPGY7+M/lhSUo+l8a5HlZ0Qe0Y9WR/Yg3QGg2cyfWNUb51jUkrTTIczEGx2D8 -jmyyKy787jvUnvELH8kiGp2KKj4pPhQH3kj4uS21nfiFllofiXhRMz3f7OJelTXi -40tWbyzhAoGBAOBALcJjK8XfP2ldkQRJFTLwCGrJT+8zjcmdrYUEUjprfWYH/nlQ -uHVD9fc7IPG6di0kLjpZv1v6i0S4RcVf6XdmxECil7bK9eMK9Ow3L9EBCWqIu4bz -b6Yyl92PsV4JQu5pV6Duhyjpm1tPUx9lH4y4YLL6KWfOqR7kue7AeLJtAoGBANE3 -2sp424hVCYOZmqwZAr8RMx23Fx6E2gLw5jrN6W0A8ZbGxgq7FSsJWNW2Pyz9Y+lD -sruogXU8mDXVgp/FU/sOvf3Kvb/Mo/fHmyMRC/rGWF+94gMHeTRZl1p8HJFgNZVl -GIFaV7lcseIET1wd8nqd4oM5kiLih+4a2Bb2NT1pAoGARKPgXcu1Lk/zPPEi3kjw -cDMAoI8WJIWHNNtKrZhxAui77Wss/T0z+NDgjNhQcS091vtoGvw1kpXR4yr0UEHX -WHDgSVh7T7w4H1LPPS53OGY016Mao2gIGLsLuQmupLX5ArjD1cKtJFy87OoO62Es -kwosrxvbaKbdJVOlhersBtECgYA7qLG7CruPJLCR1jtE19zwnvb0gkEVcsy4Cfmc -yxrE+n/pfsT6Sl6+5utuBYn+SkMzQRq2aFaCF8VPlJKq/Jn1/T4wIJ/7EV+wSDr0 -xOelmumYY40PUBI/20xNgRakXcrpzuot+JULRmNzD8eRfPin/l2ZDdGeIPqh6wWz -hoGoAQKBgQCfny+1w48lB5J0L/2cYT78T7BG2RjWEnpIyzymysmGOE7cpuYtZIi9 -4N1etLj47tKHTnjsxueZHHnGoKtzBKVHHWjzlIF6mSE8aDqZDtC4IEw9gcJHNYKX -9c8j/wmscdbwO4ImJXlp+UabDkPo2b5bA5IhqIlEfO6/+FU4KcTMWA== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiWsORHGVrsTgC +2kzA/swykPlcfUOqW9Nci9xPWIE8RtCsd3UkEOtzWCY3KSyu9Hh/nonwj37dblvJ +qYuuH7iDjXpMTtpwZg+P5XLNGS0q5PFTq56reOHxosqUKEKaO5IwR5OGiXwHPMoJ +s736sNVcWv3Ob3+lRwoszuZVQzrq58AcfG6ivo6C230LN82ygIxFZWo8u0LKml7L +OzMHZmqVM4FKreLLs+CNsg+fmQZ57iA28H8OmGssj+YKNlh9ftgSAUKJRoO2Kgdj +6qVVKDAizjobn6ZhiPIIUgl5552EMCY3GWP7/4OxjKmZ1Ug3ekWKuYf0pfpVTcup +7a4zy88tAgMBAAECggEACAJUPXdaJXrjmXhtauPm7OOr+X0Qdnn7LkiUALIMBg40 +Qx3NgI75HoKNuBDm7GaQ/zKx+VUK3B+SlZswkdFsx8iV7OfC7OKMB/w4spd4W/JZ +WVhRBoJ7GvF97tshlfw0VP9i7rMflDfSe7ILQC+zBtBSTvm/IUck4FsAj9o2MNpT +xXflPBmZMhtYq/jcQbycgD7ewBljFv+lQy1JSPSsB/QCOQAh3PB8XzGa4kcM9k36 +J4hI1kGQNVtN4BhISJ4lxTafWnLTgGOAWEnA+ombdXWmfDvIxahFPv4kUKwNdJ9U +xO5d2Z2GvsZKolRrD0SYpxjpYW55SfyryHxZRWQjnQKBgQDUIVsw1RyWbNJByd34 +bLEdZV4WTvkTG4m6ZqCKlnXnrK5/66jhy1axNnRykT2j2at/AKeNvzs9sLMU0GWu +TWPPeXNQ3hsNY/TGGR7J5n9u4Srnp1ijBWom5zX20bwTE9HRQgi57Znl5MTKs7Nk +Qmfsq96G16+tqNESlE9vtSt+AwKBgQDD7iuPC7nHpi+nKDUnLiUXOvsiSH3qSeO5 +eEcA8vZK9I1ih0u5uw0G0wGWGOS/4D7K5sABV2izoHvg32AJN0bzG885uEzNZ+dw +WAMbJt9kSi5fXsweuOt9gjysDMh44s4v4PEWYW44BoCnBoOmsba8+43ryR5PK9E6 +2olwKcnPDwKBgQDO4ik5mt5ipob4upPNMNQbwzzbrPGl/Pl53ZU9FDixVexpvb/b +VqCZ/G3dPmFLZ4KmPlErIRH5vFcrOYOxVrC9K8mXWMYxbQbQHLe2WSJ3VQqvGrqL +Y0B/6IbszOgMAwxidXBlRKEPYOm8dz3BzjHk1EoWYExppXciE5rVa2+bWQKBgQCf +rOBu6Z10Kem4DrqSvbaYoga8v9tuLt2Z733eNiOmnnsDC0QZj2lkYF5wlsUF4pkJ +/tgHv9aiXW3Xq/O2TwhRZB6T6bEdzUn+cpvFav6v2wzDyJwNhaLVXGhZxukyK5Th +zC5ukOSkYBhFBrgQB9DnXxMgT32WBB22GxfbAxNm3QKBgFmeNOr+amgfNZJXQE+P ++CWCH/QdxtZquLLdx1yPLmptPvW+jriTwtm8r8gO+zwORZAhNoTUroGtS0t8XJwY +E3lHsOFF/cQfBQ9r3d3Qz62OOTzfS0tpiyl/NXV8wpmmn4QPiaVms63O36GTxxkL +YA/Fl6ndFQEWhSYX2F5JMeO6 +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/fake_ca_cert.pem b/test/common/tls/test_data/fake_ca_cert.pem index cbcd367fb579..4508f2cdfeff 100644 --- a/test/common/tls/test_data/fake_ca_cert.pem +++ b/test/common/tls/test_data/fake_ca_cert.pem @@ -1,23 +1,23 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/fake_ca_cert_info.h b/test/common/tls/test_data/fake_ca_cert_info.h index e7cb8cd2545e..04ea6dcdb052 100644 --- a/test/common/tls/test_data/fake_ca_cert_info.h +++ b/test/common/tls/test_data/fake_ca_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_FAKE_CA_CERT_256_HASH[] = - "409183b43ea9022bb1cdf5cbf55956002bab5ad6639498cf96cd7f399a9e03a3"; -constexpr char TEST_FAKE_CA_CERT_1_HASH[] = "f913a10dbae3c8223f78549c4e0a5f98c4f1d822"; -constexpr char TEST_FAKE_CA_CERT_SPKI[] = "D8vA9t0nc1K9C3bLp7CtacLNVeY8u+QwS0Tbo3lwD7k="; -constexpr char TEST_FAKE_CA_CERT_SERIAL[] = "3ab7b5450f606856f70dc7034124554ea9d65c5b"; -constexpr char TEST_FAKE_CA_CERT_NOT_BEFORE[] = "Aug 22 07:51:29 2022 GMT"; -constexpr char TEST_FAKE_CA_CERT_NOT_AFTER[] = "Aug 21 07:51:29 2024 GMT"; + "6b7207bbcf7144eb5c1d22f29e1e0c96879576d15daf1dd54f41440d3b70b17c"; +constexpr char TEST_FAKE_CA_CERT_1_HASH[] = "2c088d4877d568b5090ba125be1f4a45629b22fa"; +constexpr char TEST_FAKE_CA_CERT_SPKI[] = "5j05h/3g7ypaQEyg0A8NAt2+vFnwOlgIuDzaJ47r1j0="; +constexpr char TEST_FAKE_CA_CERT_SERIAL[] = "0906bd50f8b1b94c03926f73f8efbb47e6872886"; +constexpr char TEST_FAKE_CA_CERT_NOT_BEFORE[] = "Aug 21 19:14:03 2024 GMT"; +constexpr char TEST_FAKE_CA_CERT_NOT_AFTER[] = "Aug 21 19:14:03 2026 GMT"; diff --git a/test/common/tls/test_data/fake_ca_key.pem b/test/common/tls/test_data/fake_ca_key.pem index 604aec4a51a0..e5be2c593749 100644 --- a/test/common/tls/test_data/fake_ca_key.pem +++ b/test/common/tls/test_data/fake_ca_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEArggAZnikQjBrKXZLBJ/jOY0lFE9iCfh4qNjhcJy4MyKxPPqO -tmxu1wOrbIquXjdQEsTFiMk1xclQnSrSx9++3pec25ioNomAREjLlCefoCUWzzce -grM0s0shP5FvlKHReaIl6NuVvsMOFZnw5eEnlIubKtapXIkpzegV0lrbkID7dElp -MumhRBDwrUHD3u5//SbWf54uF8J8Dfvt/tKDMTUhcQ+QhHuIUp1JpUBRGc2jfDcU -UctknC4So+fgqJAo381t5SLBj4gM/VUfW0xNZ9rBmXVugRaPw91fPlhym61F3NpI -MLYVZFuLGtngETxyyjqTgajZHCOBxbvu7iwE1QIDAQABAoIBAA/aZr7u6nelFX33 -aqoHLpnFg8Uv3gxud/9Zkl/Bxv3RgTe+01VG12n6yZjfoTav7zlmd2AYhC96QT+v -8PeIKEj6oq1WYKxnJioSP4lFesMJ3eQOb1cUoA5dH7A8vV9axkxAOxfVOPThq9zH -4yvtsL9VYFMsrszhKc+5/pLk9+9XygFPeOTSSP5vdEJ3Z0xiNFZPZfHtB0JoRjxu -p+Imbk0NoFDUSk+2jbVodA2hKrhQp3UVQnQIUcPVJid3bTvHbZI3KkgN7l6ExyTJ -rkUZM/sdL5zAICDAvh1tZfXKzc6qHA6E3yW4uOGneeMQCm1zwP2q5CVcu7NjPhj9 -y6uJ15kCgYEA4xMSyuBT/DpfZ3EI1maSscI2KbvuUQfzTAEv/BlyZkXzM3RK2qQW -y4Ersp16EvFb5sex/HbvLre5qMUbPpYvnNxKI9bgq4+FS/XN5qFJUgZPlWuBkkvp -HyBIufq5OeTc9TGt3N9Ae9Esn3vo1g5uGoqXNXaHDjQo6N/nF8knDU8CgYEAxDMu -dlhHsd8M7cB7Z0LzOwpTCHkeMEZ1tc8CeeFUxeR8RmN8Rz5EFkULTH/f9NqDafS5 -mXjNCg+5tb5QP3q4pwtJHwlcT5zoAr3osBL4NyTGJVI9v95ZUCC6fjD6k00+fREE -5azjLZWRvPFypcbZu2oYcNCEzWNZpM8F9CkoKpsCgYAL2Yb1h1dapkEsSL3JUnj9 -RcFF1ETPfba4lKdIZJuPsr7KRJtTZZS68faxz337VxUQqgMjxaEdswDBSefuEDBT -4zsLO79ltIukNyOTkX8eBK5Kgd21ILj9otWovujDmKnfMcR87jmTPIszl2fDI+Wj -BPB3HcRWfWpVHLoWh6y+CQKBgBLtJQRBi9j6vVKKCN1zNedyHYRpuqHJij1ZlNGR -DQ5x9hMMMcblmMfVLTvZ8g66rYahFu5ZGt5nmfCQRUl6WymyCwG1c3QynKb3DuU9 -TzhykbKz9kT1/AOgxJy7uNBQ2UBTTfeh7+BL1100pWycfBB6MZVgaA8wEEu3tMlS -1w8VAoGASdFh+b6wztdFpjaaec0+HLh8W8roUSmlVd3RRgJf5D385r7Z0HOaRHlh -p28h20ALy4pdEtF4uk/n7kTRATnUUoyUHQlJJLnBiUFHUYxMe4o0hHf7ugWPMQ2X -3+I/z3hvXJEINXm2IO5crL9mAqDwV92RgDC9B5gkgE0gOf/ShjM= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCmvnnGe/JKJa0 +3CxKzcVpb4g1VvLEhp2WHIKEZjiXJH89FFcgnjPBuzIAAJPS2VbVOvkqa4JCO4ti +t+K6PbpjKYNnylBo9Ky+FbzSeUox7Q7PIU2XV9FNdcGzTROWHvqgToxjIcWqoa0p +NBdryMmoCd3AXY3q8Z7OEvIysdHzakh7e5bkpVK23A1b8+FoO6itQ56Y+0HMGJTH +hwHv7ZUTf510RzlMQhV0zc1CwHlt3znGqnuo3zRnWNwYJQJ3tQI/uLfgigc/cBES +05qiwvmwGCD0+nbbb3za6KtAfZkH9SRVsV6eFnamGN5kPgvFKe4P/WNJxoIT/duA +c4uQ+BTpAgMBAAECggEAA0nBuzPm/KEg8Ba1m4tKhfOKe6GSdzDxwgg39FYTKAqd +KRe049TdzwIuCsNNEXJL/fesdMOy7xI5KAaEtYeMJKzI5EdjgG0nQLb2pR/DhIBw +OvO3Gegz8yPFjWqvUAlfTAzHtnfAR+0faI4mxH10sCV/3QY3paabe6Pk+meiwoLG +V0hksDUFfAWKUvc81+3kaMfYTDUsO4dW7XjdNvEkqsq8F3MZkdVPo0X/6HN2yyoB +Vk44BuRNb/QAI4pqZ2rNtNkhwXxVCcOPl8S8RQeqqMGtxi99WgaSDwumhiQ6kNo+ +kpHFycfvb3CFSJKkSw2a0PikgmtkvBr15eeJ3sylWQKBgQDkiotugCX83NJRDQHZ +FUpUgVO540HOQAZWgCPhBnSBowZ/Fpe4wqEemuK56IvX2whQYPEkAm3AIuc8RGgY +dOuPkIcQQVj62xyVrspXLg6eFthUeAhjMa5/dg+SJj5PsUzdxwSf34bnAeh/ostJ +Kg9bQB51LKx7xKkCinf1V++9RwKBgQDZ/KLLUSUXCUV0rYZYC2nGh7x5lN1Crooz +TXI6YyXwd9rv7phNToy9/5u8oWblZaaOFYcs2uxeeg4J+HIFyrcAZ6QHf5NpnV4c +c4bdolcHz7shIi7BKig7v7G96MDlN1ZCq5H/u9m4yGsUD5s/q8XV4Hy4FC9VzLRn +U1uofEP0TwKBgQDkb8NM8VSHOqYSk8DMHubMLvTkck6dfQuYvL6gN1aPGcftkkSX +ThvEPqbvkoztdqcJyMxf5PmUuo6NhAbUo1Gtj5YhXmA1Znxc9XiUyZmc1VLoo44m +sEsuZnDL8eQIvj0J1Ns/fisWjqa5pZwyhpMQ77dCAiRqFjmlK4kaOAqPEwKBgQCb +Irn0+qXr1BRTKl+O72hy+wz+dhxVpYQDaN2fggpxLctpsCNB+WIeofgC8dcZ8RLs +0ZNnL9LClhjBrcfwKUm+BwRstbWCl5VvqCRWPX+0tnkV5o7huA/0HcPwROJq/svs +HNCF8PnNEQ1rtIOnd6cPRHleRDc/17SYSHHV4cI27wKBgFAZoZFJ2aFCwtqEyhtD +EOwc5WIRqxvZ7fBOoyJnEDHIUC01UyqR8+AIh0/WFG+TFNuxJvebx12EdEK+S+iJ +TJ2SNlBywcxHflTC772Iy3IZb+deVUU5YxFIoTNv3Ba4s/1lzfH6HsOlamTulxK6 +VmCaLqe6wc2VJnXd0whBbeJ8 +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/intermediate_ca_cert.crl b/test/common/tls/test_data/intermediate_ca_cert.crl index 8a262920774a..44a5f1a3bedf 100644 --- a/test/common/tls/test_data/intermediate_ca_cert.crl +++ b/test/common/tls/test_data/intermediate_ca_cert.crl @@ -2,12 +2,12 @@ MIICBjCB7wIBATANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEzARBgNV BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoM BEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3Qg -SW50ZXJtZWRpYXRlIENBFw0yMjA4MjIwNzUxMzRaFw0zMjA4MTkwNzUxMzRaMCcw -JQIUS/zr5MA/czykD6IqKh4UQhk46WYXDTIyMDgyMjA3NTEzNFqgDjAMMAoGA1Ud -FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCc7VVA7kvu/H5l3qDvrH5UmSdw1jXr -q6qeKZIYYlJ6XK2l9Q25Cb/nQtiwChILTMItf5unDPX1Erpsti2j06JUlZmrUFOZ -XojqZjKMtUH830msgmm3kavllGERzz7YXzbYFLFVpmHcBw14bV2NxPPYbvoLNHfq -YZ8pgcE6oSSLRytQ0xCCCqJp4h9tAf24zgmBOt4h78e44GKQpMhoZlAxbJu4uocV -qvLuni4Y1/UX0i+IdRUZk5bKOWdzq+Zdc3a8uHK7wuyVfprAM2sgUTUNfYI9TLk3 -Ul68+0tF1A1hTUVeqi/mc32yi8O4ZH8eOL+x3nJyV8flffu+dos+Lhk+ +SW50ZXJtZWRpYXRlIENBFw0yNDA4MjExOTE0MTFaFw0zNDA4MTkxOTE0MTFaMCcw +JQIUCJAk2LFDOO9q+3twtS1w4LExj8sXDTI0MDgyMTE5MTQxMVqgDjAMMAoGA1Ud +FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQADYU+nJ9c8R5pLyMzdaY+EivtxOBb3 +MHihGRc6UI69P5C3dcXRxfRQmpUCGD201c08bU+ZXjJqGm2YE0cO1IgsAfw1wDGS +ebKiqj+MjoPcd6cakAwstfEvTR4Ku0WxUCVIYhIuyHBcuyUmBWrTQEFLmdSSg9ES +LvSxqS8cfe8Y+eEiFyAteWBW36LoUKeiAIsm1QSIlUFLqVgNMx5Ru2klxn71YsN/ +vJ1OT/k85XSTEeQ5gcQJe0yaY/gkU5d1w/ccj5/1G9AF2PQZHZTjfW/sCCkI0ndh +pELxqaEbxrlerHI+2HY83Hv0SsskPBW6s9skKXH3W8FWNPzaEtyUjVNO -----END X509 CRL----- diff --git a/test/common/tls/test_data/intermediate_ca_cert.pem b/test/common/tls/test_data/intermediate_ca_cert.pem index 25a9159b7327..31ca4b4c0e81 100644 --- a/test/common/tls/test_data/intermediate_ca_cert.pem +++ b/test/common/tls/test_data/intermediate_ca_cert.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -MIID7jCCAtagAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapL8wDQYJKoZIhvcNAQEL +MIID7jCCAtagAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWEwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI4WhcNMjQw -ODIxMDc1MTI4WjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDAyWhcNMjYw +ODIxMTkxNDAyWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsM EEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2KN2qre5737wAqiPy6Ub -ZmtMvhbZ0qFJXDLdsvHN7iywA8rdwuUhhL+VhcFukdcxNOCbDNElnXIVHPr61dM7 -v/i1TJ8S8igKlX2zHwa8WXcTZxIvfG6Skgskr3GQwnfQb/D09tlgmV9NfVTexOPj -xLGi+grJf/Lybtq+Pj9yrG1v2NqmHyo/icyi14KvH3OeZ1ClfJX0qmO4mO/wHOpt -sIj56kHqb0ttZD3Ja9ee8H/VmSXVDS/grrBYmnqorvgY7rFunci72kogW892QOgo -K5pMFv1LQlhnJT8Nc2SvyI2M+9fPBLK30KYTJ4e5uicubQIrANDQQ2myjD+oFrVm -HQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU8C1rPT/4/p2oeosaE/i3eZFKT/kwHwYDVR0jBBgwFoAU5YZRBAkl -IKJnd3qqjq32OKSSLyAwDQYJKoZIhvcNAQELBQADggEBAFoJ932JcsdaZbjVNdZI -pOjB8TD2Z8nz4mJAX0aabP8HayGZY3D7A0D4oED5dKmly/R+wKHgpZACiU3lrAPm -DQeozwVzOVqHZjIVjqYLzscF2IhB4NpGQE0f8M5Ute+/9OgbR/RQuiEZ1GluikGV -9LVP1a4mJgYSbvsekVbC+zN0pla2QOS+eQguvThVv8EreGWAjFdEqLDmya8nOwNL -hTI1CSbK89T4IL2pwIj+R9sS31bpIPXlnhgU7bn1+mwBXSE0vhyw9yFGYZi+l84C -gJ1tDP0F8faetBWCkftdLgaczYsJ7iHVDhrqZFC5VP/Ly6nyHjoxcdEEWLTZetUy -yyE= +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr705Izook/Jd2HnXMuDR +imJFZh61VIvdv3ygT1Nj7EW3c+One2lAJ9B1K4ZELZiiwuVE83JPM8Ig+GUg7RJJ +VyCe2HlKQhSB2+JdmV0gFzKjuUaQai5GyAYTgKEWuLV/UQZC1aTIoM3/a+DE2L61 +E/pDW2M9fU+Y7H4KTz3LYYXOEr8521UPzgEG5pwbINGfkyv8KUeclA7fXF2Q8rSP +5VJrqlR2jxvq7ECFFbizcYY4TBU8nBWZH+zZHycqckDywD0qOD9Wnt9uJCh1KPge +H9za165vrmzHxaWg6VKRMuVw9eYapAlKnLS8VI2fSG6YjiU/YOeENN3mYX70bnwq +RQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU3O86c6M7zsm8uUvuaTtzu6ZurucwHwYDVR0jBBgwFoAUD6DPJb1Y +F34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBABT4Q5aqOSbNUhNmx8rm +MYUvTgEZbyS/s6W+htVnpdoOCnGV7CHotKJD35u/hHjiWFj9sRZc1ODAqGi5h2SH +OTrU5NJitzrN5lZdghcZsE7haJYi7qzktg2TlpD59natgDkv/RzL5LM4WU1sjJ9F +HEgbjRi/uV5l9LLoxgS6nnErDI3yj2vHBMdNFVdtU6kWGfU9NeAm9FcM9ZrJVTiQ +vz+dYzqXZRi7e6/8PAAk++UgqXYwALI24ZlCLACFhHQf34KPr/OKdyE8b2f61BZk +u2eKq+6vtW0nLtnEephzM5h3eWm3V51pl4WTOXJXCL7D6A+Zf1YWEofApWT9ChFe +5k8= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/intermediate_ca_cert_chain.crl b/test/common/tls/test_data/intermediate_ca_cert_chain.crl index e70fe1a18360..7b2813b8a1b1 100644 --- a/test/common/tls/test_data/intermediate_ca_cert_chain.crl +++ b/test/common/tls/test_data/intermediate_ca_cert_chain.crl @@ -2,25 +2,25 @@ MIIB+DCB4QIBATANBgkqhkiG9w0BAQsFADB2MQswCQYDVQQGEwJVUzETMBEGA1UE CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwE THlmdDEZMBcGA1UECwwQTHlmdCBFbmdpbmVlcmluZzEQMA4GA1UEAwwHVGVzdCBD -QRcNMjIwODIyMDc1MTM0WhcNMzIwODE5MDc1MTM0WjAnMCUCFHwlLHXpWqV6iPHx -xcw/9PqcWqTCFw0yMjA4MjIwNzUxMzRaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG -9w0BAQsFAAOCAQEArv50n9iLaX9Vei1ldedumBtvl3DomOUtHPxb2YOPRGd9EKWa -rNtZ9pWibwLLekNoc8zNhNw2KFDhA8i6/af6BuK2O3MNMw9gbHKJnILkXJapame1 -DkEEORABNuBRpgAWrQF6GaVkFp94NjfcGHbX8QCmYEueArEBEReZRtOHhNSjFdaP -JU+hiueoNtEcOg8mX3w8OnYq11Rwmf440veRxupgrbcL4W8sCg3IbydUUvy/R0Jo -3t9bRFYd2Jj4J0idxD7HSku8pCRjCmlQcicso+G/G6oqoduJ29O8hfliqp76mjeL -HSVSWUXy9f1yTr0BZ0/eY1yj84mtK8Tp3FRELg== +QRcNMjQwODIxMTkxNDExWhcNMzQwODE5MTkxNDExWjAnMCUCFDqzcIiLuhgHHdG+ +r3TnjGE+SQVlFw0yNDA4MjExOTE0MTFaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG +9w0BAQsFAAOCAQEAPe7WB3XT2rBs/2K+/G7s0EAeIlgdv2H/QXhBb3gLA+mUpLTH +cPgvkdnSEKw6x6g+erI1pAqew6ZiEbaSf4SLCYKTQhpzHH2cmwJ+chwplFnSIcVl +2FQOmQ1xf/lIZRf3hgPTGTzws6ptBoPGsOo+IqQ06+ggCAXXuHoNhHzKAkw3k5g+ +W+fPfQEUkJWCrDmM7Nhu50bf+cSPQl9qw4Z42K86pqp7w1sw5STo4Lp2MoKCT/3b +8X4wBB8hTvMdOJozwUjWnf8PbgXRTOfuoCR9eycLTbMUS1GazYKLfjMLESFR3rqp +tnY4u9DRKVqDzKPVPzz8BXzdJicwWlqVdO2I+w== -----END X509 CRL----- -----BEGIN X509 CRL----- MIICBjCB7wIBATANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEzARBgNV BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoM BEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3Qg -SW50ZXJtZWRpYXRlIENBFw0yMjA4MjIwNzUxMzRaFw0zMjA4MTkwNzUxMzRaMCcw -JQIUS/zr5MA/czykD6IqKh4UQhk46WYXDTIyMDgyMjA3NTEzNFqgDjAMMAoGA1Ud -FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCc7VVA7kvu/H5l3qDvrH5UmSdw1jXr -q6qeKZIYYlJ6XK2l9Q25Cb/nQtiwChILTMItf5unDPX1Erpsti2j06JUlZmrUFOZ -XojqZjKMtUH830msgmm3kavllGERzz7YXzbYFLFVpmHcBw14bV2NxPPYbvoLNHfq -YZ8pgcE6oSSLRytQ0xCCCqJp4h9tAf24zgmBOt4h78e44GKQpMhoZlAxbJu4uocV -qvLuni4Y1/UX0i+IdRUZk5bKOWdzq+Zdc3a8uHK7wuyVfprAM2sgUTUNfYI9TLk3 -Ul68+0tF1A1hTUVeqi/mc32yi8O4ZH8eOL+x3nJyV8flffu+dos+Lhk+ +SW50ZXJtZWRpYXRlIENBFw0yNDA4MjExOTE0MTFaFw0zNDA4MTkxOTE0MTFaMCcw +JQIUCJAk2LFDOO9q+3twtS1w4LExj8sXDTI0MDgyMTE5MTQxMVqgDjAMMAoGA1Ud +FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQADYU+nJ9c8R5pLyMzdaY+EivtxOBb3 +MHihGRc6UI69P5C3dcXRxfRQmpUCGD201c08bU+ZXjJqGm2YE0cO1IgsAfw1wDGS +ebKiqj+MjoPcd6cakAwstfEvTR4Ku0WxUCVIYhIuyHBcuyUmBWrTQEFLmdSSg9ES +LvSxqS8cfe8Y+eEiFyAteWBW36LoUKeiAIsm1QSIlUFLqVgNMx5Ru2klxn71YsN/ +vJ1OT/k85XSTEeQ5gcQJe0yaY/gkU5d1w/ccj5/1G9AF2PQZHZTjfW/sCCkI0ndh +pELxqaEbxrlerHI+2HY83Hv0SsskPBW6s9skKXH3W8FWNPzaEtyUjVNO -----END X509 CRL----- diff --git a/test/common/tls/test_data/intermediate_ca_cert_chain.pem b/test/common/tls/test_data/intermediate_ca_cert_chain.pem index 1be173f41e36..4a9bac05c253 100644 --- a/test/common/tls/test_data/intermediate_ca_cert_chain.pem +++ b/test/common/tls/test_data/intermediate_ca_cert_chain.pem @@ -1,47 +1,47 @@ -----BEGIN CERTIFICATE----- -MIID7jCCAtagAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapL8wDQYJKoZIhvcNAQEL +MIID7jCCAtagAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWEwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI4WhcNMjQw -ODIxMDc1MTI4WjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDAyWhcNMjYw +ODIxMTkxNDAyWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsM EEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2KN2qre5737wAqiPy6Ub -ZmtMvhbZ0qFJXDLdsvHN7iywA8rdwuUhhL+VhcFukdcxNOCbDNElnXIVHPr61dM7 -v/i1TJ8S8igKlX2zHwa8WXcTZxIvfG6Skgskr3GQwnfQb/D09tlgmV9NfVTexOPj -xLGi+grJf/Lybtq+Pj9yrG1v2NqmHyo/icyi14KvH3OeZ1ClfJX0qmO4mO/wHOpt -sIj56kHqb0ttZD3Ja9ee8H/VmSXVDS/grrBYmnqorvgY7rFunci72kogW892QOgo -K5pMFv1LQlhnJT8Nc2SvyI2M+9fPBLK30KYTJ4e5uicubQIrANDQQ2myjD+oFrVm -HQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU8C1rPT/4/p2oeosaE/i3eZFKT/kwHwYDVR0jBBgwFoAU5YZRBAkl -IKJnd3qqjq32OKSSLyAwDQYJKoZIhvcNAQELBQADggEBAFoJ932JcsdaZbjVNdZI -pOjB8TD2Z8nz4mJAX0aabP8HayGZY3D7A0D4oED5dKmly/R+wKHgpZACiU3lrAPm -DQeozwVzOVqHZjIVjqYLzscF2IhB4NpGQE0f8M5Ute+/9OgbR/RQuiEZ1GluikGV -9LVP1a4mJgYSbvsekVbC+zN0pla2QOS+eQguvThVv8EreGWAjFdEqLDmya8nOwNL -hTI1CSbK89T4IL2pwIj+R9sS31bpIPXlnhgU7bn1+mwBXSE0vhyw9yFGYZi+l84C -gJ1tDP0F8faetBWCkftdLgaczYsJ7iHVDhrqZFC5VP/Ly6nyHjoxcdEEWLTZetUy -yyE= +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr705Izook/Jd2HnXMuDR +imJFZh61VIvdv3ygT1Nj7EW3c+One2lAJ9B1K4ZELZiiwuVE83JPM8Ig+GUg7RJJ +VyCe2HlKQhSB2+JdmV0gFzKjuUaQai5GyAYTgKEWuLV/UQZC1aTIoM3/a+DE2L61 +E/pDW2M9fU+Y7H4KTz3LYYXOEr8521UPzgEG5pwbINGfkyv8KUeclA7fXF2Q8rSP +5VJrqlR2jxvq7ECFFbizcYY4TBU8nBWZH+zZHycqckDywD0qOD9Wnt9uJCh1KPge +H9za165vrmzHxaWg6VKRMuVw9eYapAlKnLS8VI2fSG6YjiU/YOeENN3mYX70bnwq +RQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU3O86c6M7zsm8uUvuaTtzu6ZurucwHwYDVR0jBBgwFoAUD6DPJb1Y +F34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBABT4Q5aqOSbNUhNmx8rm +MYUvTgEZbyS/s6W+htVnpdoOCnGV7CHotKJD35u/hHjiWFj9sRZc1ODAqGi5h2SH +OTrU5NJitzrN5lZdghcZsE7haJYi7qzktg2TlpD59natgDkv/RzL5LM4WU1sjJ9F +HEgbjRi/uV5l9LLoxgS6nnErDI3yj2vHBMdNFVdtU6kWGfU9NeAm9FcM9ZrJVTiQ +vz+dYzqXZRi7e6/8PAAk++UgqXYwALI24ZlCLACFhHQf34KPr/OKdyE8b2f61BZk +u2eKq+6vtW0nLtnEephzM5h3eWm3V51pl4WTOXJXCL7D6A+Zf1YWEofApWT9ChFe +5k8= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl.pem b/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl.pem index 418648fceab1..654128b24424 100644 --- a/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl.pem +++ b/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl.pem @@ -1,60 +1,60 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID7jCCAtagAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapL8wDQYJKoZIhvcNAQEL +MIID7jCCAtagAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWEwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI4WhcNMjQw -ODIxMDc1MTI4WjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDAyWhcNMjYw +ODIxMTkxNDAyWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsM EEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2KN2qre5737wAqiPy6Ub -ZmtMvhbZ0qFJXDLdsvHN7iywA8rdwuUhhL+VhcFukdcxNOCbDNElnXIVHPr61dM7 -v/i1TJ8S8igKlX2zHwa8WXcTZxIvfG6Skgskr3GQwnfQb/D09tlgmV9NfVTexOPj -xLGi+grJf/Lybtq+Pj9yrG1v2NqmHyo/icyi14KvH3OeZ1ClfJX0qmO4mO/wHOpt -sIj56kHqb0ttZD3Ja9ee8H/VmSXVDS/grrBYmnqorvgY7rFunci72kogW892QOgo -K5pMFv1LQlhnJT8Nc2SvyI2M+9fPBLK30KYTJ4e5uicubQIrANDQQ2myjD+oFrVm -HQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU8C1rPT/4/p2oeosaE/i3eZFKT/kwHwYDVR0jBBgwFoAU5YZRBAkl -IKJnd3qqjq32OKSSLyAwDQYJKoZIhvcNAQELBQADggEBAFoJ932JcsdaZbjVNdZI -pOjB8TD2Z8nz4mJAX0aabP8HayGZY3D7A0D4oED5dKmly/R+wKHgpZACiU3lrAPm -DQeozwVzOVqHZjIVjqYLzscF2IhB4NpGQE0f8M5Ute+/9OgbR/RQuiEZ1GluikGV -9LVP1a4mJgYSbvsekVbC+zN0pla2QOS+eQguvThVv8EreGWAjFdEqLDmya8nOwNL -hTI1CSbK89T4IL2pwIj+R9sS31bpIPXlnhgU7bn1+mwBXSE0vhyw9yFGYZi+l84C -gJ1tDP0F8faetBWCkftdLgaczYsJ7iHVDhrqZFC5VP/Ly6nyHjoxcdEEWLTZetUy -yyE= +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr705Izook/Jd2HnXMuDR +imJFZh61VIvdv3ygT1Nj7EW3c+One2lAJ9B1K4ZELZiiwuVE83JPM8Ig+GUg7RJJ +VyCe2HlKQhSB2+JdmV0gFzKjuUaQai5GyAYTgKEWuLV/UQZC1aTIoM3/a+DE2L61 +E/pDW2M9fU+Y7H4KTz3LYYXOEr8521UPzgEG5pwbINGfkyv8KUeclA7fXF2Q8rSP +5VJrqlR2jxvq7ECFFbizcYY4TBU8nBWZH+zZHycqckDywD0qOD9Wnt9uJCh1KPge +H9za165vrmzHxaWg6VKRMuVw9eYapAlKnLS8VI2fSG6YjiU/YOeENN3mYX70bnwq +RQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU3O86c6M7zsm8uUvuaTtzu6ZurucwHwYDVR0jBBgwFoAUD6DPJb1Y +F34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBABT4Q5aqOSbNUhNmx8rm +MYUvTgEZbyS/s6W+htVnpdoOCnGV7CHotKJD35u/hHjiWFj9sRZc1ODAqGi5h2SH +OTrU5NJitzrN5lZdghcZsE7haJYi7qzktg2TlpD59natgDkv/RzL5LM4WU1sjJ9F +HEgbjRi/uV5l9LLoxgS6nnErDI3yj2vHBMdNFVdtU6kWGfU9NeAm9FcM9ZrJVTiQ +vz+dYzqXZRi7e6/8PAAk++UgqXYwALI24ZlCLACFhHQf34KPr/OKdyE8b2f61BZk +u2eKq+6vtW0nLtnEephzM5h3eWm3V51pl4WTOXJXCL7D6A+Zf1YWEofApWT9ChFe +5k8= -----END CERTIFICATE----- -----BEGIN X509 CRL----- MIICBjCB7wIBATANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEzARBgNV BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoM BEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3Qg -SW50ZXJtZWRpYXRlIENBFw0yMjA4MjIwNzUxMzRaFw0zMjA4MTkwNzUxMzRaMCcw -JQIUS/zr5MA/czykD6IqKh4UQhk46WYXDTIyMDgyMjA3NTEzNFqgDjAMMAoGA1Ud -FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCc7VVA7kvu/H5l3qDvrH5UmSdw1jXr -q6qeKZIYYlJ6XK2l9Q25Cb/nQtiwChILTMItf5unDPX1Erpsti2j06JUlZmrUFOZ -XojqZjKMtUH830msgmm3kavllGERzz7YXzbYFLFVpmHcBw14bV2NxPPYbvoLNHfq -YZ8pgcE6oSSLRytQ0xCCCqJp4h9tAf24zgmBOt4h78e44GKQpMhoZlAxbJu4uocV -qvLuni4Y1/UX0i+IdRUZk5bKOWdzq+Zdc3a8uHK7wuyVfprAM2sgUTUNfYI9TLk3 -Ul68+0tF1A1hTUVeqi/mc32yi8O4ZH8eOL+x3nJyV8flffu+dos+Lhk+ +SW50ZXJtZWRpYXRlIENBFw0yNDA4MjExOTE0MTFaFw0zNDA4MTkxOTE0MTFaMCcw +JQIUCJAk2LFDOO9q+3twtS1w4LExj8sXDTI0MDgyMTE5MTQxMVqgDjAMMAoGA1Ud +FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQADYU+nJ9c8R5pLyMzdaY+EivtxOBb3 +MHihGRc6UI69P5C3dcXRxfRQmpUCGD201c08bU+ZXjJqGm2YE0cO1IgsAfw1wDGS +ebKiqj+MjoPcd6cakAwstfEvTR4Ku0WxUCVIYhIuyHBcuyUmBWrTQEFLmdSSg9ES +LvSxqS8cfe8Y+eEiFyAteWBW36LoUKeiAIsm1QSIlUFLqVgNMx5Ru2klxn71YsN/ +vJ1OT/k85XSTEeQ5gcQJe0yaY/gkU5d1w/ccj5/1G9AF2PQZHZTjfW/sCCkI0ndh +pELxqaEbxrlerHI+2HY83Hv0SsskPBW6s9skKXH3W8FWNPzaEtyUjVNO -----END X509 CRL----- diff --git a/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl_chain.pem b/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl_chain.pem index 4d9c25f55813..89fe06d656b5 100644 --- a/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl_chain.pem +++ b/test/common/tls/test_data/intermediate_ca_cert_chain_with_crl_chain.pem @@ -1,73 +1,73 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID7jCCAtagAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapL8wDQYJKoZIhvcNAQEL +MIID7jCCAtagAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWEwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI4WhcNMjQw -ODIxMDc1MTI4WjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDAyWhcNMjYw +ODIxMTkxNDAyWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsM EEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2KN2qre5737wAqiPy6Ub -ZmtMvhbZ0qFJXDLdsvHN7iywA8rdwuUhhL+VhcFukdcxNOCbDNElnXIVHPr61dM7 -v/i1TJ8S8igKlX2zHwa8WXcTZxIvfG6Skgskr3GQwnfQb/D09tlgmV9NfVTexOPj -xLGi+grJf/Lybtq+Pj9yrG1v2NqmHyo/icyi14KvH3OeZ1ClfJX0qmO4mO/wHOpt -sIj56kHqb0ttZD3Ja9ee8H/VmSXVDS/grrBYmnqorvgY7rFunci72kogW892QOgo -K5pMFv1LQlhnJT8Nc2SvyI2M+9fPBLK30KYTJ4e5uicubQIrANDQQ2myjD+oFrVm -HQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU8C1rPT/4/p2oeosaE/i3eZFKT/kwHwYDVR0jBBgwFoAU5YZRBAkl -IKJnd3qqjq32OKSSLyAwDQYJKoZIhvcNAQELBQADggEBAFoJ932JcsdaZbjVNdZI -pOjB8TD2Z8nz4mJAX0aabP8HayGZY3D7A0D4oED5dKmly/R+wKHgpZACiU3lrAPm -DQeozwVzOVqHZjIVjqYLzscF2IhB4NpGQE0f8M5Ute+/9OgbR/RQuiEZ1GluikGV -9LVP1a4mJgYSbvsekVbC+zN0pla2QOS+eQguvThVv8EreGWAjFdEqLDmya8nOwNL -hTI1CSbK89T4IL2pwIj+R9sS31bpIPXlnhgU7bn1+mwBXSE0vhyw9yFGYZi+l84C -gJ1tDP0F8faetBWCkftdLgaczYsJ7iHVDhrqZFC5VP/Ly6nyHjoxcdEEWLTZetUy -yyE= +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr705Izook/Jd2HnXMuDR +imJFZh61VIvdv3ygT1Nj7EW3c+One2lAJ9B1K4ZELZiiwuVE83JPM8Ig+GUg7RJJ +VyCe2HlKQhSB2+JdmV0gFzKjuUaQai5GyAYTgKEWuLV/UQZC1aTIoM3/a+DE2L61 +E/pDW2M9fU+Y7H4KTz3LYYXOEr8521UPzgEG5pwbINGfkyv8KUeclA7fXF2Q8rSP +5VJrqlR2jxvq7ECFFbizcYY4TBU8nBWZH+zZHycqckDywD0qOD9Wnt9uJCh1KPge +H9za165vrmzHxaWg6VKRMuVw9eYapAlKnLS8VI2fSG6YjiU/YOeENN3mYX70bnwq +RQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU3O86c6M7zsm8uUvuaTtzu6ZurucwHwYDVR0jBBgwFoAUD6DPJb1Y +F34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBABT4Q5aqOSbNUhNmx8rm +MYUvTgEZbyS/s6W+htVnpdoOCnGV7CHotKJD35u/hHjiWFj9sRZc1ODAqGi5h2SH +OTrU5NJitzrN5lZdghcZsE7haJYi7qzktg2TlpD59natgDkv/RzL5LM4WU1sjJ9F +HEgbjRi/uV5l9LLoxgS6nnErDI3yj2vHBMdNFVdtU6kWGfU9NeAm9FcM9ZrJVTiQ +vz+dYzqXZRi7e6/8PAAk++UgqXYwALI24ZlCLACFhHQf34KPr/OKdyE8b2f61BZk +u2eKq+6vtW0nLtnEephzM5h3eWm3V51pl4WTOXJXCL7D6A+Zf1YWEofApWT9ChFe +5k8= -----END CERTIFICATE----- -----BEGIN X509 CRL----- MIIB+DCB4QIBATANBgkqhkiG9w0BAQsFADB2MQswCQYDVQQGEwJVUzETMBEGA1UE CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwE THlmdDEZMBcGA1UECwwQTHlmdCBFbmdpbmVlcmluZzEQMA4GA1UEAwwHVGVzdCBD -QRcNMjIwODIyMDc1MTM0WhcNMzIwODE5MDc1MTM0WjAnMCUCFHwlLHXpWqV6iPHx -xcw/9PqcWqTCFw0yMjA4MjIwNzUxMzRaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG -9w0BAQsFAAOCAQEArv50n9iLaX9Vei1ldedumBtvl3DomOUtHPxb2YOPRGd9EKWa -rNtZ9pWibwLLekNoc8zNhNw2KFDhA8i6/af6BuK2O3MNMw9gbHKJnILkXJapame1 -DkEEORABNuBRpgAWrQF6GaVkFp94NjfcGHbX8QCmYEueArEBEReZRtOHhNSjFdaP -JU+hiueoNtEcOg8mX3w8OnYq11Rwmf440veRxupgrbcL4W8sCg3IbydUUvy/R0Jo -3t9bRFYd2Jj4J0idxD7HSku8pCRjCmlQcicso+G/G6oqoduJ29O8hfliqp76mjeL -HSVSWUXy9f1yTr0BZ0/eY1yj84mtK8Tp3FRELg== +QRcNMjQwODIxMTkxNDExWhcNMzQwODE5MTkxNDExWjAnMCUCFDqzcIiLuhgHHdG+ +r3TnjGE+SQVlFw0yNDA4MjExOTE0MTFaoA4wDDAKBgNVHRQEAwIBADANBgkqhkiG +9w0BAQsFAAOCAQEAPe7WB3XT2rBs/2K+/G7s0EAeIlgdv2H/QXhBb3gLA+mUpLTH +cPgvkdnSEKw6x6g+erI1pAqew6ZiEbaSf4SLCYKTQhpzHH2cmwJ+chwplFnSIcVl +2FQOmQ1xf/lIZRf3hgPTGTzws6ptBoPGsOo+IqQ06+ggCAXXuHoNhHzKAkw3k5g+ +W+fPfQEUkJWCrDmM7Nhu50bf+cSPQl9qw4Z42K86pqp7w1sw5STo4Lp2MoKCT/3b +8X4wBB8hTvMdOJozwUjWnf8PbgXRTOfuoCR9eycLTbMUS1GazYKLfjMLESFR3rqp +tnY4u9DRKVqDzKPVPzz8BXzdJicwWlqVdO2I+w== -----END X509 CRL----- -----BEGIN X509 CRL----- MIICBjCB7wIBATANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEzARBgNV BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoM BEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3Qg -SW50ZXJtZWRpYXRlIENBFw0yMjA4MjIwNzUxMzRaFw0zMjA4MTkwNzUxMzRaMCcw -JQIUS/zr5MA/czykD6IqKh4UQhk46WYXDTIyMDgyMjA3NTEzNFqgDjAMMAoGA1Ud -FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCc7VVA7kvu/H5l3qDvrH5UmSdw1jXr -q6qeKZIYYlJ6XK2l9Q25Cb/nQtiwChILTMItf5unDPX1Erpsti2j06JUlZmrUFOZ -XojqZjKMtUH830msgmm3kavllGERzz7YXzbYFLFVpmHcBw14bV2NxPPYbvoLNHfq -YZ8pgcE6oSSLRytQ0xCCCqJp4h9tAf24zgmBOt4h78e44GKQpMhoZlAxbJu4uocV -qvLuni4Y1/UX0i+IdRUZk5bKOWdzq+Zdc3a8uHK7wuyVfprAM2sgUTUNfYI9TLk3 -Ul68+0tF1A1hTUVeqi/mc32yi8O4ZH8eOL+x3nJyV8flffu+dos+Lhk+ +SW50ZXJtZWRpYXRlIENBFw0yNDA4MjExOTE0MTFaFw0zNDA4MTkxOTE0MTFaMCcw +JQIUCJAk2LFDOO9q+3twtS1w4LExj8sXDTI0MDgyMTE5MTQxMVqgDjAMMAoGA1Ud +FAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQADYU+nJ9c8R5pLyMzdaY+EivtxOBb3 +MHihGRc6UI69P5C3dcXRxfRQmpUCGD201c08bU+ZXjJqGm2YE0cO1IgsAfw1wDGS +ebKiqj+MjoPcd6cakAwstfEvTR4Ku0WxUCVIYhIuyHBcuyUmBWrTQEFLmdSSg9ES +LvSxqS8cfe8Y+eEiFyAteWBW36LoUKeiAIsm1QSIlUFLqVgNMx5Ru2klxn71YsN/ +vJ1OT/k85XSTEeQ5gcQJe0yaY/gkU5d1w/ccj5/1G9AF2PQZHZTjfW/sCCkI0ndh +pELxqaEbxrlerHI+2HY83Hv0SsskPBW6s9skKXH3W8FWNPzaEtyUjVNO -----END X509 CRL----- diff --git a/test/common/tls/test_data/intermediate_ca_cert_info.h b/test/common/tls/test_data/intermediate_ca_cert_info.h index bfec52c1a048..70bc50ae2afa 100644 --- a/test/common/tls/test_data/intermediate_ca_cert_info.h +++ b/test/common/tls/test_data/intermediate_ca_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_INTERMEDIATE_CA_CERT_256_HASH[] = - "91b048a0941a41740a243a8db4509ba31abdf0c00a1aa9fa36fe2e28d029b22f"; -constexpr char TEST_INTERMEDIATE_CA_CERT_1_HASH[] = "635057edf7e2eabf863ab7fb5748a443aaeffee6"; -constexpr char TEST_INTERMEDIATE_CA_CERT_SPKI[] = "ZDXblcuF6baBH/AjCGwH7ADE9pyP4WXTWX9s92hPYXE="; -constexpr char TEST_INTERMEDIATE_CA_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4bf"; -constexpr char TEST_INTERMEDIATE_CA_CERT_NOT_BEFORE[] = "Aug 22 07:51:28 2022 GMT"; -constexpr char TEST_INTERMEDIATE_CA_CERT_NOT_AFTER[] = "Aug 21 07:51:28 2024 GMT"; + "fa83825871e3671fe862ad77e888828734dd7f9e6bdee75edd51904479258b06"; +constexpr char TEST_INTERMEDIATE_CA_CERT_1_HASH[] = "9f79dbce9f962d4540fe9069188e06e8dce3a4a7"; +constexpr char TEST_INTERMEDIATE_CA_CERT_SPKI[] = "1X86BGVlx5ub3r34HvKuZ47A2OMT1Z9cRUSHc1mkrzE="; +constexpr char TEST_INTERMEDIATE_CA_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490561"; +constexpr char TEST_INTERMEDIATE_CA_CERT_NOT_BEFORE[] = "Aug 21 19:14:02 2024 GMT"; +constexpr char TEST_INTERMEDIATE_CA_CERT_NOT_AFTER[] = "Aug 21 19:14:02 2026 GMT"; diff --git a/test/common/tls/test_data/intermediate_ca_key.pem b/test/common/tls/test_data/intermediate_ca_key.pem index 401b9a27ed26..9a71e2bf5c8e 100644 --- a/test/common/tls/test_data/intermediate_ca_key.pem +++ b/test/common/tls/test_data/intermediate_ca_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA2KN2qre5737wAqiPy6UbZmtMvhbZ0qFJXDLdsvHN7iywA8rd -wuUhhL+VhcFukdcxNOCbDNElnXIVHPr61dM7v/i1TJ8S8igKlX2zHwa8WXcTZxIv -fG6Skgskr3GQwnfQb/D09tlgmV9NfVTexOPjxLGi+grJf/Lybtq+Pj9yrG1v2Nqm -Hyo/icyi14KvH3OeZ1ClfJX0qmO4mO/wHOptsIj56kHqb0ttZD3Ja9ee8H/VmSXV -DS/grrBYmnqorvgY7rFunci72kogW892QOgoK5pMFv1LQlhnJT8Nc2SvyI2M+9fP -BLK30KYTJ4e5uicubQIrANDQQ2myjD+oFrVmHQIDAQABAoIBAEyiLmUfjt+AiMh3 -9j30jufBBymrDayrrza1K6WUUeNx3WXKCn5Z7Wx3FR52mXVvqRFqbo6vIV47r+pL -ghXHnjg/c2rCTsJola3iBE3yZQhEzhFE5pVey+xrkrOZObsBBTPECfOUW86FXvT5 -47/EWZsHt345+KORPl8mc+uzKA6EFOvfQGcSzVWur34Xq9fbK3tU5D4SbNBl6JNr -VjCQGC0nTkTKhbG+AU+iOb4TJKg6psbgZI46abbgmNa3VSZe8T8sYEnEKRhDn6nu -XzbmrKuRm+UMBCXVT5u7WQZsyNaGy+pO1xCEwqQ3rtBExc6QZ5PspE8nZOsxOEpN -gQAjmWUCgYEA/HCv8rKIrdDsG8PVyFpPvVQJ0U9idqqMMzP/nMaoO4vccgeW2mO3 -N5pcY1i1VNCElHOfyzSHc5w2Lkhcp4B+zsl6MrpJOvfhlsInPROtUOueMDSDxKIJ -Fcjz6LBpVB3R4rWsvaeePymasGA2yj90k0dcB8BmBuOa9SREnKutULsCgYEA27GI -IQpWwyeI01mxzhhbWnX1xR1p92oYuk6DJBCWfJnAxzl8u9TmQX9qGgVubln8FSWq -TvzxtIlY2l57pan5EUZb0u1rngg4ordIsUL8JVRM0GEcp9rf5LN8dmE8L6XVjhp0 -EPCk0WyMYoZvPxqDt7uPf3LGSNqy6EGyxIGyAwcCgYEAv1twlMnvP8tCX52o3bJQ -BdXBh2/k1M1db6b4GdChUFop5iqImM3D4htZ81kYQ8244otvUutjzihZDeZ+jd6i -wYAK6I872b5zvAM7GVpkJBYnmKUGSbUGrAPjmLy5azEbm/5Zjn6UP477Gr4kalWF -uer7AUlATfKU0UUH2bdtrucCgYBgfyAd8x6c5ZaRzsnsjoJBv6JODFdpFy75Vlb/ -1lFjNV2ZpESHdEIW7tI5z7zrt5aj60FdJHk+JT3j3LBO2dPOpKrcgPBOH6pQvlSt -l5CNDPQYay9dAyRonfXDQX5gJ2Uf37qvXiPm4Njgxc/DVfAZGccz4cP6aCVBIupU -qer4rQKBgEcBC4HTHX43M81l876lpNho+DKptcWIY700o49wi6GF1IzSzsiHDxL7 -GPfnWDRoU7nbRdFd/PxpKoK5KURgF52vyWxFpwEnw3Y2+ZGx5JV97+Mod/IpPe6B -TGI0bmdJN96X8zKmZIrDd1FNPEFnqhBY9cYhnEmZ2T9tkCWyQ/+p ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvvTkjOiiT8l3Y +edcy4NGKYkVmHrVUi92/fKBPU2PsRbdz46d7aUAn0HUrhkQtmKLC5UTzck8zwiD4 +ZSDtEklXIJ7YeUpCFIHb4l2ZXSAXMqO5RpBqLkbIBhOAoRa4tX9RBkLVpMigzf9r +4MTYvrUT+kNbYz19T5jsfgpPPcthhc4SvznbVQ/OAQbmnBsg0Z+TK/wpR5yUDt9c +XZDytI/lUmuqVHaPG+rsQIUVuLNxhjhMFTycFZkf7NkfJypyQPLAPSo4P1ae324k +KHUo+B4f3NrXrm+ubMfFpaDpUpEy5XD15hqkCUqctLxUjZ9IbpiOJT9g54Q03eZh +fvRufCpFAgMBAAECggEAB8s6Dfxl0U3l6JRavWhoEp2SG1nQS+waDQR/bZUysMdU +wACALIJ59GoT0DbXrjf/O+qEGNHgflilMq71e14cv470TIBwkSasra5H3WXaZvz5 +ct2UyQi9XeCbG9DJG6788wB2lVgGB8+q/MNOp5gpmrW2KAbqMrUFgLOETIhejTgZ +gJsMGE45rdICyS/dTh0/qWtuoNq6VLg1RBJPToqG6BQFIH9zMwuOxtLDfyRaGCfn +VeS5eShdYyBP/nQIkG/7ucBJFiTpdbUqNAhDC+EzKRfVfNI03RsFSykF0HG5r5bo +nSNJpFERBa4JFO2shVOEPgYJn/aZkCLUxC4KM/L4DwKBgQDtos51GypD26RtJGmz +NEHkm4s1sLCOPMMjjluZYSPBneh4LaqgaN7aILzbOtfRq+TvcG6ndl1NcnVJRwUp +olOpV98CBeQcbR7nPPtVujBGcVUucDQEmpEy/G+DYONPGZ0xq8Wr5PSU4fbnCoG5 +eHWcvRwNNbmllhKp47wnzSLRVwKBgQC9UebBBTFFlDuxp4o4iixPO4c6cfPrHT+r +C5Felui2cck74siaQab+4amY3TnSAVjtzYJDEZBvqI+kCO0Fv0agwseDXTTnbyG6 +uEcOEZ2xhJrpV0Ex7mP6w8+M3fSNr7Y9Qnj4iTPcHCa2KB0fG38fABbVxjizcOoS +hVpN+XTTwwKBgBEnjpXflyZ85ZrHZSX9oMAbBmqizawG8ONRNIWXAJjKiGych1O7 +HlNKx7dfwRKuwQET8bj/D2820wauLM47nKR95mhj+nqe2ftBaLdgkHmVVtvaV7b5 +XX/7vyURynb8V1+tkcB977YLteIp3QGBk6Pz9uFxPmyYr9I50WxiH6BTAoGAIYMq +9sYFh8yKmJMQu5tx5oCiGm1rgRYHXC7LB9Rs00bnGUu2uN+gQQQPMnkOsCb+5/F1 ++otUZv+Olbniwx6t0O1Jxe4s3D7m2JegNFRX9sGDboS8jKsnVY9t4QC1NpOBDe0D +XvNik7cD/0Cwjv4eDY3FfQf+p3z4YljquFzNGmMCgYEAslklXfqJFROtBNHeRpP1 +1FQpgsc6IDqCXK/L4GOS1XCzVaXOL5wRLbdDf8IOPG6/CgU5lRrGluCZ2EZGkGj5 +raFOkyP6zleb2m7Q9CAUdhqtj0b/4rpALtefMNcI6gRFq4o7kSmGoaM+wi2vWIc2 +TjFeGoUXA+YYfeK/LLizZBg= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/keyusage_cert_sign_cert.pem b/test/common/tls/test_data/keyusage_cert_sign_cert.pem index d79305cf9929..b0244c9c5d6f 100644 --- a/test/common/tls/test_data/keyusage_cert_sign_cert.pem +++ b/test/common/tls/test_data/keyusage_cert_sign_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -IxufGc28uas= +BggrBgEFBQcDATAdBgNVHQ4EFgQUICeYGoZFMVnDGMVZzjmX/Xe6MtAwHwYDVR0j +BBgwFoAUD6DPJb1YF34IHnaYZclDrx9PhVYwFgYHKgMEBQYHCAQLDAlTb21ldGhp +bmcwEAYHKgMEBQYHCQQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIWizlP9uwMD +a0t8grAarhEADm6TvoPzakONuzWKlPvFookYjE9qfTNmWXCyzGcIl026M4wz4Ecv +5lYDbE0AUOk6MHSbtRM0ofL9YDmXcyNTJ5zpesQi0fJww7h0Hxn9lOmRURXcYcmN +aRFSYJnSrNxlPQFFZIVNwCH4jra9XEbIYr0b3adxpIsZUWqfTxhIatT94kSKqDb0 +TmylpZkxgALe4vVQQlSwMDx1rTX4fJZoAaecqKnSrAJ4CAdB1d6jfDGR2GVHHxeW +L/LlGqdfRiPXASm63JJcOM8Ullb8/tX4eKQQplyo839RVO5VCqvEkjyb7kHhyBrf +8BeUEPoS/bE= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/keyusage_cert_sign_cert_info.h b/test/common/tls/test_data/keyusage_cert_sign_cert_info.h index a15981b97ff0..272dde5b187a 100644 --- a/test/common/tls/test_data/keyusage_cert_sign_cert_info.h +++ b/test/common/tls/test_data/keyusage_cert_sign_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_256_HASH[] = - "d612e1541ec0f454c90867ede824afd20b252b11d316089cc7b31ec40edaf9ca"; -constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_1_HASH[] = "bc1bdd79249675ad7e2052b1ea53d53f82e78544"; -constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_SPKI[] = "GqxFOg7GUQqa5IiNgUfYIEYXSd/K1ykjxTuPua5W4Rk="; -constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4ce"; -constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_NOT_BEFORE[] = "Aug 22 07:51:34 2022 GMT"; -constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_NOT_AFTER[] = "Aug 21 07:51:34 2024 GMT"; + "1a646ed8760e3e07e0c1755e19b792bbd085dff50733ea1cf69f46d56e5e97ab"; +constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_1_HASH[] = "eb35ffed0d80020533166576720c2cece88cae54"; +constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_SPKI[] = "33i6ed560I0dCuyxijPusbUUDi1ES8KJphNv2zJrLJc="; +constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e49057b"; +constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_NOT_BEFORE[] = "Aug 21 19:14:11 2024 GMT"; +constexpr char TEST_KEYUSAGE_CERT_SIGN_CERT_NOT_AFTER[] = "Aug 21 19:14:11 2026 GMT"; diff --git a/test/common/tls/test_data/keyusage_cert_sign_key.pem b/test/common/tls/test_data/keyusage_cert_sign_key.pem index 95ecd0ad977f..2bddf53a4ed5 100644 --- a/test/common/tls/test_data/keyusage_cert_sign_key.pem +++ b/test/common/tls/test_data/keyusage_cert_sign_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAwXdJpy1zA8yjDZHVAk0u5IGIhBQQY7q2C9WCXY9G3FiHq6gA -F26rDxwBeks+f3G3uzLqYEg9D9UIY0NoAFRYPJEV7l/POp7p1NcZgdi4gwnZvvGr -OjdkNMWkvGqeuS5KTzqfIetkvgEm7eJI7Pjq3MX7QNpXAfX2VX3EpcRVUqucv3fh -DH/uBHrcooR+O9gM1v3pjbrB5Nmgl1yIunyS/5bpTTuS7jNxGGgTTwHfL5gwgA7B -jpE/665X0VcJwsZxWCgxTrPef/5eJsEFBm+XS4rd9fY67yC+ysFGUVtIHfWfyh5s -ucglom9Eu/+YPwGxd1u0sp9tIXAr2VJt2HdlRQIDAQABAoIBAH+6RcI922VywWPA -GCXA12i9rGem53swVehSOhOS+HGZcVj/PbA6vGzpTIB1FPoHFgpdfye6CbZeK399 -jThKd0blctlCIArPyAlhSdHUR10cL8pEu4tf7qR4qF5M9iXETgMo7M70Hjrjf9Qm -RYdOf6DqhQs4G6GLxeqDckUO7lX5GVDb32GzwgAP36JhKRrkzXuiGM/kQik/3ccG -yGyZhW0mmeJUsO+Mg61TRYVDfcit4hWQjTO4SjJwtYGnhmqm105jVwFouWVh3ya9 -Qn69gTQyQ24djH02ygynsSDJ7y4uj1KTbcyMmlz59J5TU1hLifmhT0GC+WCSTomH -R9QNPLECgYEA4IeZTRXul3ccG54P4r3cXhiYf9YjlYY9tzitmUlC+IIq6E1p5/pm -yAcMnv4ElBcB8cQ34etkA2WNtgUGocyhTi4tNdsXqLZZ8wWN49ZGVtvpZvhe8xoD -O3j05iMLK1lek006CQz1p9qjPwa2yu6jC8seLWBmR72JgQ37/PPwpIMCgYEA3JUV -pfzYLG1Qjk9/QqXfnKj08oVpS6veNQOuub8ruRMozAEtKqe0BznJJ7qDG+2EE5fT -u7XLGp4Pi4+yvWJvcD0EKBUEWXzlc2K6zVaAM9vuekcqBVZKgdsBkT0WGyhtsdCh -pdKsoaZCfLOOm7AJPsOghSadzlkELzuTroYpdJcCgYBiEpihlRzcSAic/5OMxMWG -zFOAMzbjzvkSGM2rENcR2TmIspe53iQa5wlaQTYawVn2EnEeW0UaPreBc/yLm+gx -T/YregGBjfUIM7rgc+3RbskqUv6WTRxwU8sU4uW0D5tB2A+reF+s69E2bGZXiZjq -Q9RwmZTTbTSsjEEvIhZQpQKBgQCII3s49tR0lwMg0e+5MqbQCXckNzLFgU2jaqJs -AZD6qNiFEDTQHrD9xKxh2LsSgYUCkrIbKBgyVVtCx22JdTdSDlaCZnZIxMzYahbg -pIJ7f0GwNju5D4jsnD5bZVg/arRJCnq53Uyud+6RCED71anfEt3/T9YVhNsQS7Ta -AfOUAQKBgQDAIydRFQRoC2yKvRmYTSG8BgGX5pr0M1ScihXyhgkDqHPVXjF3S0gd -C5iuAQDRv9mMGMnfAqvPbZuWHiQe6ban0LkTH/THH4PU9lDhOhBC9ZfqnCaCrYoo -lDdGoU83T0/mqfgbZ5LZhBFuijyV2jYVSpC9+HrP74+OPCvXZAlz+g== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCLOt0gY1xj+WzP +9gbVuD9onfqFfAI46qPaXwpJHrbfTQMi/HhpqcXoG0ALD8G9VzjSi5SR4n1lKkWh +ZrMTqoYMmPNhtKVpYmE8cC154XeNu9Jr66S8Ft9LMbl/DodknAUMF9hMl7uqm9Aa +Tym+fy8tElIHIpug1PUn4Tuk9AB8yYHMo1Z/YtsaE7XgHbeN/yyyfzpj+hHaWkSC +R6SgtJ8f2/kKKjb/vR13p0X0st55BZtOpNkvXFhi7YHFwIorBpQvOFbd3hEh284M +Qs3O22BVL4qGRW8T/GmVSXFqYVvHMteDv1o7TOfqpOCi0m7k+wL6JEIZmNmZ2Yh0 +82x/SnYPAgMBAAECggEAKqInvBcw31wtObD4ftEgeYSGhgFnHM6cxe18VM+W5+HJ +KBlvNcvK0jwl7D0y8iuXNsGPCOz1wNik4bt08nyw94KOZEjQreh2Je+jvUKRPVFa +KbnKg93tGjVru8BTLTepQ/65ORrtWFzF6Ih9G9wOMhr+CzlJtoH/X+rUPLqKu6r0 +8YwnFYn5RcgFq8BROrAx+YRFyh1mZbiWeOc4WT08MfjTbTSC9RAKovLQUIP8Evp5 +MQClScY844zJxH/4fKv/P3J7b4guNoJJjSnl88DafINSEwNuMBEl7E7G4sagd1qO +k5XQM3kf4Khy3yzOluBtQPfa/D2h96sfMsYKATDJoQKBgQDBCd0G7ClZ/Ew8VFa5 +xukVFTxAHHxk3+g46eqxYU2/pKD1azVhMm0MobzZiPA2qdjbh/Mg6CYUI2Pi/Wop +Vva+3EN0VuOLC1kkizVNTlEhK3NNMslZhb8LLCNfjZ/Rxy7ywTeVqIcv7tzKR4tD +2nSXDUV8Ji6q6Zfuo+cpUZQPcwKBgQC4pCUPG2aggDFcnerZtvGZjpaec73CKl9Q +69IkYV2ETp7N3TWjArMCj6I6/BxNMw1dm5q6iyJiIH34KiIQP9Lbjm5xu6SSqDxY +yYR0vrSfBj+zrYb9Eb5WotnLoUpz7mxsGxt+Ccze5N3Uo6M/m9xzW3tFq0FiT4wQ +H3W5arRf9QKBgQCdVtXBs7HMt5jHv5Jkn90RIxrVwqIdcmcMJJT3eTDu2FedUYHT +tE8v8ZBE2pm4ZF3uKXQgyTdoSKQ8uoLSKSC61jtg0wVqKpjA8XpDhWcZGxpCvPdi +sWHS0GoQkxXF3YzFrnkI0bFGf3GUqhW3+5H2IIoXM+PryLPefdeHVQfSQwKBgClh +oGyiV33hPS7ktZ3VwpAHxPn+Nqktle8s6wv8RllAxZad3UeLc1M/nbxahH1I09YG +6calKC+V2KWly7yYkUljwpz60QeNbPj5MRZ5J0H8xIogegB92YrRNL7Oh0E0Tlhs +Ot0klSXfZVgi1JOM+vtfpWEX4K+H5Hw4kMndgE+BAoGAa9tl6/iykcFJb4+knbAN +ql5wxgo+m4QoZ6h7b1GO+fbjXavl+6KyRGvdZ2UnE80tG7GCp0yU9W61RmhnD/Wc +GjDOlaIlrH1Ch+dwfVAc0h+HMpm3JzsdG8I97wFTQXktEyDOJp6h2vnBhKx5TrlU +IRKpm7LJXTGrlOOLwwAOnnI= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/keyusage_crl_sign_cert.pem b/test/common/tls/test_data/keyusage_crl_sign_cert.pem index 30fbf509a43b..9a35de211d98 100644 --- a/test/common/tls/test_data/keyusage_crl_sign_cert.pem +++ b/test/common/tls/test_data/keyusage_crl_sign_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -k2unUERsHBg= +BggrBgEFBQcDATAdBgNVHQ4EFgQU0aZ9DHKLUww4nTtiBr0edU1DhkMwHwYDVR0j +BBgwFoAUD6DPJb1YF34IHnaYZclDrx9PhVYwFgYHKgMEBQYHCAQLDAlTb21ldGhp +bmcwEAYHKgMEBQYHCQQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHL73r4EGWdf +9hnMWOSy7BZGWffg82jipjuIKwu6ZNH0YyzrhnBc2IjP1d+upeTffzX1cnuzwz0X +aZTzateqM8u5aQyFbDSlHlsGcySijukiNcs72Vl5imrJmasfgf19bt2MNwnK0ar3 +1Dm2+48k3lCYHnu2YmS2oyCoVyzO+5TxTEB1VjII3NsLZb4dy1WresgWiYtweplG +n7zRBTJWKiM9Nco+ojx27j/IE1D+c/S0WCyYiMXBKYlNk3wJZZmw8D+IHvHu+Dfp +xQR/5rtkbzOYbUXm3PcqkD9KSrQ+SD+jhh5gJXuGZ/aa/7wi6SQyvaR+AfrhvhfH +uUDr1qAzeOg= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/keyusage_crl_sign_cert_info.h b/test/common/tls/test_data/keyusage_crl_sign_cert_info.h index 2a8831b1743e..517d67d2d6dd 100644 --- a/test/common/tls/test_data/keyusage_crl_sign_cert_info.h +++ b/test/common/tls/test_data/keyusage_crl_sign_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_256_HASH[] = - "26b77f1c6730b1d157dce3a89cad7905d723a67db7025d4ff0398ea57f3c2f45"; -constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_1_HASH[] = "fa1f721f75901d23b6d44b4d268bbed74fa5909a"; -constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_SPKI[] = "ke5OFPi3+yBOYxM8xF1f8JMR/aCwPi6xmWHEXDvek0Y="; -constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4cf"; -constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_NOT_BEFORE[] = "Aug 22 07:51:35 2022 GMT"; -constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_NOT_AFTER[] = "Aug 21 07:51:35 2024 GMT"; + "8f03ad5ab1d26eab46433ee73ef77737d21ba0c3159028affee87369226ad663"; +constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_1_HASH[] = "3a4da189be3abe5502eb6b8ab24355b0d11b3b89"; +constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_SPKI[] = "IqUUWj0w/Nengzu1U5HootapbFi/5/0qAhnt87mqfLU="; +constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e49057c"; +constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_NOT_BEFORE[] = "Aug 21 19:14:11 2024 GMT"; +constexpr char TEST_KEYUSAGE_CRL_SIGN_CERT_NOT_AFTER[] = "Aug 21 19:14:11 2026 GMT"; diff --git a/test/common/tls/test_data/keyusage_crl_sign_key.pem b/test/common/tls/test_data/keyusage_crl_sign_key.pem index 5290cc209dd4..f01202cd520f 100644 --- a/test/common/tls/test_data/keyusage_crl_sign_key.pem +++ b/test/common/tls/test_data/keyusage_crl_sign_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAnNMQccdH6yLlTuVszJ1zoPi3N6a59l+sWZZXQsBYp/7tJ7VX -aiyNtKayHvBYKInU7FO19/N/xgsLYBmrZOmsLZB2gn+M/NGBKx+GuAPwXsRgbUjH -eIx9tbgJibc/FlxOhm6FKU9w6a4wATeCrMueBXNYUtR8OWI6XIQ5h+LlylY+1dt4 -PUOGDvSrcoGil3L3qx0VcTyTsicJ9aroQz3+wD70qDx4ttxjmdn9OgYhUksRJI8r -c78FU48Dril29K8aTE385u/HwBqkdTpZIwvMCefBQsSoFzdeKVUEkqZUx9Nhcg8L -5s15JFOcSG80En4N2meZIeamaM+G/f1J6+BI7wIDAQABAoIBAEz8H9p65Yc8fi0Y -2ywnLxgagHbFVgzoModYEkYmfl8Z+fnAP8VTUc0Y99/QRLbB0tCg13d9BYCG83Kd -p1HGlEtZ25N8Yg3KGwq8UzoKVPlwlZWQYLuA3EVUrvn4BvRHJBVCNARvhxJv/Ajc -4z1IR66NTRJ8VO8mlVfNYSCf9gY5Q6Qmn5qiM1b6JWvcR/t/98LvOevkRpMbu7tn -0BVH32qb8vX0oPZA0dRwEu84JnXlwzZMdhF1o43d0sbMmyuwnGfar+bnSsbUSxkk -g5outTRLaGt3tNlGjyJwyqfv7kEtSuMw8MTAsw0ppo7Ay3W/rJTdTmuGjShpAX5d -T3gw+SECgYEAzG5JTPFRxNMxCwDroeJ8VD95uZdb4xQyAOgiXdFk9nmmBZonq17t -MyPHhGOSaZ6/xOi/9MDkfWr8GKAf/dq3Ta0dHE7qtcgiFYstdn9Ltl17RraEwQNV -WuLJ/urP2aNvlT2IP0DfMseZIz3whk0a3eGE84T//luzYxGru9/BwV0CgYEAxGJ1 -1+UXO8wYs8ebIOM+OjwP21U6ppBhMwKeolbrvf/IeUXZSmiAxiyo1jq4bEAhdTJs -KL4HJZ/t6XVbzH2oas7QcAi7gAxJAaVmABd+ZQftUQUihaQ7Ukx+4vTPt0IW/nWN -7e2AmA1fkld+gIWb857LYrvUuzhxlfidMpdFkrsCgYBnzGezhaQ7B/CS4bjCzbjL -Hh+0OEITnqF1DGjGshdNfp7poUgbH2vY14XqlpQ0xMIiPPuaToa1l6jA6CzWPENu -UUPCp99MxX1o6u3+iMvsoLKDSRFG32Zra1Oc96TpoK57XG7djxbFNctvtXd2+Zd2 -qZdT/mfswqrm1oYYMpiykQKBgQCqdiR/77SJDRFsC5iVpWpANh41bfdo2O3lzyJP -G0+pLjqfOYfw1GDio6UxvuqR2+Cuz8OeYcPmXrmt6VZzW6cyfq3icVH/RaqhKSYu -cjYeEBFoQCLFCdcMCqYg7grWsSEwYm191qfGU+VfK178w/yoLG+yFgQDNm0xlgks -/q0/PQKBgQCwXvSdBXKcwCwetW2YR21w01V50YOP9Gb7wyfumGKKtaA7ivksggbo -VNAQ3GOdWzDE5xk6ooLVaI86CYPGsgAxruc3ZrjX4YppDgjVmQeGeexQXNpJpW8Z -yydq41LU9QhN+5z2VyrutluGijLdN/qVmwLe7zpjvyhXoSv5pAFtuQ== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5DlwNWH8b5dze +FBKy4hun67zC3Wnxk4Bt5GejD9ecg/acNxIQ2dkC8tjBV1eAlq+by/FzcP2oKJ9C +dyoD93p28g1xxMBskhf6zGl20UDjLCl6trPFBRBK8Z7Uuf6sAVkQTR29XlHfOCgr +olc18rlxAdOsO9w6LkN6N6Lp/AriR4l00bbbwe2zfjyVIBkyxT4U3x/pg/4n9V1t +iW3pAzJllHwIAXJ+Ehik8V6pGjfJItpikJvXEuEtzpH28IzuLjBvv0tTe9dQtf8n +8BqrxVJxDB4QZSVVVtl6FdrZXWqcQp0fBq+JzpHdxGD1O1Hffolimaj1i19r3tP7 +SZ22MtR1AgMBAAECggEAAcsp1gp6V0+uPFjL2//+oW05GL2cpHX37X8kbs6QgGva +NnL+/qE3gT42HtAB54H0yCwwQulgpZvL/CqIT1GIVlUyQpAHOjldEiLSqUKN8z9S +VGYnVLMf3U1KOAJosLIZDH3Mc/43o1PTNj90j1YZUtPgGvAMymOSAKhy/WGVmWvX +CjxIAV3aX5/F0vyTQtp9cx5MwxmnJRDpVHwU/ySLPZU4kvouPm/aVjQssycFXEsZ ++6T9yBKl3Ak/zqRI1FFX9OSdR/ChGeRzFt3qlVmfB9beBRbA/Qg+15/zpLp87QNA +YUJMxMxfHtr/Py86Rkm7VwNc51RAXR0lnJEhK/eQYQKBgQDwPXXEuDs0eGeCvhDU +uqNakymK8RAKwDO0LSizD7wxGV/Fr5aTmUnqNtXMA1qDCtUjnDEPOzT7xq523jtl +La6GheoqIP4SnLcN6unoaRbA3nLOSdjtGfrI3gLZA2AE6as4wwIUWerL7DMs5hs8 +MVfOrNIRTveVYuY5mLngadtA+wKBgQDFMibPnuiFXvq8mNVLJdrVo6oF5b8i/qAh +mHlIDtKebOgTHzTba6zJVET2OTTcCEYGmFvAFtuBVrgHJojf7rIsPHbAkh/Y92aw +ECAM1Uy49sA4QbjX6kH/5W1BuRSW6AqUMasfvfBhVpkPtsC0qpokzs5ljuXOpLwu +AbLTv3ilTwKBgBhJDjupqAqA1W3pCsiGaXcBg2SRQ97iWRewrPmU8KBCAWV5f45C +I6+yhWBPQnoWwT8NTgRNJukAx6gqhPSQbqEYrng9x5FYGEUm5yhgXzV2B0MFQhGN +28UsdDs91RoKCQ3+4JnwEQU2RmIWjNBD6K1y2PV49xw52C4gW0HtUYW7AoGBAJoG +GyRuFWYfEq9+nJLuxWe7RxEGK230/jRfeNOcqEwP+pD8/fcoujQi+x5q/muilreO +B5QZBmiWyHTlV2G5ejdtHsA5ImEAlJeOcMo1TJDoQqluRCd5lQWAOP9txbQ9GA46 +YVQQspIE5tbMQuaann2Dftj6bWsjZsx0jS4xTtWnAoGACQu//I5qg8BfDLw0gZqo +azGRhTJqVad+nxiA/s8S3xu5YAJsqZ4RTayaiVDy0p5J5d3iDKzRgECqf0Oy/5Vx +VIZB9odYpAKvXxur/UkbVSXoHNpbTI56NJV9otEtJlWPHzCcgLx7jqgITqFhnHIU +QQRaw5acwYeYY7yI+4Mj96M= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/long_validity_cert.pem b/test/common/tls/test_data/long_validity_cert.pem index f51ac9d52e82..8cee8e688256 100644 --- a/test/common/tls/test_data/long_validity_cert.pem +++ b/test/common/tls/test_data/long_validity_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -zg4= +BgNVHQ4EFgQUg5Mg22FmCMFg5/4zXPVFLD2ezzcwHwYDVR0jBBgwFoAUD6DPJb1Y +F34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBAB+XQZ1dqggbYIb940KX +DOnvSmYsAi6tdaJHBtBUIFItcZe3kDRrXJrkow4FOwZVt8IRgwCVNJNjUNT3G1lQ +ytK6JVW/bF078irCCbDH5AxTJ+NsEMFinmM0/3VJo4iFxYAcNXtWLXhXcGvXTYsv +xfS6/2492WVNCczPmaZ13s+IAsJaJXDCm2KNhayRdMw1zUMcwrijEyJ6MOPDkrsB +45eGbEtYtkKW6vn3CLB6kGQB8B4cjJ1TbzTu/g3gT1E907qrSLURja0eB1kLsuT9 +2nog3ED5abxyUtWIX9AW/0oxMJwvJWk0xmgwX/GTxIqvnulOl/FZBKjGE0kPJLMm +B74= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/long_validity_cert_info.h b/test/common/tls/test_data/long_validity_cert_info.h index d0d54c83bfd0..d253e80c8c03 100644 --- a/test/common/tls/test_data/long_validity_cert_info.h +++ b/test/common/tls/test_data/long_validity_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_LONG_VALIDITY_CERT_256_HASH[] = - "2d23cf524c0351d972b0b4f0c850de0787359422c9eaa16f9d03192ee0326484"; -constexpr char TEST_LONG_VALIDITY_CERT_1_HASH[] = "4ad0658d58fd8f4b21dccd851804135009c6b44e"; -constexpr char TEST_LONG_VALIDITY_CERT_SPKI[] = "zXcEYz07DudHyCDzjiJRTXGnw15w1WpJuCz3Eyfu0l0="; -constexpr char TEST_LONG_VALIDITY_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4ca"; -constexpr char TEST_LONG_VALIDITY_CERT_NOT_BEFORE[] = "Aug 22 07:51:33 2022 GMT"; -constexpr char TEST_LONG_VALIDITY_CERT_NOT_AFTER[] = "Aug 9 07:51:33 2072 GMT"; + "26dfad2b708f86f7bcdbf17f65e2082d589c747ed9a91f55ba2cd34dce6c1a71"; +constexpr char TEST_LONG_VALIDITY_CERT_1_HASH[] = "cab7c1f07c134252202e7c649a5f1dba8b22119f"; +constexpr char TEST_LONG_VALIDITY_CERT_SPKI[] = "gmzuk9POLolZNsGYNXXcEfwPT4/KhKO5ACbfqHHbBqg="; +constexpr char TEST_LONG_VALIDITY_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490577"; +constexpr char TEST_LONG_VALIDITY_CERT_NOT_BEFORE[] = "Aug 21 19:14:10 2024 GMT"; +constexpr char TEST_LONG_VALIDITY_CERT_NOT_AFTER[] = "Aug 9 19:14:10 2074 GMT"; diff --git a/test/common/tls/test_data/long_validity_key.pem b/test/common/tls/test_data/long_validity_key.pem index 17ed00b6dba9..28f06a53f9f2 100644 --- a/test/common/tls/test_data/long_validity_key.pem +++ b/test/common/tls/test_data/long_validity_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA2CU+eB9jEdB+E9bUlJCsXN2HQTQQP4G5cII8QxjVlRvElkZp -TmfWB2MmW+3CO9EQ/MeOtVfYp8DoXPRgxg9dvZRW43e8IcaQgiqrrmXds4vtFx4a -SvW/RJNpwYXL2jeNlmCS7x0k1X3fJz4D8c/svkv9LjUTTLKYgYzJxjZzcp9Yn6AN -NIdMsV1geXzSlO6dZpcB/pV3/jo42JGUUCrRQ0+XKf5DZJYFGkmpivpLjUlDOV0A -k6ti7P3+e35dbfgLkC4znpLGcYGD4FnNj6RAUH2+2cVr0oWObo4lTnO48ObxSWm9 -F3LUUicBpNxfbNJHU9jIQ03hsJ/b422biGQTGwIDAQABAoIBAQCj12eJCtHAGTjY -tQojK59cLZhvNpXybdUxkac4fUS5aHkWKH1+r3sv0lqraIjJaurjkil9EP/r+XCp -tZz9xXwbTqymdIapW6kC4nGNGy55AWJRGcJ4e9vmkY+i4FbsLRwol0AJ/R+ErYtQ -ZdP7os8kWNmsAxOEGgU8foocs/3DLd4KhYJ+kkpCfAtEsAEUJE/jBrADhOVYpkr1 -GyAYaiB10T1ZUsfrsnigp4+PgLKTS+3nyGIM61t25pmYvS+JWTmt7mDlA4vepMcd -lDeQsioCzVjslwY3cfijPDUMfewc9BpQ2/KHt30d2eVVp+mIDCztmYBTmiI+Jbqr -v+HwSSihAoGBAO5wZ/IdObB+yummtyLrJsnFNb7wsjvwGBpON0Rpeejm6pyX2AkH -j1/Ped3UmYG0I77+ePVUUhU1Dkibe837hNZhuKeumrD6ltLkeL3eKIDMIBqgQ+ru -qbjWIHunrII68LKGTwqlibW/E/vH/wpOsyECM8OhmlDILRulzXaQ0WITAoGBAOgQ -giwocElsTo6GMxmPeLb+DUe+Ge+1O3w9IG+GAX0aT8CAe8j7AqUnBunCpC5y4lVZ -C7bKUrH6Qe6gFfnjdz4XLUDjtmg2ofCdFaYZjFkY/08FrOZC2gJ72C13ZRAhKElP -ls8+IZ1bSn75qhqL9/BwOK2Jf+vutFDcyLY+rmvZAoGADigIU9yeVzc/7t1iFCWn -+OTHix2ZR2u60p0ANQSaI1TKax+syOR1A7g6wQvlTUkXsjhDkDVAZlfvECqDEDi1 -q1DD+NiqAIXwPHcqIAO3neYApfQL9D/VPc8gwJa07Ep5je/hc31ejrbYheNa5g7E -HdqWni/TDKbF3tVaPIbel5cCgYEAqVYShsJjXVBo6ltGwmoMvgsYCbfQGTh31aqN -FpQEVhNzCpc2vGtdfMHDq6PaRgKS4ZB+mb19Jl3k6olqP9QZ2Pb0kJsZKWZkOL2H -ZJLT9NfmxPTxO3ygtJtGHbc3ydNIIGaxNzyxLq/E5m6sD37/RzW8RfVFoRWoAjF5 -THLkt9ECgYEAo8Y39W6lEyROgAseQDVkmnzaDKocIl+AGLnEUXDQcVfzCyPK8f7r -oqf2UcJPkaFGsqEw5nfbphG/3bwY+s4XogJ2QfWYJ1tm4f7HmIk8vqUf7/dRZHcT -cLCqm90WFAPDqKqRpoR1iFGi6d2aLYMOdEwzksxNhbR8bZ+bYgn19ME= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrLMu2RkPWy0Bs +6P9DBhzgUzOZ9h/sGtt9FMLioY94RrzuWfEuV0LR43wDN6EHVFovSIqFD3gsl2Sl +6SMFMF5Kjj1ccD5TD7jbQPwm9kCsw6F0RQx6IDXTSFrNWgVjQQsiVt7toiI7C62x +eXB3DMrCt2FAXwTr6inSONPCxcA8jss9dJa3bCWwP+wplyxOGe72W+DtO79XSuhQ +/xAr1NbICWRDCJenmrfy11tjYbf+x5DN1Kiq/w8/A2sBKPNo1zeoufMTX+GkZKjs +mS1x1bsLBbr/l927iKKR+BYvuZe5UUSTn6HvNg3srqo+SFtIk719UGzLLpU2F8gN +6fKeW2VhAgMBAAECggEAA1j9fSmlwB6ymmqqWtOE1y2DYOWBiXDbReiE+PENTO4v +udbaFtSbrL6G3Wp+KIY5mwr/dAOZ31/g1taO0fY4ottCJ5OVoXLZU/bi84ldeY98 +IemriTwl51VW+sUB3dd+3e+eXZ3+DsLvRT01cguWz8ztrshI8KrwQVFtkUWkKT7+ +tJRXQZQNgKksz/Vv3glz036yy/TSs6ZciGV/US3DRR/m1xarsFQXnrIUj6fawJpq +vMZLkGkvGoIJo8FfnfhQCEHbr0nLH/vMCTFckTmez+R1dOP/NSLN5XKo0UqpLyBj +t9hhXeI5uAYbOMwbU4eJLerqEPbSjNIUjVNMFP/fAQKBgQDhCrZW4Yy34yuDB2CP +tdKFgsVTXYs4XRdJHI0Xj47hjTr17DwFJ+8rla0Osf3OUHZ8yNuzklHFPlyvKDjc +Uu9MD5Y3039n8i5M4wajlj4lrVpPs4aUlCfD9czpFxpDMx0fO3D531QFirB7kShx +bRhdQK2D0+SpG2wOVVkaWiNL4QKBgQDCuQ6NJlFDPU8J63+DS8Dd3v3YkaaIp9KW +miSBa3vvPDH4JZY51zxnt5ftvvOnegbboWWyQXxpwoFHVHW6HUw5oaAUQL4ZvgMs +UJlqODuCicUQxYd5CgPF+sUx7LJ1teN7uJxFA8r+G+Uw7hkpAmVM/xx6XHCuS2fN +kEyNp89JgQKBgBXGGJBdcGUWaM5bt18QQ5dBaOBBC8hfUXJ0fb5K2JNAO/Uxbzk8 +fOqlp8HlPN5qcJxwPrmoLZs9BnC4HpBKwfaFB47NOuWOzCYKTUkkr0yr8jIF976G +ezZ9oN7oqlTYLDgqYyr6DcIfgiXijJw05weWy3MW3Gf0TEcywNVI5WNhAoGAFOb+ +i+JQGNKs+FiiQHrSQj7cqvG/ma3CKk5zmrzp+d1RU9zdCmpzXoLTuT6lMxYjRFJH +82GaNFQfwoNre8YHV6xk3aexgFvoRUqFnWRZ5wJY+BrsFu8fRpJLtrc81OvodnBz +vejRUoO2D5GPe9p4+1HrQatIoT0Q8H0L6qzX0IECgYEAwflOZed4F3pmEgvzo+W4 +CA7aA9YGnZGPQh0yQJhudOfYZtCfFlso7ggMlubF0cdVqKpUIc5tgYGZ0UUXA6Kb +3zm0lyAggjM3pm73u7ggxsVbIpJp2yUK0qeqJP7+CmOxOaHd8e6E5fbU3M8g2TzE +TtdD54xEzLy1nzjXM4EHmcY= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/no_san_cert.pem b/test/common/tls/test_data/no_san_cert.pem index e846902cc239..126ce02b215e 100644 --- a/test/common/tls/test_data/no_san_cert.pem +++ b/test/common/tls/test_data/no_san_cert.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -MIID+jCCAuKgAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapMEwDQYJKoZIhvcNAQEL +MIID+jCCAuKgAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWMwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI5WhcNMjQw -ODIxMDc1MTI5WjB6MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDA0WhcNMjYw +ODIxMTkxNDA0WjB6MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW MBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwETHlmdDEZMBcGA1UECwwQ THlmdCBFbmdpbmVlcmluZzEUMBIGA1UEAwwLVGVzdCBTZXJ2ZXIwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpnD8hMR6IVuM+RbIcpSWDYjBumzqbhspA -2lc9Zx+4/OnhymWjvRdB47rOejt7lXWtFFkQ1WfjmusKn0PEbubz3J+xfux1tSIy -Wi2tYa8oOqFHDEZBVPiD+bWGWAw3z0wEXZFaipqTjhL6+9JKBUl0hXlVCztD5u+C -btILcvBOkP60UAAIN2EFL/f7K7KxDc73SU2tJwpTvkRqhOIAVYmP6X4plp2VIUIS -0FIyVWt4qfJVW81iKLmERX0DDQtH+G8N4nFJnSSeSQvtPH3OwiEmnjXr1v1C+QMA -Rh/frchd4razU7cCC/ULb3nKQKwt4Ev7xYeINffaWZt6XCW4svSZAgMBAAGjfDB6 +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE62MPs2TzzhHs8J0c6l+ndCebwNI5/On2 +icu8VrvRwnkM2dlKOTu5z7FGYnwYRNOZpNE+uQF/hy9+aSGZnw3mK88EE4QuT/Nn +LkU0fETtaJbjp/eQKQPiV4O5NgxrQaoAI7T3UUKYkE5ZBRvk1ZIUyHMF9ZeDNJhC +Z/Ct6ubgvnGmS/8aOuehv4w1zVw1pp9WWQs/I0qmP1MVjUKFeN7vHNq09R1D8KoV +Wwb+Q3dUhCvsgZNUZ6D9H7cdmUSJkxAJTryFj+yKnB13So05jjLFrMLJpC94uo/o +PS6knRljpy5Tjv8fHHOJEr1LBgzg6UM3cHoPF5yTfh71ogolPIbbAgMBAAGjfDB6 MAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMC -BggrBgEFBQcDATAdBgNVHQ4EFgQUee9v58qfhJVh/fytnD+CDC1AuH8wHwYDVR0j -BBgwFoAU5YZRBAklIKJnd3qqjq32OKSSLyAwDQYJKoZIhvcNAQELBQADggEBADnF -MSUXGRs2KUpIwwf8ELAB0tGy90nHomT2gp+sZuItpdx/F8flbJ4ABOESHnHWko6f -CYbIYRnd5kucaR382TbNnNaXIDwjWgkgSrPoszYct23yoYPYLEOpLLCUt3wNrJD2 -S3fBldZ1IpV5L1Oczj9UJDhi2cpHYG2HeOuIN5J3VX8gOwZDa/4M4YJYZhcyzdTk -KQC+o/WHLZkJAibb4+JW6L2qnWQ5v3x5W21YBCWPuBBW2uHkoZX0ZfJNW5S9sgfs -Ly7Ok7c2QC5ff5BlUkwIImLyBx5oD13na7PWxg0m9OfsB0MYL10LWIAGfAS79gR9 -yqmUbmUlqnrfMN4xxuY= +BggrBgEFBQcDATAdBgNVHQ4EFgQU2rmGghd7Mshag9upUdcSCOX6gKIwHwYDVR0j +BBgwFoAUD6DPJb1YF34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBAAx3 +7gxM9Pp5vV8eNyprju0HaJNwa6JqM/ss1Aw1eF0MlbWWjos+TUvbmSsL4Gdu5uIS +F23U0+xdxUA/6ylpSU5X06T0hSPi/8/oTwEQrLfw18wSBOeQrtGOU93Y7t0QwiJz +z1cqCctw0BoKyxgDJ3RG1Zis0NUNqwMpi+BGqBIsFSIn56+gopEnG1Odv2QNXDuS +IBSt4POPEifMCkYQZakajq9jnBH9kmrMoudHE/MC6+Cu4MEsmasVOC2voQRpvJnA +ZuLBOkgjoTZMqZwj2uSHiswcPk1B1WRHqcmpg4XVsrmNUsvnJWTsg8pfv6qXIIMk +QuBlPpSzUbFhedQ3txk= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/no_san_cert_info.h b/test/common/tls/test_data/no_san_cert_info.h index 9072c54c5509..589f63972781 100644 --- a/test/common/tls/test_data/no_san_cert_info.h +++ b/test/common/tls/test_data/no_san_cert_info.h @@ -1,17 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_NO_SAN_CERT_256_HASH[] = - "1fa3b1626367eda0b93b20cab52a08ace81aeab55245abf29b7920873658ce11"; -constexpr char TEST_NO_SAN_CERT_CHAIN_256_HASHES[] = - "1fa3b1626367eda0b93b20cab52a08ace81aeab55245abf29b7920873658ce11," - "91b048a0941a41740a243a8db4509ba31abdf0c00a1aa9fa36fe2e28d029b22f"; -constexpr char TEST_NO_SAN_CERT_1_HASH[] = "c773be7b9f642ceadaa4ac8b8c8417e900435955"; -constexpr char TEST_NO_SAN_CERT_CHAIN_1_HASHES[] = "c773be7b9f642ceadaa4ac8b8c8417e900435955," - "635057edf7e2eabf863ab7fb5748a443aaeffee6"; -constexpr char TEST_NO_SAN_CERT_SPKI[] = "eMMC8S2gS0LSZAF9bFmxP4YrI5NeUp/T+UzDKhJEiGA="; -constexpr char TEST_NO_SAN_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4c1"; -constexpr char TEST_NO_SAN_CERT_CHAIN_SERIALS[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4c1," - "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4bf"; -constexpr char TEST_NO_SAN_CERT_NOT_BEFORE[] = "Aug 22 07:51:29 2022 GMT"; -constexpr char TEST_NO_SAN_CERT_NOT_AFTER[] = "Aug 21 07:51:29 2024 GMT"; + "8404a810f988c0cc25d2f4f345d16fdc00f0082a3bb5f330c588329c92178490"; +constexpr char TEST_NO_SAN_CERT_1_HASH[] = "1d402dc97348ac6dc9947c94d895de6054604df4"; +constexpr char TEST_NO_SAN_CERT_SPKI[] = "mMe5yDSof1IP+p68lvlivo4EWVVdRZ+b8SpkIQwW6AI="; +constexpr char TEST_NO_SAN_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490563"; +constexpr char TEST_NO_SAN_CERT_NOT_BEFORE[] = "Aug 21 19:14:04 2024 GMT"; +constexpr char TEST_NO_SAN_CERT_NOT_AFTER[] = "Aug 21 19:14:04 2026 GMT"; diff --git a/test/common/tls/test_data/no_san_chain.pem b/test/common/tls/test_data/no_san_chain.pem index 3af055e5cf2a..b755d9be80ac 100644 --- a/test/common/tls/test_data/no_san_chain.pem +++ b/test/common/tls/test_data/no_san_chain.pem @@ -1,48 +1,48 @@ -----BEGIN CERTIFICATE----- -MIID+jCCAuKgAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapMEwDQYJKoZIhvcNAQEL +MIID+jCCAuKgAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWMwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI5WhcNMjQw -ODIxMDc1MTI5WjB6MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDA0WhcNMjYw +ODIxMTkxNDA0WjB6MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW MBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwETHlmdDEZMBcGA1UECwwQ THlmdCBFbmdpbmVlcmluZzEUMBIGA1UEAwwLVGVzdCBTZXJ2ZXIwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpnD8hMR6IVuM+RbIcpSWDYjBumzqbhspA -2lc9Zx+4/OnhymWjvRdB47rOejt7lXWtFFkQ1WfjmusKn0PEbubz3J+xfux1tSIy -Wi2tYa8oOqFHDEZBVPiD+bWGWAw3z0wEXZFaipqTjhL6+9JKBUl0hXlVCztD5u+C -btILcvBOkP60UAAIN2EFL/f7K7KxDc73SU2tJwpTvkRqhOIAVYmP6X4plp2VIUIS -0FIyVWt4qfJVW81iKLmERX0DDQtH+G8N4nFJnSSeSQvtPH3OwiEmnjXr1v1C+QMA -Rh/frchd4razU7cCC/ULb3nKQKwt4Ev7xYeINffaWZt6XCW4svSZAgMBAAGjfDB6 +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE62MPs2TzzhHs8J0c6l+ndCebwNI5/On2 +icu8VrvRwnkM2dlKOTu5z7FGYnwYRNOZpNE+uQF/hy9+aSGZnw3mK88EE4QuT/Nn +LkU0fETtaJbjp/eQKQPiV4O5NgxrQaoAI7T3UUKYkE5ZBRvk1ZIUyHMF9ZeDNJhC +Z/Ct6ubgvnGmS/8aOuehv4w1zVw1pp9WWQs/I0qmP1MVjUKFeN7vHNq09R1D8KoV +Wwb+Q3dUhCvsgZNUZ6D9H7cdmUSJkxAJTryFj+yKnB13So05jjLFrMLJpC94uo/o +PS6knRljpy5Tjv8fHHOJEr1LBgzg6UM3cHoPF5yTfh71ogolPIbbAgMBAAGjfDB6 MAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMC -BggrBgEFBQcDATAdBgNVHQ4EFgQUee9v58qfhJVh/fytnD+CDC1AuH8wHwYDVR0j -BBgwFoAU5YZRBAklIKJnd3qqjq32OKSSLyAwDQYJKoZIhvcNAQELBQADggEBADnF -MSUXGRs2KUpIwwf8ELAB0tGy90nHomT2gp+sZuItpdx/F8flbJ4ABOESHnHWko6f -CYbIYRnd5kucaR382TbNnNaXIDwjWgkgSrPoszYct23yoYPYLEOpLLCUt3wNrJD2 -S3fBldZ1IpV5L1Oczj9UJDhi2cpHYG2HeOuIN5J3VX8gOwZDa/4M4YJYZhcyzdTk -KQC+o/WHLZkJAibb4+JW6L2qnWQ5v3x5W21YBCWPuBBW2uHkoZX0ZfJNW5S9sgfs -Ly7Ok7c2QC5ff5BlUkwIImLyBx5oD13na7PWxg0m9OfsB0MYL10LWIAGfAS79gR9 -yqmUbmUlqnrfMN4xxuY= +BggrBgEFBQcDATAdBgNVHQ4EFgQU2rmGghd7Mshag9upUdcSCOX6gKIwHwYDVR0j +BBgwFoAUD6DPJb1YF34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBAAx3 +7gxM9Pp5vV8eNyprju0HaJNwa6JqM/ss1Aw1eF0MlbWWjos+TUvbmSsL4Gdu5uIS +F23U0+xdxUA/6ylpSU5X06T0hSPi/8/oTwEQrLfw18wSBOeQrtGOU93Y7t0QwiJz +z1cqCctw0BoKyxgDJ3RG1Zis0NUNqwMpi+BGqBIsFSIn56+gopEnG1Odv2QNXDuS +IBSt4POPEifMCkYQZakajq9jnBH9kmrMoudHE/MC6+Cu4MEsmasVOC2voQRpvJnA +ZuLBOkgjoTZMqZwj2uSHiswcPk1B1WRHqcmpg4XVsrmNUsvnJWTsg8pfv6qXIIMk +QuBlPpSzUbFhedQ3txk= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID7jCCAtagAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapL8wDQYJKoZIhvcNAQEL +MIID7jCCAtagAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWEwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI4WhcNMjQw -ODIxMDc1MTI4WjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDAyWhcNMjYw +ODIxMTkxNDAyWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsM EEx5ZnQgRW5naW5lZXJpbmcxHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2KN2qre5737wAqiPy6Ub -ZmtMvhbZ0qFJXDLdsvHN7iywA8rdwuUhhL+VhcFukdcxNOCbDNElnXIVHPr61dM7 -v/i1TJ8S8igKlX2zHwa8WXcTZxIvfG6Skgskr3GQwnfQb/D09tlgmV9NfVTexOPj -xLGi+grJf/Lybtq+Pj9yrG1v2NqmHyo/icyi14KvH3OeZ1ClfJX0qmO4mO/wHOpt -sIj56kHqb0ttZD3Ja9ee8H/VmSXVDS/grrBYmnqorvgY7rFunci72kogW892QOgo -K5pMFv1LQlhnJT8Nc2SvyI2M+9fPBLK30KYTJ4e5uicubQIrANDQQ2myjD+oFrVm -HQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU8C1rPT/4/p2oeosaE/i3eZFKT/kwHwYDVR0jBBgwFoAU5YZRBAkl -IKJnd3qqjq32OKSSLyAwDQYJKoZIhvcNAQELBQADggEBAFoJ932JcsdaZbjVNdZI -pOjB8TD2Z8nz4mJAX0aabP8HayGZY3D7A0D4oED5dKmly/R+wKHgpZACiU3lrAPm -DQeozwVzOVqHZjIVjqYLzscF2IhB4NpGQE0f8M5Ute+/9OgbR/RQuiEZ1GluikGV -9LVP1a4mJgYSbvsekVbC+zN0pla2QOS+eQguvThVv8EreGWAjFdEqLDmya8nOwNL -hTI1CSbK89T4IL2pwIj+R9sS31bpIPXlnhgU7bn1+mwBXSE0vhyw9yFGYZi+l84C -gJ1tDP0F8faetBWCkftdLgaczYsJ7iHVDhrqZFC5VP/Ly6nyHjoxcdEEWLTZetUy -yyE= +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr705Izook/Jd2HnXMuDR +imJFZh61VIvdv3ygT1Nj7EW3c+One2lAJ9B1K4ZELZiiwuVE83JPM8Ig+GUg7RJJ +VyCe2HlKQhSB2+JdmV0gFzKjuUaQai5GyAYTgKEWuLV/UQZC1aTIoM3/a+DE2L61 +E/pDW2M9fU+Y7H4KTz3LYYXOEr8521UPzgEG5pwbINGfkyv8KUeclA7fXF2Q8rSP +5VJrqlR2jxvq7ECFFbizcYY4TBU8nBWZH+zZHycqckDywD0qOD9Wnt9uJCh1KPge +H9za165vrmzHxaWg6VKRMuVw9eYapAlKnLS8VI2fSG6YjiU/YOeENN3mYX70bnwq +RQIDAQABo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU3O86c6M7zsm8uUvuaTtzu6ZurucwHwYDVR0jBBgwFoAUD6DPJb1Y +F34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBABT4Q5aqOSbNUhNmx8rm +MYUvTgEZbyS/s6W+htVnpdoOCnGV7CHotKJD35u/hHjiWFj9sRZc1ODAqGi5h2SH +OTrU5NJitzrN5lZdghcZsE7haJYi7qzktg2TlpD59natgDkv/RzL5LM4WU1sjJ9F +HEgbjRi/uV5l9LLoxgS6nnErDI3yj2vHBMdNFVdtU6kWGfU9NeAm9FcM9ZrJVTiQ +vz+dYzqXZRi7e6/8PAAk++UgqXYwALI24ZlCLACFhHQf34KPr/OKdyE8b2f61BZk +u2eKq+6vtW0nLtnEephzM5h3eWm3V51pl4WTOXJXCL7D6A+Zf1YWEofApWT9ChFe +5k8= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/no_san_cn_cert.pem b/test/common/tls/test_data/no_san_cn_cert.pem index 48f9d0e598d1..57e9e11c2027 100644 --- a/test/common/tls/test_data/no_san_cn_cert.pem +++ b/test/common/tls/test_data/no_san_cn_cert.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIEAzCCAuugAwIBAgIUeOS06HNSZkEe/HG0DYLTrjfLVq0wDQYJKoZIhvcNAQEL +MIIEAzCCAuugAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWQwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIxMTI5MDg1NDIzWhcNMjQx -MTI4MDg1NDIzWjCBgjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDA0WhcNMjYw +ODIxMTkxNDA0WjCBgjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsM EEx5ZnQgRW5naW5lZXJpbmcxHDAaBgNVBAMME3NlcnZlcjEuZXhhbXBsZS5jb20w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVp5SeYoYpGj70QRdpw7vh -FQVrlExL9H5iUEULarmSB/gM1PiDhMfdWSDd6JDbvwHSRy8kMuDiolbK7J9bMRJb -FigO2AES7gyDYBrXCS+ML4gCScF9B4FqEaYbK6l6wBLRDhbZh/H5F0vn6q9Zo1wT -3bUBeXaX5bhaP3kQYWq1nf8PSv3OLAawcKZbs6VMCjJHOcNINoJn/BBtMXVei0y0 -mV8TE5r3zi1q8zlzNX1HAnVSytyTNtxi48AMPARqbI/yon5yswGIET078X9MFDvw -iNr6hnkNnTkkp371a7hBxHS3FjbHni22j1sK9LYH6cdgmExydg1xgDIAOF6DteZt +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaVv4XmWgjnFNt6dK3Lj7y +5cYDxpfuI6Rz8FWPh5jYiUU1J6L2pyNYCEGaaLCkFWoWQW6CLBl5JZ8r1sjTvcuE +JhZFcUYQIKMgE/mFZ1sQ9eodkfTn0c9bjPFgCs0vNOwxRfTUNUqAAXZ+qzjNs2Kx +dQvcccY2GLKMOvQalnrDxveyjS8Pxt8TWLMf8mN36hWOoGwzPHaAPSjqruxjQZxt +70w5jUvaKW/m8dGZ6KBHl4u2wKLLds/YM2nP4XojBcTvXYO3Qc12p95p6Kd9zfgv +kk2bGyN9Z83S93hSEFpB44fu7/vvtlkSy0HQ3mHzxGyVufVaHKyouJZxOfHSquTX AgMBAAGjfDB6MAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdJQQWMBQG -CCsGAQUFBwMCBggrBgEFBQcDATAdBgNVHQ4EFgQUgtZxmYkWcRj29ugdpUavlBoo -M+cwHwYDVR0jBBgwFoAUEB5B9l/TpnxF0Q5zQYC15zI4SfUwDQYJKoZIhvcNAQEL -BQADggEBAKTXuisv9jakJ3fs12Y1NVm+IjOftoCn0LbC8pwmrP0zCV9qFtF+GbcR -3lzfDIn6Q9PEZMCz7M2RNBxWiMM8DBmzZZEvrqOkiHIelqLBDyB7HFqdZuxqF69W -IzD5V8GTPHgJdno4cNXjEUt3GSlE7xqHXLKvvivlwvCgKtwleTQZMOLu+SJqtCrI -lf2lmDu6v1hupQ5i0zHxM8mbitlPwT5CsA2hhA/quzLAoL7KsykyzwXoqLl58ma1 -M4xNdGz7CYeuWx8mSksawLtLmOcGrch01tmt3ntrWI4qI133h2Ewys5ItZaAXcXZ -9uyd9ELdT0KpnFDbBUE4h6kqr9PExOs= +CCsGAQUFBwMCBggrBgEFBQcDATAdBgNVHQ4EFgQUtLXqsabUeEf/5S9xLqQZ7+hK +26QwHwYDVR0jBBgwFoAUD6DPJb1YF34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQEL +BQADggEBAGzyhL8j19Ic5mex5IZh0Gf5hPfRYAz70nIzUsmtvQaMQsbZBJeyOdD1 +fVr9CIN/5NytSSoCI1eqb2kmFgk2ryixQAJViDeab2QagfYdoMO2BVPxveEutgF2 +Sy8d9hAGxXU6EceAuMJnwvuevpKPf0fLlY8sdPxgkxV4IbWoLbSPfN0CVWGdEMqh +Q0RzkAk+IfELNpbBQjlZKhNnb4xiatIlzCuEqjW5DPJxuREfWb2NHzVpu/29SZRB +z5lZVZ+vPXJFG/f/oAAys6uv8l9iHmiijBsvwzBh6RbJqyudZ7fIu1i9zUfA66ON +JZN6A5Xt8x4SMTgxJJHegCon0vpZ9rg= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/no_san_cn_cert_info.h b/test/common/tls/test_data/no_san_cn_cert_info.h index 266fbd020bf5..27a6820c33a4 100644 --- a/test/common/tls/test_data/no_san_cn_cert_info.h +++ b/test/common/tls/test_data/no_san_cn_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_NO_SAN_CN_CERT_256_HASH[] = - "941fda164f16bd6f92fb39513bcffb306619fa90b85b764d09b491f5cca802f0"; -constexpr char TEST_NO_SAN_CN_CERT_1_HASH[] = "6748d234ee7122e2d67aa6007a5df8bdd147a612"; -constexpr char TEST_NO_SAN_CN_CERT_SPKI[] = "5TC7nnhfLAYZdPR5Hx7vhZ7W+1sNu6CKzTFbnH9SYrw="; -constexpr char TEST_NO_SAN_CN_CERT_SERIAL[] = "78e4b4e8735266411efc71b40d82d3ae37cb56ad"; -constexpr char TEST_NO_SAN_CN_CERT_NOT_BEFORE[] = "Nov 29 08:54:23 2022 GMT"; -constexpr char TEST_NO_SAN_CN_CERT_NOT_AFTER[] = "Nov 28 08:54:23 2024 GMT"; + "03cbf85a273231650c7152cc94081f2e987a7b7feec70505fd7c3446c2b3a50e"; +constexpr char TEST_NO_SAN_CN_CERT_1_HASH[] = "3c44a48248e492f62d883966e2fdf1ac8de5974a"; +constexpr char TEST_NO_SAN_CN_CERT_SPKI[] = "oPRjrH7g+0+rvx63t6YRQnwMC8wR+KdFjEATKqeWywQ="; +constexpr char TEST_NO_SAN_CN_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490564"; +constexpr char TEST_NO_SAN_CN_CERT_NOT_BEFORE[] = "Aug 21 19:14:04 2024 GMT"; +constexpr char TEST_NO_SAN_CN_CERT_NOT_AFTER[] = "Aug 21 19:14:04 2026 GMT"; diff --git a/test/common/tls/test_data/no_san_cn_key.pem b/test/common/tls/test_data/no_san_cn_key.pem index 547438384db5..ca2ed04b526d 100644 --- a/test/common/tls/test_data/no_san_cn_key.pem +++ b/test/common/tls/test_data/no_san_cn_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEA1aeUnmKGKRo+9EEXacO74RUFa5RMS/R+YlBFC2q5kgf4DNT4 -g4TH3Vkg3eiQ278B0kcvJDLg4qJWyuyfWzESWxYoDtgBEu4Mg2Aa1wkvjC+IAknB -fQeBahGmGyupesAS0Q4W2Yfx+RdL5+qvWaNcE921AXl2l+W4Wj95EGFqtZ3/D0r9 -ziwGsHCmW7OlTAoyRznDSDaCZ/wQbTF1XotMtJlfExOa984tavM5czV9RwJ1Usrc -kzbcYuPADDwEamyP8qJ+crMBiBE9O/F/TBQ78Ija+oZ5DZ05JKd+9Wu4QcR0txY2 -x54tto9bCvS2B+nHYJhMcnYNcYAyADheg7XmbQIDAQABAoIBACsTP05zdLMCvKCI -Iw1Kzi1CDLa0znEd2QE/R7xWhxVfD+6eXYA+nAEPgCXdRp9XMinP+jwlGdv3eOIu -tK4xBY9hty/O8uB7KACwtpiWHIT57ETx09W+VqQo7MFbmy7JXMHTQl4XH3zl6oLW -eQXsfpruvxiOAY/8W5+uXl0kFtyIoMHz/z48Ocv3PY7EJsU4P4XkYmu6Wbc8ZJDY -NszsAFBvA+cYRBocmVW0bE9RxTArCIhGz7PC3gJrUpJs9xOGj0/nCQPYnrgt8W/5 -YN7965OIO/FWR/6tfKb57O00aifYZSO51OhCW4KT1dOqNvS9FeGmBfBi2vjsTy/2 -pUnQpwECgYEA9akgBIE7uOkOaEB6bMt53vRjnUBIHg/PyoCRQjQZWw74Q/zvV9fo -OcaaEJ4JtuonD50zvHYupYJR5+Lzgu6ZG6ekf+ME+9VedJEgmdQbJwJiXiAw8//J -IZNPwEUpE+/EPGFKXdQzD7MZNsjV4j5Qvtrd9NufLCYE+Xr3ZRLUFkECgYEA3qWb -HJjXHarYCBbPyq2mEa3IrU3XE06yT++/2IwFTfWzAGyvlT9PiTq4o3YO6nWTNl7c -n5u2l7AWXls9lojfUJhyNNUgV6NhIFIaIuYuY+6jbU2cMVr9POTlM915gSZgnDrE -10NzagW4vpurktgIAB5sSfD+nGbzDVkaC6AAvS0CgYAabh7GvUy6oUBukPla+S1c -gnixM3hO266kf96g+8/6jwrA7damYdFXXfm3bflnl5uqP2SQkzqDjhjX1QAUBy2r -3waAx+ECYzttWSvjwQFG2ifRLq91oQB3v0ymSAqaXYKEaIdCvxDbUI6W6Vaxp7iy -QAP/Ux2190Uzvjodwr/UwQKBgAwWZZNp4NPlgJD/3Awe3VM8Yha2kSSlMx0P4RR6 -lZcj7bHqNKYfp8vFely1fh3QgEuFXujzZThbAPvibDeN+sG/ZQPlRjo7znwYuP6I -DKC0Rf8bJY2waOszahYkwgH2+WvB7QnayZtJ8Du469mvDNAk1rA0+z22gR+KZNWY -vDGJAoGAPMzrlzL/JPYNlTfMWdCH/MQlJDaSMO4L6Rb0V8yoHSuhkRpp2iwTSS9j -d4i5avF9igL6VHoUWof9Gwj40KgochYo6mYMwmDlhja/yT26TdpOAj7GQp8ymEOX -HMiziJTwwjd8XwuEMwLNQliEJao+2BUTwEuOwjM9pQZyGhEJEPs= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaVv4XmWgjnFNt +6dK3Lj7y5cYDxpfuI6Rz8FWPh5jYiUU1J6L2pyNYCEGaaLCkFWoWQW6CLBl5JZ8r +1sjTvcuEJhZFcUYQIKMgE/mFZ1sQ9eodkfTn0c9bjPFgCs0vNOwxRfTUNUqAAXZ+ +qzjNs2KxdQvcccY2GLKMOvQalnrDxveyjS8Pxt8TWLMf8mN36hWOoGwzPHaAPSjq +ruxjQZxt70w5jUvaKW/m8dGZ6KBHl4u2wKLLds/YM2nP4XojBcTvXYO3Qc12p95p +6Kd9zfgvkk2bGyN9Z83S93hSEFpB44fu7/vvtlkSy0HQ3mHzxGyVufVaHKyouJZx +OfHSquTXAgMBAAECggEALDVGytOyNKEOdKlJJhclCMYwFdzIn/mtnVf16grZCQ0o +ubUExMnTIeAbinL6RcWsgXt0f+zJzx2rng8Dr0LqDIwsTO/JNc1jbEjMbB3Sw+Ts +jlPEZrJ+Rqb0bKIra54pGWQEYNRy5n+ExXud5a3AUzxHjXk5YT1pxykLyqHXwEPH +vw9p7agF5gmcGHJ22maKDg2khiooWol1/5MNlFSjVsHWtvz3DkyraNGBTd62bbbx +RSU7lTOUH9ZEqRgdZmV97YJpxo2y96+rNLiLIrMVQN6EuXjS3uzNP5OpWCMrDMuf +SnQb2Y9YbSQfDwS8vzNacDQdF4A1qXyWI0iRMc4/AQKBgQDLwiKJxn7wQ0EjFEhp +BsOSLRIW6if7iPfABEoek6zCv10OgyrrFccQMus3hI/KBsvGuZubNlRUgdnBelZj +Nji1qgFE4/bLTI1AVYwXrTlTSxhJcsWklbqjkHBeCs3GJc3RYTKDSEJ/ebXE9QSO +grbVfUdsxRhaObthQZ07nTM7IQKBgQDB6To/NbnIi7GirGLNC4+Ds0Zm6FPVEml1 +poCNx0J8P0ZJz6UeVgjjvzIoaT5gXb4zV0fSeQ2gOHqnMoMXYbcgW8aEasidZJl1 +tS0pDd0kDDEP4sMwk1j+O8BP9SgGLD/g6QJj5xFqeXAXaKU+W/Dt8a69Al7bqBJS +ztv7gjnY9wKBgQCkBxZyvx51IE8RhER+d/l8dVf4pmulbC+1nj5kuxD6fb7V7fXg +5dkoSzVbrhVq12m4Arcnjeb5WMcJoAhnOcERTVhUMwf7xRZ40eVDMinRycQ1bHV6 +9yYWgjJTInNgrhIwGgTl9ofBwyL2+R+/8a5p0r5q64edKpiTxJRk5znUwQKBgAp1 +mRW1wSqnFlLO95lVyUzyS5bba0Iv9w5Ih+Cd4eEvzIvIroBfZaVbN8pkOuAZzluY +lqAstWZyBXOlTtrhA260ZJXZ6K5MsdZeimwPemEqYy8XLS4elItKD8qAT8NdeaiZ +CO74lMDogfpRQ7CEZw9+nM1HJnS0sSBUVhtP3+zrAoGAOggsKeZX9Qou+MkqXOr0 +HSBiV8gwqJW6/T4eP83/MY4l5ASrsXGuJmE0/Fv0NRcfHygGrRQOoXx6mMK5rvmi +8BMkOdZlsa4kHenZQzg1gxChrKK7lm6zTHhLaBGaXk0NcC3PGlyT5myuKWCbyrXM +TxTL4qr3Gw6EdICh+Jrflqw= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/no_san_key.pem b/test/common/tls/test_data/no_san_key.pem index edf42da3ef8b..563698e3749a 100644 --- a/test/common/tls/test_data/no_san_key.pem +++ b/test/common/tls/test_data/no_san_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA6Zw/ITEeiFbjPkWyHKUlg2Iwbps6m4bKQNpXPWcfuPzp4cpl -o70XQeO6zno7e5V1rRRZENVn45rrCp9DxG7m89yfsX7sdbUiMlotrWGvKDqhRwxG -QVT4g/m1hlgMN89MBF2RWoqak44S+vvSSgVJdIV5VQs7Q+bvgm7SC3LwTpD+tFAA -CDdhBS/3+yuysQ3O90lNrScKU75EaoTiAFWJj+l+KZadlSFCEtBSMlVreKnyVVvN -Yii5hEV9Aw0LR/hvDeJxSZ0knkkL7Tx9zsIhJp4169b9QvkDAEYf363IXeK2s1O3 -Agv1C295ykCsLeBL+8WHiDX32lmbelwluLL0mQIDAQABAoIBAB3Nojww0Q1h0GH8 -cEm5Q/zsBPPHeAWpf5oggOrDgkeOdKQqtybZk+MDE60N6RLOMZIgO3CrWTKva/cR -9IpV/77y0ajKYY5uymsUGCm7gaYnPLYcucXR+laT//WgvAZOuwr/iPC9KBVVFdTR -VbW90O49rQoNgcUa7El+q+tsAX50QKnt/MGaqYXc7h+PSwI5NdjYDhycn7zNLS9W -N+eDkq9RLz76RU1HB+aeWMj0RRysmSzNY+/mDrvDK+sBO7KKGSYus96RpsKzR1Tc -nHaiCUZjIxLZBNyVXv+QqEpi5HpCACYLPrb+xxPnlDod8zXu2ZU1Y3JfNAq+e3uE -mfpSwdUCgYEA/ZG/gqgF/p8eZXyZEMGkPFeGPmlQTlvUSYBD92/11L3ZQxSVTdf4 -nuBGgfBJEL7YBb+ntu5UAkgmQftTfL/iaIq3uIGQ9LOFNyqnfrdOLrfiE1/WpsMS -kOlFqBS+MfSFFjSkAm3yGufwFvCcn0I5z4C6wDnN/KYQomHtoMoY+Q8CgYEA69mF -DFCQkqryMFj9x4TK6ARYobEvXRmJGqaLR+WZyILzGHKexeiwFmzMJq8zc7ZOyldY -4jVuTwP4ie2iJJGF0pM3Jrk+NRyEwZ6LxTcogZdKpjTMJHs9M0NRLqy9l4o0Xx+S -3ss6w7xa2rr0sG0SffLSa7QZtUYHE04C4W6vp9cCgYEAy2MXgJ5zSHuq7u5U/BrG -OFxf4jmo32FK0rXeTl9wiHbLCMI+y9SaqBzukRUCFjttnJbQ2KsrmTTz8uK7YYmr -+fyiRo0ujwhbpxdAiCRRwqld3fp2ewZnIvLpG1uf/wPJqDkLAKPdmPVHH69ZgWim -ZCk2Ii97aNZu60CvUNQp2cMCgYEAkw7uht81Rj6RBNR4aQ/D9SfAnBF/Fu31L0jp -T8s6OGxuZ7AQkBamtVThdr2Ht37VYhVUtrfaMCqprlcd4u9aIhLpMJwQzc0aeiAB -xta9yxAq27fQEm9FmdE/rXrIPNVQEn/9dC4EVkf73qb0K43XGfFugvmpjf48Ky1Z -XndFz8ECgYBFIeLoo+I+UGcStoMZA2G8Tjij9eLUHyWfxgnGDmsv2SX9xi88YUqL -amLGBbnul1PGiD+IFcQMbrr7hzMZWset1Gic+0TybynnWfvJlV+ISnHzbkBiDGdT -YGT4jSH+WhCphE8gibklWijzyQPsM+Ja1MdOEU9QgorD0PXveX2How== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDE62MPs2TzzhHs +8J0c6l+ndCebwNI5/On2icu8VrvRwnkM2dlKOTu5z7FGYnwYRNOZpNE+uQF/hy9+ +aSGZnw3mK88EE4QuT/NnLkU0fETtaJbjp/eQKQPiV4O5NgxrQaoAI7T3UUKYkE5Z +BRvk1ZIUyHMF9ZeDNJhCZ/Ct6ubgvnGmS/8aOuehv4w1zVw1pp9WWQs/I0qmP1MV +jUKFeN7vHNq09R1D8KoVWwb+Q3dUhCvsgZNUZ6D9H7cdmUSJkxAJTryFj+yKnB13 +So05jjLFrMLJpC94uo/oPS6knRljpy5Tjv8fHHOJEr1LBgzg6UM3cHoPF5yTfh71 +ogolPIbbAgMBAAECggEAAmKr/W8zZfhIY4HnE7tLgFhNK7slimbj096hQkocr7+D +pUiB5z76C1fjcl8g2LYD7pfYCKkuEvdP96yNwYvAAkDkNGaJUq3mQwkE9P9PLtip +Z0WY7D0K9OcRfrqTlbyizHcIqxK0oOt/Zd9Eq+97lXCq/NbLFV+B1RNN3GJJlk32 +DgATqvKAWN0J6XrmW/eqVh8H8qNb8AxWfNO7rAFWsipJjFlGEmVti40r2KCWVHTs +A8LcpEcUOdx0mtre4sr8mZwfCQ9JKEpE/BauO09o0MSfBFpXJjLtL0YcYscgGe00 +G0APIJZFEWRrYtY+4cjWew2dtY67XvRDyfBcwPvnAQKBgQDjTieIHIv6LjcBI5bk +676bC8o2vw3KECcKiJzGCng0s+zMt5LYsevady7uvV1aHFmv891MMUcoJXFjUzYX +1GsE4+TRP+S+jLSP0Fku30SaA2eaV13l2HJY8EVvGe0oKEMkJnVmE4JHlCIrGUgV +diEKvi4/dyNIhDGT8FuCqRMf2wKBgQDdx0BmaKcgN7jKfiLIhs+SucCQLmcoGeyD +ouRk9fwmcOosaxPGVmVwRgG5c3tcogMvjdGVGFFbCMwiKSp5JGGazXjuV3Ypc/Kv +r17FtCS7PKnmH/8vTP+y9DJJlwioTqwZP/mVvcs7cnHaDVvFjiZCw1Qa78dmkslB +mHYgYUhlAQKBgCs2UWeb3bSLEqPhyy7r7kl1fVTZD1sJpRJolD1GAkIqrmrgv0b4 +1BitLbvvPg8Ccr5zgu+YMqncLGkwiYkQNeQxGu/40Ji1ESKB/mJdyaHp4clCsLQg +aOSlkN2lNSO8O79knE7yiILpE3HUFZMW6QMs0of4Mzn2/6HbQNpfICafAoGBAKHk +MT6QZm8+PcaTDREUV7Hjpo2ZUfQT+HKfFdodNlNZWZfTEjxWFPZAJEIb6pFUMr8j +5znO5pRtd5X4Nuj3hcha9UwGzFq2KRHWEnh/Z9DGF7/E26LLslwPpiXR+p/hzf8g +lDCauyBKCpIB7lvnyEY0D9EZ95UI0aDwikpYuWABAoGBAJ5pzZLIGLn27g5CRDfh +cZPwqBu0LW5wWCrf2w2rO7kHDJiL99UA2/bqt4MzAiVRZ+iWc4ZvNLtOFNc0Rb6G +d5mz+MNVPQEA6fhP8YRxsV2csA1s4yTuA5rHxK+a/WzMWQc7AHpZ10PQuP3NQPjq +5sPBcqeOYQJIbzh1Bm8+fldO +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/no_subject_cert.pem b/test/common/tls/test_data/no_subject_cert.pem index efe47cdb8dde..e075d4ff9068 100644 --- a/test/common/tls/test_data/no_subject_cert.pem +++ b/test/common/tls/test_data/no_subject_cert.pem @@ -1,21 +1,21 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/no_subject_cert_info.h b/test/common/tls/test_data/no_subject_cert_info.h index 9fefa7c8491f..dd5a90bb29b6 100644 --- a/test/common/tls/test_data/no_subject_cert_info.h +++ b/test/common/tls/test_data/no_subject_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_NO_SUBJECT_CERT_256_HASH[] = - "e2048d7e4357d358930392255ec0f10c08c0c07f43af5c31dc2d660aa14ccbfb"; -constexpr char TEST_NO_SUBJECT_CERT_1_HASH[] = "cae5ab320ed1a013268c516e531271e056705f75"; -constexpr char TEST_NO_SUBJECT_CERT_SPKI[] = "VpZsH/f1VUuGPcHm4IMduOsnEpyBmR0VtCx9mC+WaQM="; -constexpr char TEST_NO_SUBJECT_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4cd"; -constexpr char TEST_NO_SUBJECT_CERT_NOT_BEFORE[] = "Aug 22 07:51:34 2022 GMT"; -constexpr char TEST_NO_SUBJECT_CERT_NOT_AFTER[] = "Aug 21 07:51:34 2024 GMT"; + "2e226b66670a9186ce4382b5bef2791372e7b86994870f4d7e9f16c0261edc7c"; +constexpr char TEST_NO_SUBJECT_CERT_1_HASH[] = "9ad6c62f835054f7e7c45412d6826951f977da61"; +constexpr char TEST_NO_SUBJECT_CERT_SPKI[] = "lvgpdVvTKVuzWaGYL5xtON7pybWmH0+6goEhFqgEs+4="; +constexpr char TEST_NO_SUBJECT_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e49057a"; +constexpr char TEST_NO_SUBJECT_CERT_NOT_BEFORE[] = "Aug 21 19:14:11 2024 GMT"; +constexpr char TEST_NO_SUBJECT_CERT_NOT_AFTER[] = "Aug 21 19:14:11 2026 GMT"; diff --git a/test/common/tls/test_data/no_subject_key.pem b/test/common/tls/test_data/no_subject_key.pem index 547f88f879af..e676e0075a33 100644 --- a/test/common/tls/test_data/no_subject_key.pem +++ b/test/common/tls/test_data/no_subject_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAoovDrZGe2HCwmguQcseavocpwJET+130BtVnta9Fd5N12e4c -kAmz9zuTDUlbcvVFDVRsY6WxiVaQTI1F+lSKwTGNEEelnBryYu10i5SAzH+9607K -e5AaZUUKagpRuspfF61bsavlSODyZZaeKaq/LqUXQgBEv608Ip2MTcsTmxufykp/ -kW23WlnWugKvnZIHGi/9SFT8c/d5mRJ+sirVWcFvkbTsrbGBnyOIX6Y5bES8fe8Z -kdfTZooyL3mjAgr67qPtey9defOJz0xNVYGpqEVqRPhMFJyc21aK0N+SYAhp9orn -6f6aXuo/jh2704u3kz34+4ea7Y6w0S6YxyJR5wIDAQABAoIBAQCA+enAtcWW9IQN -F5P8n4mYGOP2WqfCUyCos3jhXzv9z9I5pIihejGEwY7DgivAIgIyu4Rt5THkSf2h -4I9gPOkEtu65tkAgh/lAqi5J+wHgQpROPGzKcuOe65OB5MJJNv8RaItThZQfqe5s -0YCai1O8DV9RDal/dlQ7G0wTBkp+Tb8/Ryr535YAaTPHd9gzUCwjzpA9jGmlpafn -4wcbxpfYNBh/7FW4TqplojcMnNrJ4mCpICKQsBa53a7UmV0Q8Ij0y4VkOS98Ekv/ -3aLJMO29/fWkwZQe7NJeWiTuzlyagtyAPA3Fqb9aXrFv2DV+nyYzPs6uLgMKFqZs -LPf0GbgRAoGBANEgjXKcQtKBC+xr4vvsaOVyNz3XTnv5qdGI7L3QaaKVMSZLuh8m -EEMyl2msi7wHKNGmcH/XeH1V+FyFQ/msppS7I4nIyPTAZ0SkDxbdzhw8iN6gRgGe -6ENAFZLNpQGOcKSkPBHy5m+7pGsfKp9knB2tiwtVxUZyCw/CrVoa58K1AoGBAMb6 -cTeavb6J+JS7dANPImFFEUDzyK8oAYV1GfkWYb7R7zm/GStCJ/rUz6ON76dfqx8Y -gxn+pk6zR2gwNaxGpSpNgv9mM2PEJJ+U9HqTmw+3HgK28cqy0opn+/ukGjSeW6rN -K6+0t2/IudLnl3hHzj/dlMBaIVr9c01knndooRerAoGAQN6RIdEY5UVEVpTstuqR -a0Lvoc4suUYriCSqEwMYEWen9FIfLNRYzQ9falcsjSnHXqj7Upya8n39aW2pNUR5 -877M+kt/EnSwU9l0GMq6yYV5i105+fy53Up+pqgFnCL8DAYp4ANxuY0CJnxnc0P5 -LTeM3vo/FGgByGTB8yZPZ9UCgYAWfp+oCp1i2hQ5NEv0R9D6MCW4Mxc//gTWApwS -Fd6tBOzHmXwN8Oe2KrLiqZwrTtx4onvHx4sjoI71D2Yx+LaZZrPljbdHkxgU1nEh -HmjMSQZihi4lnTvCG+lX1ICF7FUupQ1ISuTmBUpEtpvgJDYD8FftuwLEV5zeZf6o -PzLfCwKBgQDCLj+160vFJ98oSX+msN1LEkfWdDRi75LoPn+Z0W+nVqvDvGicDX4Z -B+FKMv439u2SUnU9am/rs39grB8X4A3IIKJv0NMlnW9JDzLkd2wyorzu43/+AfNK -YNmw1LyQ7PmbcrmJRYeaktx5hpI+XDWTE3LVCu7sdeWiSlHgZBzy/Q== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDOg9MELzdk0jPb +0e52gwLhtkqOeaM1i9u0aHxn35h7EUJ3eLzsixjTSAhRGMBVdrm437iwnYURPY77 +YTI7n5AfcyxAnpco6briTXpd0GvlqxPXRH4aBE83xxkikzv5i8hmN2wkyuuDPq8c +Oi99+HTOIyS/izOEAnoJFlgp2z4uLEO0XUAMh2VVCRPRvZ6k+1ag1HKOnhAy9ANQ +zfmT1WeAgzDi5CcAyTN9kjxLivAHoOkVsos3SN16KZPZJnSvCyxvo3lnYJScnrCg +fT5GWk7SvFjl52OFAgNzJwZq9HpZZUsW3meQ7itNOfPkvQcY5CxPlTpTxCe8AGzJ +SYrkQCJlAgMBAAECggEAGbAcF3EoGspq2PUMDIHPYfQi4gYPXyG+enpkvyb4+JX1 +BpdmKKZEuENFhZDmm7rg7zYk6xMs8jAOEQbOEMyQSNkyr/cKJnSsYmnwxqqeQTs+ +hJBofyP6Fp4Vak+WLjxM+Sn7sbfsA69QaNpz/d9h6CJG9+yAw/Lq6yZ0YQB8g5GU +xazLzl/Hn4lyZlPvqnWQBaBxc2Qf2sVejlKnET5pUa2s7wvFSSYlolJL02DBXMgQ +i/H6JfSpWqVVj2yDP0hInPYufQz3xFZR7xY3m/5udK2w3ut7l8ORxYu0VtFF9k1V ++gkgaIMYrfozys2Obn9wk9W8LxVZcQkTJw2vjE5nAQKBgQDosCcJmi2ZGdNZSVP2 +cTdn4o+ftMBfLwWvodRi0fiyLScxEX3rnIlAJn7nF1Lm4nLmQuyYPQGDPdt6RXsn +SGgOzn5EXe3AaoQceGXYR7Sy5uDQYmux753zxFY+OYtDgzuj7BRIgO3mvuylPnaT +E+sgnzBPzykAgxLzIXumsqk0uQKBgQDjNGXmNLAIC3F1tC2tRvIUlAxTnCPu2hAz +aRiSXTMMv+u+mht7TMcmEr559MQSREl6iFS0rPAy0JHstYUIMcTIjNV1wHv5FcZ4 +2rV2APgvi4HsGxZe0/j9jz2BBEPh727bcSlCbxsck70MKyG8PtJiwwm4X2BZhLgV +aXlFm2udDQKBgH3tt3LO6haNj4Am2zXol9+1EZ2RKPtaa21d25+Pm1Ryc19u5AL7 +OJxrOQq/6LHjo+NSHNFXUtZAR+OobroXyZkZz+QYIW+dNdpinluqkvSvVsPwP/CQ +iZ8/hp0ub1weTcytG10Rya6zbUcQwwNeKEYDYRYQO1R3m23RlSXmUwShAoGAYV51 +RQDTZ78vspey841x9Wu1FKfXpmcBhmbFxwP1+sLNDvQQTvkKZ8CkrLM+y+1D6CVA +1+U9UymbP+xSxL4/bQsd98az2n2Afw6LsbScqBOLbFn3blA9ZrzaSM5BITRxN835 +NqVS4x5VaD+bx4bMttKK+d619ecw1MxM0o3WwokCgYEAnE0idhdy9/fnnfBUoT1m +AfSzT83fBUka4kfM9f/V/OcjII0cnUP+0aB4iTXvlBf6zK7VOCIlatuLAY6E1a2e +9yKONmydEc0rapGwsE61GLNivlSZeHnIKXMSz+eoQ0AXv0QDqFi6x2al9isNWNXF +el0DX29nEXNN0yClTG1ur2Y= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/non_spiffe_san_cert.pem b/test/common/tls/test_data/non_spiffe_san_cert.pem index 37e76dfec989..213f93c16924 100644 --- a/test/common/tls/test_data/non_spiffe_san_cert.pem +++ b/test/common/tls/test_data/non_spiffe_san_cert.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/non_spiffe_san_cert_info.h b/test/common/tls/test_data/non_spiffe_san_cert_info.h index fb64a624f194..1d03138adba0 100644 --- a/test/common/tls/test_data/non_spiffe_san_cert_info.h +++ b/test/common/tls/test_data/non_spiffe_san_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_NON_SPIFFE_SAN_CERT_256_HASH[] = - "610db7309c6a740a6129cdd0cd7b7b289291152156549a488d9f9911d5ac615b"; -constexpr char TEST_NON_SPIFFE_SAN_CERT_1_HASH[] = "d330c0228fa541fe550d73e910400defcf6f416b"; -constexpr char TEST_NON_SPIFFE_SAN_CERT_SPKI[] = "s8y0Gnl5vUGM4dDDOPDJFHYJ032dpPfaSMAQj8coS3A="; -constexpr char TEST_NON_SPIFFE_SAN_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4d1"; -constexpr char TEST_NON_SPIFFE_SAN_CERT_NOT_BEFORE[] = "Aug 22 07:51:35 2022 GMT"; -constexpr char TEST_NON_SPIFFE_SAN_CERT_NOT_AFTER[] = "Aug 21 07:51:35 2024 GMT"; + "f3a0cf42ec3a1aee31332ba3a364edbdef2af8746b9667b306d7440f42979284"; +constexpr char TEST_NON_SPIFFE_SAN_CERT_1_HASH[] = "af12349b99f0829b7e93ec871805d8dd7b95585f"; +constexpr char TEST_NON_SPIFFE_SAN_CERT_SPKI[] = "3+KkeYV2kwjFJBJ0sApQa0BawKy30Z5q5gx3LAfreiI="; +constexpr char TEST_NON_SPIFFE_SAN_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e49057e"; +constexpr char TEST_NON_SPIFFE_SAN_CERT_NOT_BEFORE[] = "Aug 21 19:14:12 2024 GMT"; +constexpr char TEST_NON_SPIFFE_SAN_CERT_NOT_AFTER[] = "Aug 21 19:14:12 2026 GMT"; diff --git a/test/common/tls/test_data/non_spiffe_san_key.pem b/test/common/tls/test_data/non_spiffe_san_key.pem index 4497e8abcdd1..887afbfbe292 100644 --- a/test/common/tls/test_data/non_spiffe_san_key.pem +++ b/test/common/tls/test_data/non_spiffe_san_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA1iLX3FrtWMhCrdRV/4HxssCW8dh1pwOaPZOI6fScpYhJgNER -SwHxDvlgyzJXVaKEy5Us0FDOcdl9SVqYRwqDECZMvkVPv/PuC+aoaYYmpjGDylGx -oVGj+6TEbNXsGHxE0vipKc8uwqfnntxjF5NUbSm6Y/iiGVFxEqnLHl7QyLp9xiRM -ye172te/y/EdBzwCHeFd9g1BPSB52o35Ku65yXZQEskv27aKa/6WjYXQMEthpIZf -aesmL9TaZ4tfmquO6ITDTK0ZliF8LBtWkKKaSjzIVzlklI+SxUaCvv/FAPGNA0mm -fzmFPIm/az+wC46zzBzDmamvOEi/Jj/vEKu7swIDAQABAoIBAAzAsHhYFfCGpKnz -jleUJo/Ntm+aw475wPLP2YSNY9Lb5fy89rmv2OpaYbBYRCk+b4gsTyns1g6jtDlt -IsqATsPkdAeU2yYEYfXle7wlGCInqsCe0uRXl1uCOYx9xPzEUdj6pCBwTUmcdEfa -ujAKPyntJUOU6Bp35jMFV6psXSTHEpIZFb5TSq7RN7zmpaZulxxrb9JUTDq27zjm -OqWyqAxgmSaeafsDwZugP+sVRhxTrr1WkhW9Xolf7XoV9Z4517ON9j1CzpuHf6Xd -HoeS90ibB5qv7nl34VWsvwqN4l4PIRpzN1I2rwMyeuPTAaM23rapkm3gKDP9wgr7 -8gFI2hECgYEA9NT1wvbYO7rmNkJaBWEUsrB9+55GLUksdAllb9Uf8BX8BDyapr97 -imbQNBJFIaFRWhb4sD/Ztg6QytpmFHu0ri7YuHwcnPTnFms0H6ovRKUBWWN4DXed -SAbpvKrXEBF6DBi6KVEimFKLwE+9dj3eamCnttaoa+OTK7p9DXkbzKsCgYEA3+du -bxouTjg38fMqcDDtbHu3dJensGK5le4vdAXmBgrNTJwID2lh2r1ebUg16Yz0+YPk -K6KHOHXY5T6a6rDOvb1NNjiWh6B/6W+FQw34GWVTjpXcJ/4pRREAT0ZGbKiH4/xQ -iXueBvYYGIlhNBUmKGSNLmFeIlRAsPQf9HeQPRkCgYBoN5KZuCuZWViPdjUNnyKJ -Yblu9xOWSVSj3DASp50dvK33O7j1DANRiaxMzg4hX6Laf3bCx5sr9Q1LXCYhx/rE -PmrANQyU/2ay01VvuSi/xqFJZJ8A1I7dzxuF1Q8Q5u+V4Jy147SfNFwKs6bJg1J+ -47/gg4VTz56g+ZQrvQbJWwKBgQDWZIMhDT+jlD81hLJxJNhilP/wOzrNMWsk/iIg -BXng9Tzpi0pIf468ZbFiEM/Wpyr3NGwpwAGcdXNO5yhtawk7M2UYcwzoJy3ztt4y -e9DBeH2OvT5GaR7ZTFMwlUjfyGv+SN5RFrYVUlV2QS17MnkMGmP5MjBxzJz5E3j5 -m/bYGQKBgDEUqckbaRC5KZwrB3EmYJEeE9Q/HKDiWtHYIFW5DJwCOrAW4nqEuHix -FbM0nA80Q9cjULQ+gAw+RCr1yFothwzQ2+t90zh49GosyS9Q6T3TJAd8JTCixrKT -mG2EfrxmMC0HYKHW1O7MF971Nyim2yuROupZTeKWlGKncmwtPX/a ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCRUIhG+g0DDRi4 ++1iQJMUtfuG7UD/ztNlDkZbVNoLZLmfivsw18llRXpVPtiIBM1YrcBa+vWz71Wt5 +q05CBSmDT49/MnLNnX2QH15xTtDpKUaAmsfJ5lFUrCWWV6pRfsEnKqM1tKzHdi/n +rwyTwPqy+jIfrP4k0D9XbzSNyJr2Ic46scY4lTOY0PJfxPiDLRplL/qPFOHz+vdb +RN7Ubz/zMCpAxn6G40aMq+0n1klKmaw+50ISTtl1HZktYxLB7jHXusMZZIcZ7OX9 +gBA1zt2mlI+b/7Jd6Gk/KyZzUGwAl+d5nLqbstjaP4gi3ifAm5F8jAGJJPcoAD4l +y9p2y+WxAgMBAAECggEAKnZUZB0kWTxl+YPk1LYR8iHt90zTazTw+dgcsbAMm0b+ +r1jelnL7W5YeXl0T4bLtHqNR2inDI3GxRqviodMdVtQUU/BbcK7xJoCsGcMUs9VO +Vz0jXWGSaYImN6DlUYwPCBFjAMoLZPupsvNJYxGUkGEg7XWhDAPYRoXl3vp8Iai9 +TO43LHcpYGBIYA6l9ogGraNe2EDNV08fRwJZu20itbmUDNH0Bmiv0GwqwHdLSkqc +0/3/WxgLl4FVj3CLCKSvesqMWUAaFHfHKol30oJXR5fVlofwP4VDjNe1lCiSkeVn +shzMyAJ5sVERQNtLY1sEArNpNtwZk89IQb2APYlgEwKBgQDMwZRP136pZSHYQi9g +3hQf78vzgOmzWddjUo+ck/M/s6kkq9OdDiUgs9IY7ucZFKr3Q6Bh09RB9PXRtKH/ +5cGSgw5RxspfACpcFQRF7dncUAl3uSHKBC7JiMvdBCaYVm0Q8TyyAxDwx7nHQ0z0 +RT96vsjDGuV38P3L4p3GO/7yYwKBgQC1rp6WVtgFUZzDxLcErUyCJyKPGr03n7a+ +QSNz+D8fSIpHpZd0Kj6FwnJcI0BLRBVkSsi/Aq+gROq/ZNW1DI5dtxmutB70YTMG +5JCjnXLYhu0yeEj3cXrBEf+RWtDJnNAwk/VYu2YOYyIs/jnAnEJYIH+OokIH7bWI +qOzwISO52wKBgBxKVtKdRKvlBEMcCe3JYWB0Qmq3khKsxBy+CIeqzX4stZ8Sep+F +l82n6sx1HcsSVvjpCBzcJsSiMuCxo3x240L6Bp136PgtTq0AXmHHFkXhbR10n92I +rGo+E2TLMQX1UwZ3PlqeH9YU0m9ctiI9+yJbf+OtMK1cx8RG4GPGYFhfAoGAUBSq +9EtNJnMFrUjM/vPAEHJdikRX+OeeLhgaH2jhsdFQmioEKwDf1CeULsae9U4KO822 +1HLDpNobuscgZ5AkRGyLlnTwW/ln+3bNxkCFOamnbaKVTvQnDmj3hENKWkOThIYD +E9xuLJNHohtgq2R03dFdSCp+/m2poZYL8gA5dhcCgYEAsDoLRl+stQ4eUZqABsQ8 +v45R4OGgBrAUkyodhHuR+n9MZXtxVycp6K9M9WuuKcze8JZjZ6vx/FAqlmm5Vn0f +qYjGVySfCje9owgb1/911HLhIUOuUkJHFw3KGFFHS/I6DEbiAcCsff3A624ZX1Cq +rpf+i4GF/xxInvNkhUUEdKk= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/password_protected_cert.pem b/test/common/tls/test_data/password_protected_cert.pem index 1d84ffac9f6f..73af5df573f4 100644 --- a/test/common/tls/test_data/password_protected_cert.pem +++ b/test/common/tls/test_data/password_protected_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -rB95VtshX4M= +dGVhbTAdBgNVHQ4EFgQUHf05QKuAnP4qHwOfwHXS285x+YgwHwYDVR0jBBgwFoAU +D6DPJb1YF34IHnaYZclDrx9PhVYwDQYJKoZIhvcNAQELBQADggEBAFCIT9VwjvDr +vrVoHybAXGUN0TY9BT+aiDLtQ+wwIH+NNPjvm5pCViYpUud7QA18rfwcz9ZGuNLX +pYVPCVLPmLppe9FSJUzhdv2fAU63xelnde1/OXedWwbnbHRSzEJlkfffHtC86ddX +C+IUEmRrHlItD9js5rDzWv9etkjkxC8cxfawvt6ijuBAyu5u2+nH/ttOJxnJKQNK +Yn4Mn5MO6aOgVKxTIejPjdhkpD5KXEaRNGYj9J8M+c996wAJc3qARD6gJeK2UWNM +7Ut70RZCh0Ubk37fX+79OYZ2xReK6mrCf9t638YTHxPY+i282uEaT4F1YxPcPBEV +zAx8vW66VXk= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/password_protected_cert_info.h b/test/common/tls/test_data/password_protected_cert_info.h index 3c4cdadd6645..b32884d0f381 100644 --- a/test/common/tls/test_data/password_protected_cert_info.h +++ b/test/common/tls/test_data/password_protected_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_PASSWORD_PROTECTED_CERT_256_HASH[] = - "45173624db09809c4f7f8ed2970b2a0f7143fb10a8e8321481a3d3d8a7c405ad"; -constexpr char TEST_PASSWORD_PROTECTED_CERT_1_HASH[] = "9dab9964d0b2bcbea55f207a888fbb8febc87ffc"; -constexpr char TEST_PASSWORD_PROTECTED_CERT_SPKI[] = "p/yEpnPtyUQAwUldjXtUbM7IXRgGV+7y4DvXgLEXDdg="; -constexpr char TEST_PASSWORD_PROTECTED_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4c9"; -constexpr char TEST_PASSWORD_PROTECTED_CERT_NOT_BEFORE[] = "Aug 22 07:51:31 2022 GMT"; -constexpr char TEST_PASSWORD_PROTECTED_CERT_NOT_AFTER[] = "Aug 21 07:51:31 2024 GMT"; + "54115273f738ffe4aa137d919c2fc01b5a7068d347097caedbae5f31ddb94017"; +constexpr char TEST_PASSWORD_PROTECTED_CERT_1_HASH[] = "a0a5ddbd26007136fc2abdf09ba84db245bdc2f8"; +constexpr char TEST_PASSWORD_PROTECTED_CERT_SPKI[] = "9RmDCGjXZWFgfXUE31MM/x70QsTg/vWgFpOs4STX6P4="; +constexpr char TEST_PASSWORD_PROTECTED_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490576"; +constexpr char TEST_PASSWORD_PROTECTED_CERT_NOT_BEFORE[] = "Aug 21 19:14:08 2024 GMT"; +constexpr char TEST_PASSWORD_PROTECTED_CERT_NOT_AFTER[] = "Aug 21 19:14:08 2026 GMT"; diff --git a/test/common/tls/test_data/password_protected_certkey.p12 b/test/common/tls/test_data/password_protected_certkey.p12 index 5b6829d128d96e697fabfddc5c67ebfba9122358..971cb4d56e2a59b923bee2b04bd8539ea79607d4 100644 GIT binary patch literal 2835 zcmai$c{~%0AIELB88c=%k_dC;D4XO+gz`9smck@dj+CS3n6sLNa?hP(=9p*|k}G#^ za^*A&e!o}GpU)rP*Z1{#fByLX_kMlRWEejXz=)!?ISKAfMb7g{M!J~j(-9ejYY?C2QXn|GotC^q`wNgT%x@UQn?~7MpDn*hC=zuP-AxIkhbdTooU@8u zpzez0f$w4O0q}@dGK4Y@0dzVX=11jZ>m2oRnw&hUE?vwqfbq^ON-5V(Fxoz)za9R8 zcYyB0Adt*LcA3QPV`>Z^W>!`fziRr0q>8)vTkTOJ2&sw91P z{ySgh5Uu9f;PA%T+yhP=3aI(!xHk(!;n873kikRo(RKVF9 z%Sr-gm77aR)`zlUZ#ZS75X3jdr9DRj?Q*=;P&VstwwwpQ^*8Q$r~LD3!?7k>N1S=f^NmN}V8Nt2<( zqPu+ly?jGwmCM(3Pgv#!eVBzu)@7dPL}=|S6fz-ltx>i%_RP?Edh#pFk|GnsOG@Sy z5>^8xJD!7jPn^W;)sBdZHV&D0ej{ni&(Rhc^k6pfP95hJc&N{8vSmB=AsRdYYOXbY z9(}+>H2LzWD-6C|`eZ{1=3Nq{Ipn0Vkc!cj|gPnOZ0YV z>-uhD;497RDF!;M;-t58gxnGNSky4;oGf%qtU9t5L=`<-ai z&D{;2iMr#ALHjTl^vc9!V0uHf<>h=GI=kvC_4`@duyDX(mI2UGzahv zJ#|Tf&sctwh?DQ|hHKlMR(kp?i5)}y+VCRXa_Ywdm~9nZZQo2`6taMX5;cNNM7ZrYsp3nR_Twtbd>n;v?tC+ZTGbpLNZ@)I zdgun^dsr?JK4-SgcDwL4^knUowzrKgaXm(02gO(0&G%|`^i~#sF3NrOaCl$p9;_iH z%(aBBUE5i((JpV_3cK?t(!tvH zSyHWYF!)uVlV{hVNX6iPHU{8-*fK5R8h%)SD$R)O6l-DM4AbbgAXFtM)9$y}?UBPF z4WC|bssRE_=R&g+M%)x;P-_P78;w=t5liKi6M1vH#FB^|gV@KCv34)mObM*O1(n?! zu9+i?5}%`gN}9yrgzh=2@edMfdJ*(m$cm+*`JKmfKdzo&|H5#O-Ll9O)zA3;;)SZj zGhXfQ#Ynn3sW-KAcn@|cQ^8x&rIXB{A8L~M4?REfhZ$K&C8Rl9-2~U4`|WF=!!2Qx zn)7b@q5k<#eXeR3b)m2h+H5fL)Rjz@r}}T9~Y@l3FkKZ0DCu~qI_D)tU^kc zJ&8Z|Vwo5{?-)H`hWk*8KPgvfltx_Se`YCec&53m<%6@fRzD$`>XFK4 zn9)!f)5@7P6Z>-%pW7-eU+%vDSjd>zMI2SV?anZ_&-BW7hAa$3L766Of?(tj$osxf+#gHwkRzf8Dg70#w@t2aL9i6^KeY zn4ungnI&{S7?!o^n(;64q+H}P(`h2K=JmGzOhD^9Y8~9WJSZpsDLbfXCftY@@Af*S zLNzA-d@~8PT8@Jh3}LONd)jLA63p9amrfj2yxUx67ySzQY%ak5Bu#_cb?_{cAx@7T zW3U3e=q+!R5PRI^h2Alyho#;n(k|SvHF%i~hP1Q#j=A~`>vdGEUcIldv84W);9aG8 z?b7dlW(^D)x^2_bv;bZ$q&y zQa~4^W@NC}VY>VQIg3tKjW$H`5KDwYcd*lY z8X>Z4n!OY{uFBn{kFC*Na%OfaSQBN(>i+<{kL$(yB)u5waY3tf(mTngD~AO80$Z2U zpc~7D*YFp**>ZVr8K&a;7~dE_-*uKCR0v-aW7T*pB_Fy;6?&k3!<{$WEp;cY#q&ql z@cW_FCd=jYp6ikdKG#J9o22ejFnI|Fu^a0%eJd`bH$pPzP39-=6W#T6k-8cPU7y*_ z;Z{6A1MD6oXc$!*Z`tT!o9EAIO1q>RYG{EX&%j4T@UN3`5R7-5iLPQg^Y90x&t zN3niAv&g*6u)g^xS|5!;!~eXIKmeEnB>CCZ?tuKw6~pC)liw!flnMU5Oho$dvFoZV XzT+BWR|G-OG(+Vq-N`xUe^mQ78u%bG literal 2669 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 diff --git a/test/common/tls/test_data/password_protected_key.pem b/test/common/tls/test_data/password_protected_key.pem index be993cb25838..6248839921b0 100644 --- a/test/common/tls/test_data/password_protected_key.pem +++ b/test/common/tls/test_data/password_protected_key.pem @@ -1,30 +1,30 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,CC4FF22DB39A1B460F76F9DD354801D6 - -EqB76ws0X0R99inSrTFasUa9QOWkLFoFuVV2hAsjIs6Rg/Xj8XZFun7+QyvM7WzD -GBro+ydWNQN0EdVWlRY+NTHQzZq+ItCjKkIYh38uYZQiseauz9SalqZMvJp61pXA -HfD12DLdrxUSFaR5Ko/BbMIqJc8l8OBXqvfdVoBZLQBl8bSKdehFVpsIHUxBcb+l -v0YsrsO8qgUjbVNsU87lUPG9yX9o9/i1OQwtS7Rc+0+tY8cfyNzQoN8fLK9UaAek -jPIT1A2t/Rfh0QlW4HrRX917f9RXvNR/LIeAXSb2jUfefcTl88m6ExZ8WGRt7s3O -7XhgzPEJ2V52TfgEezTM3ZRgmBDWcTzrRfpstmW5eCBDPPAmFSRz/c9PEKdEbMhQ -i0tdYQhonY47+s01lTg6Nx+IyNK4wo10/a+8PmDZaHg5sEgYefy45pE80Z36zn2S -yWxSNYCpm2PjGjsDcSigh8p0Wes1M2USAe0TnIvFjBZckN9Z2nMlMRjDHZ9AaWkF -AcarJgDNFHbM+TZRw31ej3raZEjaix0mbu+j2/Nc5vBxiO27JqgJUvIUtFg8rKP6 -a6eEZlRyJr5RESn/GseIlU6saWkCejhy1yhgMvnITsNDWxLJTZ5Iol6wZXlNz18L -GgofxpJQ8QdQKyd/IfW4rL8am+rcaNopbZJ6Ygqw4w3WQ/gLSYfeFvFV1+goCYmK -b9aPosuIYFfXf4faNZRaFbWZSodI0p8lbsJmJbf2UTCN4ESVw6EQh+6GCDfifGic -P8AleUVGS5CMGupJwuB342URz+bA5KKfOGNDyvt03ZxDYS/O/xopNEIZ5J300X1z -5iKhA95AMOOBcbpR5DStL9vIpaEONOhp79yxv0EgNIGCDShPCZ73AH7wOayZC1PU -nMQiiYAoOUOQNUXHkp/vjAkGid3WWJwBpI5b0DumK8ewko1gHs4OvLLhwRe75tWK -v3YIgdnr+N8xvRjf+t8wNXK4KGfRMLnT/dPiWkTeK80PjHtiBiGDcimXhpISHT0c -LMAiTtLojtijZEQxYKek6aRT406QezTR0+pHuANz0hM3Xs8r2KeJpxpMahgE4lRp -GYmXzdM+rsRTv956MCAr66V6XTXQ38Rk/iAOHbwC9AcaYNbYYAVgoa/23QuOUTHX -WlW8JNjrxnU9mK3Oa7U6TrRZ4fmaFseDsobSSvcDy7b2zuidZDdciOy0v3B6QDZu -83qlMXQsYb0eS5USVRO7XkGjCzL1Q6zZifv//ZR3P2RgVwFofK06eon1i1hPAwO5 -SMWlq+N2gI6c9yuFzofz2SsyAJzFJgDEP+NxHxR2hIUjzKqrbD0ollAOyjFlJzic -2Zaki2GqLj6/dJZi3FTe5ONs/59Efq+yiidEBLUUM9Auq/qwYIl7anrE3D3qqIQn -BAVExw1o0yCJ4AgzZpe6gvm6HvTg9UEKCCBPKDeKIIz+Ckr3TKYk3QXT+W7Iy48g -gBYod0fpqS2xFyI9wMcbnAdPYaxjxYSBhgaImGUpLHacH+/MVLtNMbbv7GnVNo3C -HEX70EjWAWUdf4tZ1vuzF6eHsa9XugUaF3QBO7hWV7Sax5PbA2B9/4MevnPfxzlH ------END RSA PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQJ1CUKkqmLXkh5mOX +bNpj5wICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEGIA4NdyuTdYQ+L7 +PBt1QnUEggTQ7K1Y9mp5c1HkYV8mK23wsOtd3JOTCotOJBV58Ib8BfKq1zRMzIKi +dQaxFZdcnXH1eerspdRZ6605d0dmLnUVKcheruJ2LSh7LvHVz9Bnidb69h4tzzrG +PuWg/dlovlQTBm3zi2NBYL2GgQ3mSsdIxnAlhDIprgpiNA0jx7SX6QYi2MzbvfDI +hybVq2nFY5MTJ2cAA7swE7SyLov7DEr+wokdcakuutRuqx3hXbYQnQvrgFKwL7Ex +1KDT8LnVau65S65Gy3Fy+W1UHrUAw8J/nrLa7vjNSuCzc9XPbsl8MQRprkN7Mws5 +oqR2oy04NKGYGhopmGStlwNBA56R1pHJ7jby1ma+CE3+CaKfl6bknwST0NG2j22Y +AN9ThmTO92bY8qNUKK3G3FSrtv6C/nwUwvi55gb4cYgx/HF0mXqEcuoessrE7GQg +5OjH+K/QNJrYwm3wdj8cTDeI/BOIN3ZAQM80za2Yq6Vqda4I/a4uW5B75XYr68pA +89j1MGDDJ90pa3jYZ7Igke1JNtk6dxX+Xf1rpL0PybPewtJ0EO/CbDmcoME2qFLW +Xkut5ArxO3eMvkkpcQCBD0TK9F/gqdqBXK6jyFbUyt1PjRd/4eg7re7LSdT+zlsH +AAZPpH4HArp3oPz1sw+bXK+xnjDw4XyhLx827AfQf2ItfMBmxIYRMUxmuCnP1UXj +PjlVw/+TM9ANG4ta4a45fPDUlIGn8njbJLP/akdhKgR1kUWW1Qolz8jgH7xuQerG +Pyru7se7IUG200k/QhUpCYyXPCwLttgJg8rlN2ojI9RqbIlqROP+JcgSwjL2avy9 +eHW9G/jB6C9M0mvChAp64ERtiuNIDEXwiGD0anf9hHCm20axAHmydTu93h6AvQ5E +g52GeqUWxnF1luiEAkr+ipl7OsbkHE23PBPbuH01DG7SO+oitRtEzMF1EB/ySqGE +X60gOT1AJ6wogdhdpazFH5XAghYM+Sb+gk0epoooDNrjpIeMSjFepXDm+hWpvMzA +gaaehXKzCNmGTX0R4e1v6VqMZNlcUqXN964qMXnIUI1lncCNjkcELzpfqzI5YOqq +ORs+dLt1JZn9UK7DbgOtXz1O2RoIHgYeeqa/nAaQWmdw9TEuSDzg7XVnibcQrget +SZLCbZYDdJ4LC44XXDTKmglbXTn/6adfCsZDwf4rlr+8OZT94SvGT0ctJjQWJuZS +ig5mhSdaC4SILgRw33zmATmwT3aqTWpdEIL8XdJbCKSxA9g9Bf2BMzGEgaoJW8nb +IsDWJclx7pbViE9hM6ab2XWmxyhXI9lpPrHZzjqpfWJxQxNlL+W0wmgH0fQmdgfO +Mg356Espa9N+LoiVyqym64Wi2vgDhrvl169T3R3zZHcFulqZnLRtcHFtwkTQZ+Rc +9CWX5KUdi6rfr/PihWgkoC7TZgV6icWeyA7/8Tnuq2ntJaxm4r2Cfz24Ns2+nKSp +PmCe7bHDwlyg/4A1sv0ryLXMsyGY4XBfDRNtYAA/VddpzCzJD6SaSISLL+IJ/cTY +QxX4C0wxAXt78+PRgt//BDKY4cI3IArLJXF9vkK9IcYQ1IK2t5jOFFg7sIbzp1UT +e0gpoax+K5lUGhp25WXv3pshs3TJFimu7tFBPy8Vp3GserX52tOwB1Y= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/common/tls/test_data/san_dns2_cert.pem b/test/common/tls/test_data/san_dns2_cert.pem index c9c15d8b25fe..e314aba1305b 100644 --- a/test/common/tls/test_data/san_dns2_cert.pem +++ b/test/common/tls/test_data/san_dns2_cert.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIEHDCCAwSgAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapMMwDQYJKoZIhvcNAQEL +MIIEHDCCAwSgAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWYwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTMwWhcNMjQw -ODIxMDc1MTMwWjB6MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDA0WhcNMjYw +ODIxMTkxNDA0WjB6MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW MBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwETHlmdDEZMBcGA1UECwwQ THlmdCBFbmdpbmVlcmluZzEUMBIGA1UEAwwLVGVzdCBTZXJ2ZXIwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQD4epuDf825iAFmwoO2L7zjdOVlXukuEdgk -Td1P0P8qRgiZ+rFrmlJxEjIkTVXZ6S3lmJ+eKuWnA1Hyj2DjqOQt90ZD5oDBiNFR -Dz1yu42ibZhDbW6e90aG/LEa9AxflpJtVw9Ot5xPfLyQSVrGIeR1vh0PsQzJVmuO -gb6VuPUzKbAq7I9QBPaaNes3xAgoOh9/o/PzunNVVwNuOcyHl+g0y5BJFGaIQW01 -Dov3+sScPXTu1U3WmeBV/D3hhVu1wZ3YMctfHnzoN4yPtDMuQGUgBs1r+kPij/65 -HAwtwrKhA8ctuHxaSEyaIfBSgK+0RRZ//zYANZVeMi9lQ/7oV3zZAgMBAAGjgZ0w +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqK6bTU0hUif0kMYsPxmLbIZC9EA7y6GsC +TKykILShmoqAIvgsipj1utX/BCI9wJeJ6T4Y0sITnqpVhW/goUC8uGmFkCxc1ImS +unE2RH/O3jAG0QuXLnH9qP65PMEpQvjglXC1W4cxOuOuNcfUII2yn38zFuGfOkpq +6jgd5zrIIy0GGxFwnMIvK6lh2q163cVVgev4/6jXvwxEl/ddDGQdljH2FRa2TyVy ++DdmXJvQ53aUZVp3PbjGNo5ZDw/PAeBfHzJBMGqyMHmdJQ1LdatDkR6xHyY1UDKp +PqRYy15QSKoo1tQvGs826C7J9era+VWcGkyALY/WrmKgcYr2XnuPAgMBAAGjgZ0w gZowDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUH AwIGCCsGAQUFBwMBMB4GA1UdEQQXMBWCE3NlcnZlcjEuZXhhbXBsZS5jb20wHQYD -VR0OBBYEFIpeMfx5k3brFHsqNxQrFzfHbgWfMB8GA1UdIwQYMBaAFOWGUQQJJSCi -Z3d6qo6t9jikki8gMA0GCSqGSIb3DQEBCwUAA4IBAQAi9VDh1lkbSF0oBJp2sZm6 -7z1LX9PWn60zGf9tMap5eEHYMW+S2u9/L2/4jhjxFvvg+9VxlYvNYLcRcG5H2vqL -IoQZnoJjanmL5m0d0bpZS5FMzH1/mtETCGaGdhKdU66UY1BO1qtlnFXcO1D1gDhF -yefN/x26NNB2fQAw9VyLOM8DiMhuAjGwGFm2E/zASpJFymgyahtn8Q2vLQOV3jgV -RaGlYLVmP4Xh7bFRi1xBjWwQ64gXtsrErD1wBdlpALGJLTDV6uHdGiwtcUFsRSQe -PHpucZgdoGsZMvVVpFkFIzTg+p9+9Dp5HiYNZ8bWn96sIIxxav5uHpZ8gKp6rvCq +VR0OBBYEFAQ4pydcSpRHpZwXSY7X/oAX11cvMB8GA1UdIwQYMBaAFA+gzyW9WBd+ +CB52mGXJQ68fT4VWMA0GCSqGSIb3DQEBCwUAA4IBAQB9HU4WZX+zdLuo9tTSlMPv +uB1GtIgENxDP8Xr2ip1ytJIroNrZDU6KhypYoBQFUSTeGaynwyrsmGCcjS4kN+fh +b6DX1O+VWJL4I4wtwleK4RayYyN2OSw+0gqoZ+RtwZhbuboL8zOvGJLR4TalDPnp +wMPCfVpT8a+VOIUsW7zCM9MbPw/h6uOCyNMqZb22Qawmdb3khT9AfBqXQQTRwg3X +7q5DWg5vOUi8VUs9d+LhpFeNWeDp13DfwuVsMt0sYHVFcqqzzPq0MzYqeq3WEhnB +j8DgZSgBnkk70/vKtaCTjgYt40Hkefuw6O5O1/qAfEEJGKYff18EcRHwtsD9kFeY -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/san_dns2_cert_info.h b/test/common/tls/test_data/san_dns2_cert_info.h index a0f9850459e7..99d78b998ee6 100644 --- a/test/common/tls/test_data/san_dns2_cert_info.h +++ b/test/common/tls/test_data/san_dns2_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_SAN_DNS2_CERT_256_HASH[] = - "4f30fa01bc9232137e2763598155af641ba54dd09516865527b9750711c31b7a"; -constexpr char TEST_SAN_DNS2_CERT_1_HASH[] = "f5703141f3c7ebfaac7517a01b8f4e412c51c2f2"; -constexpr char TEST_SAN_DNS2_CERT_SPKI[] = "GiZPt9W+fiM0knMNeho5yTZ1siS7EwsJgzLHEuWG66M="; -constexpr char TEST_SAN_DNS2_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4c3"; -constexpr char TEST_SAN_DNS2_CERT_NOT_BEFORE[] = "Aug 22 07:51:30 2022 GMT"; -constexpr char TEST_SAN_DNS2_CERT_NOT_AFTER[] = "Aug 21 07:51:30 2024 GMT"; + "6f89cfd5ad6f5cd857f8e16c27bbd23fe3ca7da44e0c645331ff7840a1b380d6"; +constexpr char TEST_SAN_DNS2_CERT_1_HASH[] = "628f58a6f0ae84b6c395312eb9185a5c192f811c"; +constexpr char TEST_SAN_DNS2_CERT_SPKI[] = "5gvDIIgDr0j3VPIgoxtk0dWZfV/T/+WsOVZ1HW1RGV0="; +constexpr char TEST_SAN_DNS2_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e490566"; +constexpr char TEST_SAN_DNS2_CERT_NOT_BEFORE[] = "Aug 21 19:14:04 2024 GMT"; +constexpr char TEST_SAN_DNS2_CERT_NOT_AFTER[] = "Aug 21 19:14:04 2026 GMT"; diff --git a/test/common/tls/test_data/san_dns2_key.pem b/test/common/tls/test_data/san_dns2_key.pem index db9645fae6d8..42422e7ceda6 100644 --- a/test/common/tls/test_data/san_dns2_key.pem +++ b/test/common/tls/test_data/san_dns2_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA+Hqbg3/NuYgBZsKDti+843TlZV7pLhHYJE3dT9D/KkYImfqx -a5pScRIyJE1V2ekt5ZifnirlpwNR8o9g46jkLfdGQ+aAwYjRUQ89cruNom2YQ21u -nvdGhvyxGvQMX5aSbVcPTrecT3y8kElaxiHkdb4dD7EMyVZrjoG+lbj1MymwKuyP -UAT2mjXrN8QIKDoff6Pz87pzVVcDbjnMh5foNMuQSRRmiEFtNQ6L9/rEnD107tVN -1pngVfw94YVbtcGd2DHLXx586DeMj7QzLkBlIAbNa/pD4o/+uRwMLcKyoQPHLbh8 -WkhMmiHwUoCvtEUWf/82ADWVXjIvZUP+6Fd82QIDAQABAoIBAQC2Y/lHO0bdSxIM -Rfe8gaobJDFGibaMFJkdfPJYpkbG1wV1UWluXKbrTLn1n7bG77y67Z8s0LwmLe+3 -JruuIMjtXLb9HHOinDVZVOB8GWPLuLqts+QhV80zRMUTzdRPTg1JqUAZPfnE9wDK -wK2bBkHWk6htXj7Og1sMDfzBljSWSi81PjNp+MUVmn5l/PYXWxyDiRpbWlrrXvCa -5GM+RbSbuNaCY19R2dalLF3lUMkoOwZDTqKTeViEDwrtAmzRg7Lojy9Wu30NNG3B -TuPGd8Eyd7y2fdGVSrzR8QMONnWy3aFEP2aJd3Rl+0z+K9JayoZE+qgsY6W7zHAW -ClAYzr4BAoGBAP9AdazeDI/0f2zWF0EfrANUt1ElmRC4yah3RWzSDh5k5JxngWAA -0+hITirNczcv8+xRsIE56yBRRNtRxWRUKDd19YE/7WAq/eOtCnDEfMHo0LilpWrK -ZKKJpHzXm9AqwvGArIdDlTwcsaRImlWzkLm2SXUIM54izN0VCgEnSuE5AoGBAPk1 -EMKJPDwgOoLvKySxCmbOAvdEVGAJj2ja2fI4Kti8pBdQ/NHx/dvy1YAjsWYaC+rx -uxeMyvRaoVvrf1TRYbD9rav0SOwTLqOQslp0QshWfI3MAxY7xOBhapHn2UZvzpyO -BLHPAdXOfOolSn2EBp4pL1MSku+Ex4xDSv+OtpihAoGBALM6zeY+XM/QPJFtmxKN -bLlCCR6fqeUF/AOhDEynCmbpLWVtgHiq3CEkdE61yIsdzsdHbQqwYptktVbTCimy -tjKLT4IcI0/9oBz4anZYYcm+8qBVH9vmlddTkv5eXvhCrnPpiDvKhsWY2Fuk50n6 -NktQ5i+ZPLVzdipfFZFNx9RxAoGBAJiEJo64iLnPi5/ImiHpjBEg8eW81tqz3yXw -EsTQJUDiKpbuhNxEevYapxm2PoLbXAHdEYC3NRrZQLnN5e7V+jDlAF4lsl9w2fFW -xCDh2GFdtPrfKeB4keQ1GpDTUUFvegaMUEk2BMyChCaUzgMFQzuWvxTbYDvginPI -V2USRaQhAoGAehETthS2H29wwQPNhyoF0SwXQbJA2Ev2Grbkjs3S3w3rZpQRANq8 -aLUeQro+A4S/xXXT2Vhxf6SXbU4cRrd3iqJekI7Za4uVm63B/6QxNf1HCiXpgDXQ -NNNvszx2V+2l6VU9INbfv/2iN+7AN2Arcv24cqqT0+4GtqKYRnAdDn0= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCqK6bTU0hUif0k +MYsPxmLbIZC9EA7y6GsCTKykILShmoqAIvgsipj1utX/BCI9wJeJ6T4Y0sITnqpV +hW/goUC8uGmFkCxc1ImSunE2RH/O3jAG0QuXLnH9qP65PMEpQvjglXC1W4cxOuOu +NcfUII2yn38zFuGfOkpq6jgd5zrIIy0GGxFwnMIvK6lh2q163cVVgev4/6jXvwxE +l/ddDGQdljH2FRa2TyVy+DdmXJvQ53aUZVp3PbjGNo5ZDw/PAeBfHzJBMGqyMHmd +JQ1LdatDkR6xHyY1UDKpPqRYy15QSKoo1tQvGs826C7J9era+VWcGkyALY/WrmKg +cYr2XnuPAgMBAAECggEALsw4Ya9qmc0k75osWxc8wnSVoFjVM5oVK5m4dJ6F7ldY +tWpog59N9239Qdd6Ly9SvVuGdz8mnkypHUHIBady7TNt2YxPluvgNZjOX5Uw7MwP +uyAsJtRgBtk9y+VYXaeMV/7g8w8Lu88tJBCoNr8JGNFiIsOtIqPeKU7mRdr8QGNw +5tSgFoyG7jG+1nbEGJUHzK+SAqOLT5MYt2Z0sPHifwIYbwVe7IohRndxVWXsxwtq +C5SwZqeg1PUl4trt+T91nHfzA6B0+/EaFHWWnyFZHTD1sY9eLbTiatj5g/GtkOJt +tYRS2m5+dlbp872f0vUwcoe93D7J9d54jVFozjAGSQKBgQDiRj6dKJ9IPScnmNhv +ODYqkFr3Ui4STfAeI/FQofMoK0WWXzz6CBwhvzK0OTrXPZjXDkI+spbs6gzGQ7ND +0HBcdgzd4FoZzjB2S7E9aZySAwL9RWXbnucacAGVQI4jW2KSLMt2OtQD9AAd0gIG +pDkb6Lyxj6iqu93nq58O69qhDQKBgQDAhpjYD/XmFb7V5hNvtskQXqLZEHmUj/BO +PUxTiCs103vPbrTNLnm5l1Mk4LI04zAndP8hO1rE64vn0LaBqXc2Gf8lsgyjTAeK +cp+lCFPKOi0we+McouUfcWyb6j5fo0SgqCs8Vi4mxC/HTAS3G5Booof4blC8EvQR +2WUKV9vQCwKBgQCS+J1i5yfOfCoahiTO2OwV6X2sdyyFpyn36dCsVwThanngmiu5 +G9tp8A63ERUvCUtlJFXS850kdUGm5gJiYdkZtXPWCgt8B3li3PdatGaGUH54k8L9 +S9FAUtA0aaHpRUpZN89QFBXyG2KX+/hk5/ZQMnOdwXoEq9IO0GKYBooTYQKBgQCV +5bYHM5YPCItG2xXy+uvdNPGx86PVyaQeJpfQycpq5DgXr2hSAIeBupJfuhrGFsUd +U3h5FU981rBdUyFmHt3UX7VKUjCIy99rKgemZK9oWpdokmynlSSzsIoRcvYRXHtI +YucW2TqhsEpK76MUNf/fl/wprypo5JDnfM2wmetpNQKBgHtj1R7rHUsAye0yiLqq +VeSNcjs69KsVPC3rZrhxCx/768EYreYa3XfL20RgQwsSGt65OPnz7QIgVE5a0Ckr +vxfh3L18KtAPTPko9kh7/BGoROc8R85Jt95tmNB0QsCwaHvpmQukX5Q2CXRZVaOJ +dgzdR551cxWkFZopfrOy7Mlr +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/san_dns3_cert.pem b/test/common/tls/test_data/san_dns3_cert.pem index 552e8f2ae667..ca5b3191c4ff 100644 --- a/test/common/tls/test_data/san_dns3_cert.pem +++ b/test/common/tls/test_data/san_dns3_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIUS/zr5MA/czykD6IqKh4UQhk46WYwDQYJKoZIhvcNAQEL +MIIEKjCCAxKgAwIBAgIUCJAk2LFDOO9q+3twtS1w4LExj8swDQYJKoZIhvcNAQEL BQAwgYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH DA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVu -Z2luZWVyaW5nMR0wGwYDVQQDDBRUZXN0IEludGVybWVkaWF0ZSBDQTAeFw0yMjA4 -MjIwNzUxMzBaFw0yNDA4MjEwNzUxMzBaMHoxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +Z2luZWVyaW5nMR0wGwYDVQQDDBRUZXN0IEludGVybWVkaWF0ZSBDQTAeFw0yNDA4 +MjExOTE0MDRaFw0yNjA4MjExOTE0MDRaMHoxCzAJBgNVBAYTAlVTMRMwEQYDVQQI DApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARM eWZ0MRkwFwYDVQQLDBBMeWZ0IEVuZ2luZWVyaW5nMRQwEgYDVQQDDAtUZXN0IFNl -cnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN7x5F5jrr1ARV7n -5UkWOPjPYQRHLR2nF2AOtkynfFq0k7ZuBbeulaL3LjjzHv6eK2/lfOghM7qajijZ -J0JK+qgo86N1MxKWprPJbsZGt2mNHwnSNFzAfea0mkPS3o9Pb+QqfB4CUkk2kgpk -6jAiEp5Bh9tZ0OdIV/gIdb3ovQ5TZ9E4mg3PU+RbjIJIj6MiBQiNPojfcLNz5Lyj -GQ5F1u0YFX8bCbozf8bJKvbnDDvH1mWOooceglBfP9Ooxmz73KWl/S+XOOkWTo4M -kG2QbqbwQgXFRsCq/+v69SeFvblWVvUj+5kkTFs7kkz3dKwy87gpJwwS2rNgw5Gv -qAYTSO8CAwEAAaOBnTCBmjAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIF4DAdBgNV +cnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlA5ta4VGjIernY +VjFo0ssmf7Q1ZwYy7taJ8dNcn06k9cGoK9vlYhpig6CQ0NW0KWSIsb/BMbxybsEu +FihtTBYiroEt9hrYsurbTs3CTTI2fq3Rk1/E6A/fKoXRyh5wIu63lhHqq0+PKMUt +66Q8mqO0+yzyzwzi2IQtLNXkqbn9lLdOPrZ/LTXyuEm/XvbHV5gbKLtULoMzD9zT +yOBw+eP3lBwWkbqWM4a3M2D0E1qVe+6YEI0OOpYCoJ//NeQCD4PwRepGJQ4Q6Mlf +jyXnVU3l8RIu73KxYYtmk4TwGa+abJQmsfKzrzr25Zi8r3ymVbdOW2GzDZ3QGiFW +opFKTnsCAwEAAaOBnTCBmjAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIF4DAdBgNV HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwHgYDVR0RBBcwFYITc2VydmVyMS5l -eGFtcGxlLmNvbTAdBgNVHQ4EFgQUNS8X3fB+yccR6/gbVBHE7JC2/i4wHwYDVR0j -BBgwFoAU8C1rPT/4/p2oeosaE/i3eZFKT/kwDQYJKoZIhvcNAQELBQADggEBAMBT -Sq3E22yt3BA7xrfuM81WS6effDrxjVSoP2WGDDoYkksQHD04rrngwnZRLpq1EeN0 -d/5Yp30zj2Kvq3TW+MW2lCQN9BXJFKaZ1yE1+HnCITAfIXf+9G26UORTV0YGWSby -7vQJZy2p8+TaoV1JWz/Dc2VXNV4kmjj/pP8yrkQeEsI5GctzIb23a/SIifVrMg11 -fDO2fj9kxxwd4VMC6Lms8XH+5gn9QHHnR79RcNgHYsPAOAN48s+NJvsjiyqd+z9k -7DOvvbiyvGDPnny/1l7kGReZpYDJv4EMLibjOZgQdLt/aHvT8agRLIRzNm5X1+bB -Ckz0rRs2JXG38tfsP2I= +eGFtcGxlLmNvbTAdBgNVHQ4EFgQU2uz9/WstPx+1uc/dQugetDm01SwwHwYDVR0j +BBgwFoAU3O86c6M7zsm8uUvuaTtzu6ZurucwDQYJKoZIhvcNAQELBQADggEBAHaT +YjHF86XmfUhU2pui6MV0/+jD7KWeP6KdOj1rkNTVMpkg3XdDUSKJh40Wh2proCEH +uKbEcp1OUpfiW5wwO6bdDUlmuwhAFEUbkl8ErHpZazlbrrp7PgyTRZBtlL26hRVK +TSuXZKbIpG980YIfvABJY+kBPvt3bq7BH9ElTbHKUgia8EG1DtLBN7uZmMCIR2GF +N9sm3QGV2BzbPXw4DoVxnvUcVOouJtjQHyWED0W7BuUMq06d8VuNYBMUjjMCovb2 +tQZwsvT+Fb0OlkY8F8GIZZb/ufA/kZgdZLNiLf2b/qabko3aqHZ8qfvU3uumaCdG +WzZ52/WVBem+AvC7Ly8= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/san_dns3_cert_info.h b/test/common/tls/test_data/san_dns3_cert_info.h index ed44694a8416..0a68cb8b365c 100644 --- a/test/common/tls/test_data/san_dns3_cert_info.h +++ b/test/common/tls/test_data/san_dns3_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_SAN_DNS3_CERT_256_HASH[] = - "675534929d18f4c12f4f96dacfc66c8c293358871dd24d2701a165ac4e4a17d1"; -constexpr char TEST_SAN_DNS3_CERT_1_HASH[] = "e33fe38cbf5c3adc715848ae8c0554dec559ae9d"; -constexpr char TEST_SAN_DNS3_CERT_SPKI[] = "kpL7WOh2bPEEBnP6xoahijk3QgUZBcMkSvFvYGR8EnA="; -constexpr char TEST_SAN_DNS3_CERT_SERIAL[] = "4bfcebe4c03f733ca40fa22a2a1e14421938e966"; -constexpr char TEST_SAN_DNS3_CERT_NOT_BEFORE[] = "Aug 22 07:51:30 2022 GMT"; -constexpr char TEST_SAN_DNS3_CERT_NOT_AFTER[] = "Aug 21 07:51:30 2024 GMT"; + "ba0351d0085efede86ab77f09f18b862fb1678ef03c7b067e81bc8db724c3b1e"; +constexpr char TEST_SAN_DNS3_CERT_1_HASH[] = "8f5cc8fc8c58e978b881a168000522d6b33b6b54"; +constexpr char TEST_SAN_DNS3_CERT_SPKI[] = "3nWK+gGVRX+k/aQefVZI2xAW33NT+6OjJcnSye3t8ic="; +constexpr char TEST_SAN_DNS3_CERT_SERIAL[] = "089024d8b14338ef6afb7b70b52d70e0b1318fcb"; +constexpr char TEST_SAN_DNS3_CERT_NOT_BEFORE[] = "Aug 21 19:14:04 2024 GMT"; +constexpr char TEST_SAN_DNS3_CERT_NOT_AFTER[] = "Aug 21 19:14:04 2026 GMT"; diff --git a/test/common/tls/test_data/san_dns3_certkeychain.p12 b/test/common/tls/test_data/san_dns3_certkeychain.p12 index b01c0d2ff87fa33b8314bbc0571ae20eb4349938..1b5142ed280da74f2c3425234d3caf718259656d 100644 GIT binary patch literal 4753 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 literal 4738 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 delta 627 zcmdnUxsa2^powMfM3zz!pD!GH8l#X;@anF)TY3M&5OG8KGTx&Bi510k1~ zEf;@JlH6!-`6^oaL-L~I{JI*E(nG(Ny=ME+F^s~RG{^Yo!Xgp6SJ%1-WdecjlpV}RgZTgm&yEH52FNnQmsA{0h#tF2!?K>|cr>LPAi%8s|u1&X|-ibdE zJD<-j%W{Xq!XN7=r!)K2U)y2(<=W(l(W~DS_dcuLbWriW@w<&JatB{-n!LMhc9qC=FQTC*JVG45+0}Iu{JQqix6X^v5T?0h}PBvC;K4vB_Q7K$RnnSO)wKr(v zg}5`-oxiT$FuEM=GO>4pw26U*k)ffbA&`y|=QT1z;!d1XJ9#UkO#PyMD=t-#Z%_Tm&{iJ6+F*FR47{3`3@Rl2?QE8}*X z*!gmGtA8sp)M(msTu#ZG$HcayYPHOwE*{_NNw1%7IXN|Zk@F1e5J}l%pT%Uez5ci%v=7RQF(G8Q$c;*) zP+4Ub2?MbP5v&S$;X%U4&C0;s*vMeQa_HTII-jKF?z2>Q-X55dR3RsPOndc4?=`A# z=1RZ4nC#N(ewkG|!Bc6`{Q2zP&z|`5uH(+db@k2)6F)^LzYgEF^~{lA=h)X;Yp-;? zn9V5kpZ&=62mU>KQUnfH-N;>$)iO^zEJ5@~bkpyUy_%;4CGX99a`PJJ3XLjxyRwy{ zz3~->ss_q%S8<9Oim{0NIp>-7ciP#g{R_SJel6dj6!CjTut5{kIk+-*#`*@KZGVB?e;^x9>3L6$rfUN5+2gypz=%@MdP9j&DTG zgh%&i;LGWAoFd)knnQ z%FlDQ8BJe(Y!{yikgk4w<74i6;d`~}OkBJD0(*{pu&$rEIpWm4LI+2&iqjT}Sx=t} zeSd4y3^d~u8>eS~;iJ_}DN(JSwnYKT@7G+sezvA2=h?k?NcIOeJ;GVP z8Mp2B{1?o0w6*Mc_~u< delta 1250 zcmX@eyMb59powh_6C*Q_Dr4i+YV&CO&dbQoxS)wGou!E_87Le-Q7K%+!zKR3lITLM zK%VElQ6&o>uqfrfnb-{N}Sio1jsdnawpEIoxGJ%rv9Fwz3E3O z0fl#$WUP)A=51|c4lY)SJGgUo$J^g)-<_-9dm(1>4$;GxPPk+@=>7C(5bM6Z_+Hb^ zppGc98S-aCM3?_*+Vd#5gY~Rvd8CR*N_7iolI-iJ?W~>VKf_ZGGEDyBqn-ASA^)Ao zbA{iB+g}FT9$Kg#6kwjf^>xjqq#0U_2PX$I71THHmJ8?J%KPQ?JH}I~OI#lB*!XLz zfjk>?sH`%Jgn?Lt2v!BW@E~F2W@TV*Y-CtHtHdP8Yf{kuyw`E=t_jC4M;Qwme^6(U zpR!hU;3x zo@ynfewbvaYM=~v6{o177>h{g`AzP>>N@`^sm-oF`@i?Xh6y_a4VswF!j-Wz)-Pyc z+Q-twv#y+e}qJ!7?UB1_LB7GqN%OwIl##Vt_JCK;M%cm-W<% z%!5qKj0}uSjSU5DyG|*tw{d5_TVyoJ^)}T&L*yHE)`8X#0#Q^}p}8*zN8-Z0_@y z-NaCEf%9F3&xJrU?zMgXysF#p@|9PvmrZ_O@HhFd6TyG}(?4T@St6MkH@DZX?vCHF zB<9TTL$xgVH(zKk5iLzKZ}K^~>YK}s+`}n>KqGb?b)DAvZT7}RiYLl%%Bpxjm}s$K z)e(7dAE^m>SDON+>|`~Jjjd15)YzgoeeD{p57q+bX5QwvmF&@7-eRvltmOi)f)sgjzOb(gnH5eoU?i^k_#fPW)@zLT9%`bLu+;)1&O091v3g2d_l=V4R z#_hQkHRCozBg?cIC##wQy|d093htKmm$CC@Og1DoS?d}o8gR0)YV$EONdc3mNWALi gK)VpOK;0wra!S5z;R*4&X~n{E>Ew>;e$n+C0kY>MMF0Q* diff --git a/test/common/tls/test_data/selfsigned_rsa_1024_key.pem b/test/common/tls/test_data/selfsigned_rsa_1024_key.pem index d574dee2cf32..d792632f3de8 100644 --- a/test/common/tls/test_data/selfsigned_rsa_1024_key.pem +++ b/test/common/tls/test_data/selfsigned_rsa_1024_key.pem @@ -1,15 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDeET818RoQIO7SHDrGcW61gQNTcyRewbmriO37re7Of73QXJO4 -FcPSyERrgC75TwAWi9uj3oLZUohaFpgfzVQVp/yCvOJTiAXNFXdZJEhke4QJYh3r -5YcFiTf5V2XBAJP0TCtm7gBv7hTnIPvDh+lTPcKhJ1JQN2AK9azSYpgqwQIDAQAB -AoGAcIa6yiGvPEcD3XIykkX+fHiwb8PjxSRTakmLlkHvxbHTRFb0/43/2bpjeTnO -E8TlXYdnN+VT1r3MnCHg2hSYqyJqTm52mlMPr43trAZ5SnP7AiQDlWGQtaL/liHw -Je60efWwzitDr7y/cqgXIDlg8DtII/vYUCY8syUIY0NFewECQQD/eJamlQtUqVG9 -XXajtGSlgoqHoGZa5Qfa82YQf7nC3CxFlC5Og7KcwreYlPvfhD67icM3TP0HNDER -oEPdIPNxAkEA3obz86qLTtPU6kXTNPvQTzT/LFgPz/L+MxCaFGlo2bd/q4tfuKRc -zPvCfQRv2egrpBV1ZjeCTMGq9kS4bcNkUQJBALrFRZaJ9puxoiHId9kdJEvgkTiw -qsQfF0wakG7VglCUuQUxXV1naSi0LpetrCrwOxDOmdsPPRmMLaeOPK8ozPECQCka -8LFQDY+wHaJw54TgByi6d3Bvi+wzzLUOGggvOIkPFmxPwIzQ/7t1vgVt7mNoObeD -pz4MfutC0xvOserEryECQGnPKAAYUNzDrZRMDIPjxXOwg+i7sbbLpKkq9shx7Wok -jkN5XrzaWpjbAIEElpjJeoJRS2rNwlOLHU8cPk0BYzE= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKKPOjJBxOoILb6A +xmf533eGPZ/QB3nd7txk4yfLgZlFhnBJQn3RlDMYmSk11/GTSfUdQkp1t331Abc8 +XZ8efqv7IQB8KT8I02RungIGuHqrHKKKDE17kuvltMmVa6JDmDtUGR3G8xZsXlRw +wS16Ge2jradGo1vioPgEjBCep+8jAgMBAAECgYEAn/wcB2gpFzcTZiCwo5YMs0Jf +ldAT+4FLWobD9N9ZXfJJ3GqNUOyZUSxNWHyQWUVfDShNnKB8BS/DD4YOkdJeUOyY +nsR9GWYfyDzMTq6l1bTwUfvNVs5xnz2F4gWNeZstv1/hUSfY5xgaagzuWZR6rHJO +bVL54gGsIyDtj8grOUECQQDN/e88PPk8hUwUONT5zj1ogvVMPaPMUBt749jxba8T +3n0nAgq7TlGMxPA7mbNYyt5xQEEWeMs4YWrl5xL37TyDAkEAygYJSY9x4quCZFr6 +QjafUQgbpu8v0tiINCp92ZB2hRMeq1XF/VfIEo1H/4nkRnNB5tdXth76wG0/bNse +MtdA4QJBAJ4JfEnS3cS4362EDKG6wRI1psxfXhOaQfvCyuYvKGst/wa2YlVhuN8v +GMAhI5+zxQVOLqF2+zK+Sq0noz3jHNECQFDJDyeyS+lHilHVK6QUsaq2olAj76zR +1818fGzm3u4iEi6TkyPW2XPJuVPPcVBWwLCtxi5WvxD53tYJ3U6ZUyECQBOycUlc +3ThCXxFjE8VFpN0e9DDM9ubr5sEbYs+JjFL1e1HfqUhXBfYzhrtJ/lMCxYV251ez +uqkrJus7jT3JNm8= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/selfsigned_rsa_3072_cert.pem b/test/common/tls/test_data/selfsigned_rsa_3072_cert.pem index 892a62bfb046..86d671f8008f 100644 --- a/test/common/tls/test_data/selfsigned_rsa_3072_cert.pem +++ b/test/common/tls/test_data/selfsigned_rsa_3072_cert.pem @@ -1,30 +1,30 @@ -----BEGIN CERTIFICATE----- -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 -aAUo5+u8XHBLPrhiHpxpktZAeFQ= +MB4GA1UdEQQXMBWCE3NlcnZlcjEuZXhhbXBsZS5jb20wHQYDVR0OBBYEFA0EaDFd +1WxsZcRENFFqfs6C5QBHMB8GA1UdIwQYMBaAFA0EaDFd1WxsZcRENFFqfs6C5QBH +MA0GCSqGSIb3DQEBCwUAA4IBgQCHNivdoolKRcATW2j50cK9noQnPAWhdZ+DxsX8 +YCLK32dXfdjhxJiF4YCUxwd14PdNiRQk2CWn+jY+DpWw1wmF8A4ZH4efZNVsfmuv +ao5HlJuB142xo8xlQ7wSOeJRFpc4v7+zuLux9YZNUhF+d7fuvsEGe/iptQmqT4uA +fhTxcIAQenwDnbkQeZGSFHebO0PakJnGQSGW18brrCk/j3fqppRZEfsuaQERTGGe +tZOFp6rVyBxmG/EeRM1eAouwWNbpxfEoqf0IUa8TKnYzZo0z95GBxIpYCByo7Xg5 +n/hdFlbPYcZNMP4gmjuzqN7OOUuEJxMCS3OqTMrl1u9jNt12t7QqkKmNBjygtDns +1vq3dlWMzaZcflx/TLHP0mXKnnsIZhQM0+Mqg1f1wTCYqANMMnxShNGmKagZEAbk +oM4k+omEyEZo0JJdXYvv1IZ20SiSESEqEWjrbM8NuQDeqpTthEL/96fqtZCAvEJE +iQ9GJVnajs0wrJczz7lzk4322As= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/selfsigned_rsa_3072_cert_info.h b/test/common/tls/test_data/selfsigned_rsa_3072_cert_info.h index ffd8918cda4e..f9ca0d538336 100644 --- a/test/common/tls/test_data/selfsigned_rsa_3072_cert_info.h +++ b/test/common/tls/test_data/selfsigned_rsa_3072_cert_info.h @@ -1,11 +1,12 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_SELFSIGNED_RSA_3072_CERT_256_HASH[] = - "f41eb27c7095ee23153dd1567674f3954480bce9a1d5e804d0cccb0019ae4aa4"; -constexpr char TEST_SELFSIGNED_RSA_3072_CERT_1_HASH[] = "0ec1cb3334cdd2bfa0d70dbf79c02f86230523a0"; + "122dfcf45f814ba273b2c1e63df6d5ad9236157e07d44782a47814225e63097e"; +constexpr char TEST_SELFSIGNED_RSA_3072_CERT_1_HASH[] = "bda1675f0305337cf330779549f1b149abbd148c"; constexpr char TEST_SELFSIGNED_RSA_3072_CERT_SPKI[] = - "kzrqx6//+lmI/0QKjGb4qQKM5yEA80jfqB5d2AKw1vQ="; -constexpr char TEST_SELFSIGNED_RSA_3072_CERT_SERIAL[] = "69d4b91e126be26884dd3bd9013dcd0d4ad61620"; -constexpr char TEST_SELFSIGNED_RSA_3072_CERT_NOT_BEFORE[] = "Aug 22 07:51:32 2022 GMT"; -constexpr char TEST_SELFSIGNED_RSA_3072_CERT_NOT_AFTER[] = "Aug 21 07:51:32 2024 GMT"; + "WoFvBpLlfIeb1SP0jw8Q3OEV+Tp5kXk8B+1x65wXHHI="; +constexpr char TEST_SELFSIGNED_RSA_3072_CERT_SERIAL[] = "73af1f230bb45a6a1b8a9033cd01de3ae0f4a391"; +constexpr char TEST_SELFSIGNED_RSA_3072_CERT_NOT_BEFORE[] = "Aug 21 19:14:09 2024 GMT"; +constexpr char TEST_SELFSIGNED_RSA_3072_CERT_NOT_AFTER[] = "Aug 21 19:14:09 2026 GMT"; diff --git a/test/common/tls/test_data/selfsigned_rsa_3072_key.pem b/test/common/tls/test_data/selfsigned_rsa_3072_key.pem index 9f7b7c1e8e45..e22e33e5d676 100644 --- a/test/common/tls/test_data/selfsigned_rsa_3072_key.pem +++ b/test/common/tls/test_data/selfsigned_rsa_3072_key.pem @@ -1,39 +1,40 @@ ------BEGIN RSA PRIVATE KEY----- -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 ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +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 +J2FzqAbYgx8vTSQABQqlxgUb +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/selfsigned_rsa_4096_cert.pem b/test/common/tls/test_data/selfsigned_rsa_4096_cert.pem index 959f08cc0550..d9f5a70f1eab 100644 --- a/test/common/tls/test_data/selfsigned_rsa_4096_cert.pem +++ b/test/common/tls/test_data/selfsigned_rsa_4096_cert.pem @@ -1,35 +1,35 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/selfsigned_rsa_4096_cert_info.h b/test/common/tls/test_data/selfsigned_rsa_4096_cert_info.h index 5af3d1169d34..73eb1e1ff95d 100644 --- a/test/common/tls/test_data/selfsigned_rsa_4096_cert_info.h +++ b/test/common/tls/test_data/selfsigned_rsa_4096_cert_info.h @@ -1,11 +1,12 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_SELFSIGNED_RSA_4096_CERT_256_HASH[] = - "b8584190ad942d14f92ff2e20e35612736e179a568195fd27e02b91df23bcdb1"; -constexpr char TEST_SELFSIGNED_RSA_4096_CERT_1_HASH[] = "21c8e877136167f72b660e02b35ba3e252504a2d"; + "09bdcecebec594f3a594cffd4e163ded10a73331895c86d561559d70589eb34e"; +constexpr char TEST_SELFSIGNED_RSA_4096_CERT_1_HASH[] = "30be905f335a4cb514e159e454cb8267e4c8adfa"; constexpr char TEST_SELFSIGNED_RSA_4096_CERT_SPKI[] = - "DNMMJPogJFYjq9z3zphnzkDvSJVMkcEaXKTGN2xCexg="; -constexpr char TEST_SELFSIGNED_RSA_4096_CERT_SERIAL[] = "6a85e83ef52ba67a85eae3191cbdacb8b1b5b796"; -constexpr char TEST_SELFSIGNED_RSA_4096_CERT_NOT_BEFORE[] = "Aug 22 07:51:33 2022 GMT"; -constexpr char TEST_SELFSIGNED_RSA_4096_CERT_NOT_AFTER[] = "Aug 21 07:51:33 2024 GMT"; + "zabZtt3m3jVTPmOSzzoY5CiB/4McBxyVn5T9JfnWDQY="; +constexpr char TEST_SELFSIGNED_RSA_4096_CERT_SERIAL[] = "6c06f05a408c43930d2886cd8ef5327b33874562"; +constexpr char TEST_SELFSIGNED_RSA_4096_CERT_NOT_BEFORE[] = "Aug 21 19:14:09 2024 GMT"; +constexpr char TEST_SELFSIGNED_RSA_4096_CERT_NOT_AFTER[] = "Aug 21 19:14:09 2026 GMT"; diff --git a/test/common/tls/test_data/selfsigned_rsa_4096_key.pem b/test/common/tls/test_data/selfsigned_rsa_4096_key.pem index 95078ea39560..28defd3c9b42 100644 --- a/test/common/tls/test_data/selfsigned_rsa_4096_key.pem +++ b/test/common/tls/test_data/selfsigned_rsa_4096_key.pem @@ -1,51 +1,52 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEAsh8w75V+I4QuInR3qXOZk0/1xqP+Gwozygq3VI1DX5WoHdVl -GILVDDjHNzFLrXCxMdF/yjn/iLlxI22n7xZSRA98Xmyy556O7g90mnbBhG2l2omy -+HVixgL2DJsCMkD/dDUSkcJ5nxjcVWHxgev+4zAXnEsMhdHO17Gh+sLZlA8OvswM -9VztCuH4L5lFdZ9PwlM1Psk4/TIslPNR/OrtaqZE7qIlLwEPeFrXCMeQzUJeBV8F -lmxiLv4i3dNlHP/Tijm7Ez0MkrjHAYCl/lBoXfruNm+w4lylT2RV+UfUKm5n1Sxu -HPXqjxQe7qxMN/nPmE/fmHosK0m6OwxcW8sFGWOQIj7se9V/6zlwUTnqtVKU8G20 -bWCXKtZip9THWqSqv9JH8MTh1fJgJr6V7K0LAyncX6cJSitZXlc340WUDQVVqtB8 -yKGTz+Ms2TKLNhCYMlfAtU3pt7/2NxPNRK8OYOlvnj1UOJuKyKjSL/pwJ7Q3XDtS -7OCgU7egVtHnv6L5HsLJ9RDdgytPYkAlQ5xdQ5GpyjSRcaD8Q7YBGOoF8iOxw+2Y -yYs69knb1FFMamePPKLFT8HyQnRanXAvJp/g/1t+vzxDgJ/z1Pu0Z9tfEftAcYxu -AwaYQOFQ9ReW/jbWv8sorwp/f2VAjxbSK5ZkWt+cFCa5SVwQSkWF3rZXUxUCAwEA -AQKCAgAMJiB6VuHxnjRfWT5IKoBREeUblVfhlEKQB0cV10S/IkADOOjaUSIi4USF -OTGGNOeBFF749he9xZg36GTJ4+XcionbDuLs9V2eUyOK3Yq5c5kaXMX+OFNyWgVa -OsBdmR1TWcNYecE93r44fKOyTtxltoQFvwCtp+/Jum3n4p5ggN5qmRRRL/NjCKKa -7INWUHVqNa6uB5+BdYig6C+xZnynB4wwEpMir5nUha2hBauUtHAhQafp6J6Rwfey -1ZZR8gkFpoZh+4n9/+hi69lmjSlxL4pL4DZaWiNUVO2gQQvxkPI4Ef24r/U9qQur -D8lrD/je1KPVjI+yrCatnFw4TpKcWZGafhU+JFMC5mD75eRnTjWrx1AqoNC31Exb -FBrAwz/J37vPoKxXqGxH/9qtCB9L35muCacpaR3HBeLKcIh1CselWFjfflaYKzdi -OEP74u8ziUY3F0vIA4beyi+0oxx21LhMHmrUxmLeQefpIMeBDBYOn1JtMxVZswHc -LfKll3mC3NrUdQTE4Qj0s0aXVYfUo7Bz8Sm+1D5DF4BRiqeCxoGeiD8WY8ZndOfJ -c3+1jF1Jbu5DioQ0djBZbizlTWg4EK2tOf8NuI1lwXdXXAbrli0zVM6pE+3trsiv -2wmmEpXkZNN1rUMCWG0he7n7XWfmZACnqmumTS0GtFGY6za/QQKCAQEA2ZJU5Dkt -qyR1WsnvibkdAFj67t+Rl+NSFzfqAP8AHxgpj68UKNDE0cgBEOJVhA/HlKD/Grz+ -4NuwaikBmv3hUUNp7jQSCGUMGdrjDO4NVth1z1tI443+HakabKNgMveyIZJ1IU/p -Q7QYYg4KHjwoXAyyn5+CDR1WqCzBiu+/+EvWxHM90Nm+yerS9SdhHPZTb5fn3JN+ -3BEmRC1sBD3jMvaQUvUPQVVne8TahSIV7xFOb6neaLIkMC2UD58NnymFByvGdT6v -thN389YHZb8qlaXOie7X/7BpGnfCzRZkcF/iZcohoZZ/wJqordHSv/8bgeLVDV+K -k/Mbcm/XLmizTQKCAQEA0ZUbmqEx5gZJO8daiVjQaVDOYWXBuhQjmT4/zi4ERaB/ -JnAfIWUBvCUfmZ48KyONMxh2drIPfATx3kr/QbrZKap4x8/+603Gxnt1MYO44W66 -jvB0sMBU/eI6B5RBGhe3iFfmom8b2CU6I9JKs/Z/p3sHrqeW8+U4X0/kjQVP1rZP -iEOgdwn1TQOO76DXm/iCqLU9xQ2kFHZSJbDLifk6sbX83Gh5LgSHK5lNrsa7yGTb -hFWaT0zGu/CUoSVCrbOdGTxMS/w93XEgRjsbqAG+jq3oa+AToHKwcsD92MqH5LSL -6nmOK5daZGuaiN/eitcdAl/PBBXH5dGXqt1gBmeq6QKCAQEAqzNDC2aWsfF5SpxV -mYiI8ooRwj83wE3GfbCouGnvPYh0w7QfZ9KG3Q/FDvUaF1WXVTOuKOsIoAUedxqX -Qc9+KcSjKSXd/q8Ma5faS4VSB8FCSozo+O31RH+Y5F1WSCSyDUrCUhkgUv72pMmp -Wos5stzm/UW1Pv6T/rdhACORah66+1A3Fw0P3LCjmPaIqxKFKu1cLCv/ickQ1Frt -gRT1n1d2z2A3xdAfIrwOuu3MVpbGooUHFlj+ss5akEQ2osQ4AiGHAyD1gI8nNz52 -CbD4IFMdB1piqra0rXgJV/nDxM0eR7xa5FyZYAQSsNvHOv7RNU45GVHRqIOGWHD6 -4HDQjQKCAQA4ztXgn/jKhMGs9mhP+kbjhQer1s0gBv1vODRLSqXVyZ8taA7IGnzR -5q4eEYn1l3ladDMIEVOpJh35RxLRWjgq1w5N+s76MObEPgqSFUYztLPUstCuaDOh -bYSVMVZEIFGbH1hghwVhHRYZR5MAHLyVRP/cE4kTKvqQuzMUFnCBnoEISmxgV86p -xWElCs/mcwHXgOjxVLU45ql1lepVx7xlFxMnGxpdotSQuMkZqryToOLvh9R/0iu8 -HYXr+BGOy7S1dman4gNS1qsM3lCsxWxFeFYbh21KfEvfjvg/nwYes+GI+NHUdv4F -YjVNDIFh2NUAI8AVN2IrpRgbNE4m7kqhAoIBABy8eTd3GhBaueIpUxlGpefzr5j/ -PBdYRzrJRoih10VcpB3I6shXDsazWY6XHWhzxV0qNavGg8F0YeZbXzpFb+lmmoE5 -TKPTW8AhGPH3yYskGT89a50GfkcrWzj1oIuNd0sXCDSsSiEwqfyauQ5/8KlYlHlv -mBH5BPVPSMeZadPpw0DuuLCzrtS+/E1IPwmJUaDiG3gjAKzkD2hr3dNLGZCtg5Pw -WmImhRaPes5kQgAEYwJaJ7VeYKR7Q+/MqMYSiuuoyhPOUHxeJE62So4sise0QZej -F1glj9c8oiIFsJbr6MEnCe9odP0S2TGt4KN4YrV4iduTIbPcnfz7FJcqOVc= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +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 ++VUcSJx/bJ0gwv5k5cWPkjwOlO7REw== +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/spiffe_san_cert.pem b/test/common/tls/test_data/spiffe_san_cert.pem index 8687cb574b5a..32af6fe901f8 100644 --- a/test/common/tls/test_data/spiffe_san_cert.pem +++ b/test/common/tls/test_data/spiffe_san_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/spiffe_san_cert_info.h b/test/common/tls/test_data/spiffe_san_cert_info.h index 172dfb227891..dbbf88f4e5e8 100644 --- a/test/common/tls/test_data/spiffe_san_cert_info.h +++ b/test/common/tls/test_data/spiffe_san_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_SPIFFE_SAN_CERT_256_HASH[] = - "63aee87b75a338f6097c7d3857059738bb7df89644e7f5a586151bbd589e41eb"; -constexpr char TEST_SPIFFE_SAN_CERT_1_HASH[] = "38db5b2ca202ddc9da8fe23002c60899fb443acd"; -constexpr char TEST_SPIFFE_SAN_CERT_SPKI[] = "SdE6CKQC8KxLZHpT3b8UME/T18pnuV+7xdOhlzqyB+c="; -constexpr char TEST_SPIFFE_SAN_CERT_SERIAL[] = "7c252c75e95aa57a88f1f1c5cc3ff4fa9c5aa4d0"; -constexpr char TEST_SPIFFE_SAN_CERT_NOT_BEFORE[] = "Aug 22 07:51:35 2022 GMT"; -constexpr char TEST_SPIFFE_SAN_CERT_NOT_AFTER[] = "Aug 21 07:51:35 2024 GMT"; + "763efd1a257bc904efc1d16f092db79d4a7c3934da3bde9d0f2f89081411ab2e"; +constexpr char TEST_SPIFFE_SAN_CERT_1_HASH[] = "7b8814ea37179bd985904f6abcd0d3b565022cc4"; +constexpr char TEST_SPIFFE_SAN_CERT_SPKI[] = "3xDmK6zVxvJTHn7KzzpdZNqdP6B4ZqYXPetwlJlFfqQ="; +constexpr char TEST_SPIFFE_SAN_CERT_SERIAL[] = "3ab370888bba18071dd1beaf74e78c613e49057d"; +constexpr char TEST_SPIFFE_SAN_CERT_NOT_BEFORE[] = "Aug 21 19:14:12 2024 GMT"; +constexpr char TEST_SPIFFE_SAN_CERT_NOT_AFTER[] = "Aug 21 19:14:12 2026 GMT"; diff --git a/test/common/tls/test_data/spiffe_san_key.pem b/test/common/tls/test_data/spiffe_san_key.pem index a4573bfdcec2..2b8a7557df66 100644 --- a/test/common/tls/test_data/spiffe_san_key.pem +++ b/test/common/tls/test_data/spiffe_san_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAxr5n3CV5GQqqrCISnse3SXTBQMrSgTxS7PXdaEVEXcqIB9CM -NvQiEGN1stgJ++J9WdiPfj55DDRtHBODpTgXAB+MyiIXGjc2AEA7tOXlivDdNOFQ -oHfjwgKQDYNTDSmJoOOqmDTUE9nKuR2Vo79yItwEQLKjHl38Y7Cw+PqKxCscsWeb -zNsDWfuPPXMv1YNGljsadY6GdHa/ycvdQA2cwdq9o0TDkYWNUK5wkdxtTpJOt4YA -0e4QBn7q1Pn0ja6Mn3VhfaDequNVhIm54hEwIJ2eMLtIaxh5HpoMW4v6Kp+PZ1P2 -y2NDzjtwE8ftACG+4oQe8ne5Vkdy8Tnl9xTtMQIDAQABAoIBAB7KFrsDTyxy+5fp -O2s/04RcwyevhEcjOlGdkWx69ql1G/fh9ib5UWGqluxbDcjpALRvmWNceFJMuO6V -k1qAQwfw21XhTCTykrodOWLADvykbhCoK16A1FcVII4HX1F1su2q953W6Vgd8IsX -KzyQBzWhUkNXqW+l7djf4brgzaiwIrwGKXaqy+kthfG79PbxrYH7bCvb4glrNuPZ -RXhBQm9XVvO5pkgeO+wsVrIvGEeriTe5CYRA3CVHAHxQzFW3lULvoO9cZYU+Aceo -sk5qHzlZjFuOxItZYxwTlj2QlOQkVavlMGP36NIhkOj5DKXE7iQ4ULvbV1zMG1b2 -/KfW0HECgYEA/s7iaRMDe/U7rcYpaDAIuZqWzDluo9GADWroMWU0ott4Ly29aEqf -YVPkjaxJ6NVSNnSMh8o6pR17KLDdt3K6z6LUCh09GImfKEi/rRYyWdauSRue2jj8 -l0Jjh70bSyxkeb0Oma1V4JY8jOxwrLaq/Eq7CSiZSCwHRC1gsp/K830CgYEAx6xj -UrojTuoSRxkXIdChF4S7ucqowC+z/1KoCBm2pGiYz2JTVuVBsswxuMadUpsXreBU -fXXgpFHNIAfjcJrdrSOjsIJR2YDqcE/SksG5Of/JHW6X2fvMmODpE8GX4VPguLg+ -PwH0wjMemxPtSQp21oiYUmymaRfOqi/VLQQ/JsUCgYAZsiFQ+VLjoEJpbs9kK1vl -47oLVEtdB9aDA+HwgUVCmyFOmK0+JDBYb05gHxzA9yo4RZ6aXwF0/zkZTGS/iDlg -kQoTDwnHPLGpLVTvDor7VlPzGW72kMKgOlixKpfjB9IGGNOtGbbMVDo89+cQ88bg -dGTSMp7qkU4WSQE0YjrkPQKBgDCL60Ir23XOV09N/F/OV7xeGz5a1ZiUgJDtScle -ZxemDrEtWNHhv413NAeW0p1I9ALkbeZrCIkrElJdWKECJi94YM4DgV7+hwFzhuED -lMNTO1SalPT80YvB8ylIgmLYf+SpdwjesuGciC5wM9r0XlxerZosrHEUxrx+ELh3 -Ndt5AoGAZ1rYyi7SFeXnPcYacc2Cnkg4mWoUgur7uaElrxuyYJ3xDsjR28ALbdDx -ToB5b0tetFwElmHKXOsjKRA69uTkl1cBRAlvOe/kFkK0O73wULUNwn84PGSUiv0m -EyK6F5sGr8bKmUcMm33z2l7VRaovzp2qrNPJU41oYg8bL4k1l0s= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMwFBZNmvEy67i +lfl8H8awJMcRyR52dq4v9HGoKiLTG8Ao3xzxkPe17kzHhe9nsnEhuQFcDVykSlEw +qWikfhbf3bCl+RAIrqf1Nvjp5gW8xLKrRpFavn27tLjtK7WSuyxE/7oVJrPPit9N +32N9kC30ZHDCaGpKqHJbRT2MY/OmVCQk0U60liKJvwvkD/yk/ChHFK0uYjllagIC +itdnPnDZCKrwAjWjOofsDkOsdvkLQbHDIkfxKUmtzwJdyiE8MvgfIp/5LnJvYpRp +hv1Sp13r3KhYdhgLZzswlkGupb546KsjcwCXtPl6ynhALeIsBKTA3K2QTdyMjqBw +k4uX1Xx3AgMBAAECggEACiGvxvQ1ZrmYsaPFDSvGZBiJodydzj41xKruYYIC9rpJ +J0gEL9lVE2n/ad9Yv9im7xv/no4xrHvTA1M2fpy67ctp81CN2GomGe8mlMOjhxaL +m+uc+/C5YUEdjKj4TYMeqSrVTL938wkWkObzJO8zd6OhQEU+3Xfpn2tJBmmNeNv7 +UKHlvng5oyc47KzU8JT6asaR92B+P0TrTJOYHzeBZ58cJ+Ues5WHVcwzJZHDR0QE +YCSn4uRu/XV8U+e9XIO2tRKct1WDlP/rknDfI6L9VoPxGG+cVCowlYtoT590NBWl +/Gha/89Ls0WDFqdQbQnkxgVTyUpKw8IUUiYZ+bj2+QKBgQDGy3Gw4t4fIvwCnj1s +xnLrENGLi+9Ch9ipy+USmsFQgrDSEb7nLfAu7yvks+u9fSA30dcn/wnSFQqqS8yo +U2yMiTsZZ8zPTGJQe38ENdm0T3JQeer7U5762wH7nA9jU1x/pMh5msUHG44AOH22 +elKLYQAFjAhYC8y0SpAVMQ7MTwKBgQC1QP8cbdgGQcmETKVoCu4epXss0PUPdf30 +T1goVTt1M9RDm/ZFRrDHdKy0c9BnKApS/3t5ZpZsuOTOgwXJpLG7nMdibfzJ0+GM +AKyxexxZg5nEBzRhdUBGNZ3w35AZBXv+qwKUOFDBvvoi4K0Zr4/eEPsVOH+USqmp +R8Vt//H7WQKBgFV8Ktmb1VSiYKhnj5Z1B/nZc6KEfFCpxhvOGCWV8sdCS/MpumQD +NyOXqdJhJGCJrA8U52bFn119uuZcThecODN+17EnF8WU3ToqwQX4ejO1bjz5EHkf +DmBlSUb/ZwaZVE93dtYEHfHegYPKxxRvKYvSHIZGH1htSovE/IyAWhK1AoGAaG6K +jla7oN9GvHNs2gVyLTYrQicjC0VwjNMqeBKjr2OtaUbzHfcc487VsyMHcGghirCo +88mn4fyl2FalfwjlXrN2LcAxZhguW/wHhDrqmqi4b7m29HAaGFnMJnypCcGfL5xY +YA4SeY8PkAjjs2jz+37NK+zhlQ9vsZkop7hQNAECgYA374jtAqzn9j11VGYl3PC1 +VzrIq36yewlfAFJ4X/ne4Fb1rG2psS0aNlrJYJjI9UwF+T4HNZ/wuAaGpsUHvu5e +E7o4hMdLkc6SodRN0eVSsYv84yrZnlSE9YRH+MiumSPzynKU1S1mV3erhiPGZyXu +W4MSQGtSAXhk2wMOjAoY/A== +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert.pem b/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert.pem index 914d431a2dea..192d567703d3 100644 --- a/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert.pem +++ b/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert.pem @@ -1,26 +1,26 @@ -----BEGIN CERTIFICATE----- -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 -/QPZAbPp +b20wHQYDVR0OBBYEFDC0XxJkDZ3xMkZbT3+lS9KfTKriMB8GA1UdIwQYMBaAFNzv +OnOjO87JvLlL7mk7c7umbq7nMA0GCSqGSIb3DQEBCwUAA4IBAQAIqks2KG5Nmyp3 +jKms7MoKw0+lkppal/yPMBcuhkFGpNkBqU17TFqBjXmZYFY1I4bqReJd656YQpJJ +BOW8LLoUWWx+/y6NNXhCmOmo4iVfMOo9TFpjZXmoVHAA881XAAaoGLetWU2F4+mW +rOpz13i9vG7VJdPGMq5tvJ5F89N56GTXALpGCzlPYILLBa/72jL+TDrSorZVS4Dk +p8D8bCk43Uz6A4XUBiQEb74vRe6bVnW+Zx3SM8YQvUQac19WrRDDNAscYwe0901H +5tse0YDNlClDd8eY/eFxkWQqX0ssTMzk13N4u5cT1qh+Lv59vEGNFIQjG/Ydfcy/ +FbHMdyfS -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert_info.h b/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert_info.h index 40bcb7fc776d..d6a8bd6be149 100644 --- a/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert_info.h +++ b/test/common/tls/test_data/spiffe_san_signed_by_intermediate_cert_info.h @@ -1,14 +1,15 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_SPIFFE_SAN_SIGNED_BY_INTERMEDIATE_CERT_256_HASH[] = - "43cb2042a8d069de6e4b0b5e5c1d36b74db90c784e2cddd11fc30a676f64da41"; + "1d2c5998997f6b5965faa5f7ca91e131d403683978ce8f25b054bfb09ec43391"; constexpr char TEST_SPIFFE_SAN_SIGNED_BY_INTERMEDIATE_CERT_1_HASH[] = - "0d2cdf0876d70ad371f81ead0971f58c98def71b"; + "6ec7fe5005080f6e2ed96fa4406f2fab2416c103"; constexpr char TEST_SPIFFE_SAN_SIGNED_BY_INTERMEDIATE_CERT_SPKI[] = - "MWPq6EtazJ+l0y5xrKRmnFmFlJ9Ubg3bJr9Js6pwMw8="; + "iXPqcAw2mJDEhpY+W/Dib3FQ+QWG3ccyjf5t8qM9b8Y="; constexpr char TEST_SPIFFE_SAN_SIGNED_BY_INTERMEDIATE_CERT_SERIAL[] = - "4bfcebe4c03f733ca40fa22a2a1e14421938e968"; + "089024d8b14338ef6afb7b70b52d70e0b1318fcd"; constexpr char TEST_SPIFFE_SAN_SIGNED_BY_INTERMEDIATE_CERT_NOT_BEFORE[] = - "Aug 22 07:51:35 2022 GMT"; -constexpr char TEST_SPIFFE_SAN_SIGNED_BY_INTERMEDIATE_CERT_NOT_AFTER[] = "Aug 21 07:51:35 2024 GMT"; + "Aug 21 19:14:12 2024 GMT"; +constexpr char TEST_SPIFFE_SAN_SIGNED_BY_INTERMEDIATE_CERT_NOT_AFTER[] = "Aug 21 19:14:12 2026 GMT"; diff --git a/test/common/tls/test_data/spiffe_san_signed_by_intermediate_key.pem b/test/common/tls/test_data/spiffe_san_signed_by_intermediate_key.pem index 802a34a4e623..e4343025f44f 100644 --- a/test/common/tls/test_data/spiffe_san_signed_by_intermediate_key.pem +++ b/test/common/tls/test_data/spiffe_san_signed_by_intermediate_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAz4r1N9T1OX0papB4GU28ehmjav69guC6xDq0dE/RqCra49GM -cZv3y+W7ib/Zv1fS7aeUrnPV+csLuDzWzvNmoThYu2jCF36970a72J7eOitvN7kr -gpem4W0giE5jGW3pvCES5ufEznZB/2sjo8nxo93Dp+ViV9Y2wwIfxo/FXkW6I3Nv -y60fdYOw28wM5nnHXICOgsN8q/KQ0g94VMRUJ57G537SAqdHuyuc3ECTNpgIFqJI -nSJ9J7V0RyMpXXPzeRfHIMkKmjXePquoLR8SEswjmtedk/QI24hZzr7wv1U2ui/E -X/xQX2ypJQIJNNsaUBE2fnsTL85JmQomG54YqwIDAQABAoIBACbPJkG1edGxPPBn -aX3Z0nfGmY9laUyy91nAXIQvdNYMhXf6dFe+QZ0ILYR5sp8cLh4wqxXgJVAbjup5 -vfVfAH7/SWBqG3lHQv8ea/v64TVhb9+sqZ02/IbE4EN83P0hV4bNbHpvNpcg+ABq -KXT0S1JIItEfjL8+GGlo2UZJFjAlZYifEfbz0ww50ZbCI0dEv2BpPB6fvYlA9tGs -IejpaXyTDXHK23Z/xd75z+DvdxmO5zg7ah7SccY8xtFgG5XuTNlWso5/9oqEnqQI -ma69eIyf9JcQ4Whd+rWcZnzuFBgb2MDXXc/B3Tum9Ab9H3mCFi15JpBSa/NB+3+p -Rq1RL3kCgYEA7FgDz11eXLxKPOJOHlAPRKE/j/726uhjn3sp0SjlUvC6nzFKyMv/ -qq1G4OR7gaZw1AEHbxcrdj68nGPVTekTDEdJ8yUfMa5PUXeajCcSxR02RQw8s116 -xdZYSX1iQkFJdpz9D5GcvG5eSrhlIGMkDqH89SjlEchKuSrFyk09QE0CgYEA4M29 -/dkT9PYpZJaAqvBoPbr4NE7eQmeydAgFBEuoeZm6kFmiyVN/hNlCPQct1BBqCIxJ -D2nAnlLD+JOiJZx9FmmGjjVOtLXF0Bcxk9vz3/TNTjCSbIQR4N6PlswOAvHGS8Q0 -4tKu7+LY8LwtebylkVb79cRyTL0ECg5zr9+teNcCgYB8qGPCESY/VZT2jgrUFDgp -Y7+J7NpBxrcdHDJPPvnOCGj2pGIkjOzaEjELV5gJJ0flmnFYV+k1ohuLhWCxiljg -pg1MMO1GIAF4H9SlTcqpqyG/w5eUp56lEMxaXsbf2V2tMVqMxqnb/X7AfIfiUEhp -a2lnyd0gxvsatYPDk3/WFQKBgQCv2EAFkQhLVUKLrC55iBQCNX5xbD/vMa4llSBX -e9cNR3Ln9zWexfG5uThXBIaUm0JV7WY46EADmDoy90ieowo1vdXC52/pa0aQv5PI -VQUu6g6uWtAukiBqBa3MB1Hue7DhE1lLFAJDIu8PYCMyVp4sUh5E4KWH4VKHi0Zz -DERlgQKBgDaU0MoCM5V0gMVGVhbUsa2ny10kWc+MowZFwMHLohjKrmEEOfumR9Fc -oUleivDAQ9QYm6Ymfo7znk0ly7ahjstffXFSYhXcWm/Py51tlMzyjyjdKn3nz8yN -9Dag4/mvNyfNgftONBtVHn9S0QkZgWXd+h9OP7cFEW2VSVCSqVwr ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqbqkoo+IZ1vcm +1QLWRUiJ9xdXf2O1b5ewHvvZiAt7VHWudmC9a5kkZ81S3nFtxO8Xu7owlRjwhKNg +LGn0+M/eiTQzg/Ihjgos5KVVCyysHWuIg6AF24GCCyCT3TIqQD7ibuHsxjSYH/5d +zR5uoOr1k8sZNnYrEAQiR7ApaK1EEqLXlqWfTrxme1sr7YK63hUiX++fd49vwtnA +131wR9GU4jHLqT1dY92GaH0gcSRPMv83gRLyDvTC5f8SdfCUHxN1K64z6WinqoFX +ZFlNLKNxyXE8HX+MIbtb3N25wpOBF8baUwx73zulvgctp84RkevHwD2ozzRl+arF +Ii+CzCKjAgMBAAECggEAT6n5POtZsN1X2llgAZsR/Jc4XGhJyZG3VBYvf69FOqkw +dtOThYbpZuh0Q4OBfp86aRwRPEs9BJPjL/2iq2Sv+WOluFy5DbEwlWps05MtFuiL +jpyD7Kj9YLVlzWfr3m74Vewhg4TkKaVuxxatXmWuXgruuMLJung6jnF26OwqbTIK +8sVKGwDPY+RVcqPrch9EBP+/rmYHIbC4skaY8UbYOFSWxokh4m8eonwQTjfh6Eg7 +C6s7bzAnN1GFxcYpweJBpnkCCYe3i4NZpcN7rfANDOK+tML4cmwtQYhbZxF6n0EE +h5N4NG1OSWA83iBgHo9I4R066SxboxWEEUEvhkYFJQKBgQDiLTFbPeQEx3Vi87J5 +gdoYlFIwSFrVqGdlumvP7DRI7t3o8uuCTxafvamdXPj1V/Co2YVsv00DKBZ9YmAc +Hwy9DNAUPoCrRE7nICGVDUf9fN52brl861kByes6wrWhyn1EVneLydUcd79QS4yI +xETbuXYMGHJUlzcU/q7TKgBnRwKBgQDA58Q4rI//hZ7qAk8d6fl+SfBXoE3Wt3wO ++D/E3bWqU0B/wjDfSmmhCJlHPobi5WhgBSfTsITxklBW5N83sMTOcqoo9xQRQoZK +x1tsi4IhGY1KRZglobXtxg9/BueO5DSu6P4BgCyN8bd6ex9zhjl/824Qs4wQGBce +Ho4QENSPxQKBgE9gPOogll13AqNvkztBbyEhLJb1TaueJmt1OVEHPHI8InUWi8B3 +sSDulxA7CMRR0IvxivnXSVfKQdpPJBu6aeYPEReJt+5jUq2agS6mMpWrtQcrZL2K +evo9uugsXUIipkPNdLcCZmBPRj0PxopZFzFlrSAhlD5Ls3ES0JgbLXkRAoGAIsPi +LiCTVwaazCucXJTFPQhQQ0qFnLO2rO/6dh1K1yZn0l6J9kPv43CsRxWys4OKmvty +4QjH/M1Uo0ReIig+X8J0fiuBN1cY4rMo+9fsnNCBESiXsfiB1BdExazV4H+qKvec +h2K1JOOyIGW+FlDTXgbeCC6DiIb+65OwIJ8X380CgYEA2NIJ+pZhJ0Zecg902Gms +or7IFROc4tbzqZjrft9TBsAUs5g1LY+J+Xwcbzwz960BaXPEAJpz6bUer56c5ZhD +R10jGGE/oKQU5AnAKDZLZALomXGcyfYBCqwq8IbMUzem65SimCcDiq9UMQ12qeXj +vAymSGz/FRkKBQ2OaPUe52M= +-----END PRIVATE KEY----- diff --git a/test/common/tls/test_data/test_long_cert_chain.pem b/test/common/tls/test_data/test_long_cert_chain.pem index f4e8d07490a3..b057dee10e19 100644 --- a/test/common/tls/test_data/test_long_cert_chain.pem +++ b/test/common/tls/test_data/test_long_cert_chain.pem @@ -1,72 +1,72 @@ -----BEGIN CERTIFICATE----- -MIID7TCCAtWgAwIBAgIUfCUsdelapXqI8fHFzD/0+pxapMAwDQYJKoZIhvcNAQEL +MIID7TCCAtWgAwIBAgIUOrNwiIu6GAcd0b6vdOeMYT5JBWIwDQYJKoZIhvcNAQEL BQAwdjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM DVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsMEEx5ZnQgRW5n -aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjIwODIyMDc1MTI5WhcNMjQw -ODIxMDc1MTI5WjCBhTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +aW5lZXJpbmcxEDAOBgNVBAMMB1Rlc3QgQ0EwHhcNMjQwODIxMTkxNDAyWhcNMjYw +ODIxMTkxNDAyWjCBhTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBEx5ZnQxGTAXBgNVBAsM EEx5ZnQgRW5naW5lZXJpbmcxHzAdBgNVBAMMFlRlc3QgSW50ZXJtZWRpYXRlIENB -IDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCnn3lQ/xWkwknQcc7 -C86RE14xjer2OuG0e4Mn6oi2MzrJFPaN/MKupTyfKRAkNmujmW8/2wlwVMY/E0+X -eLoawv07WUyPFbmqBFswkHsHhknknnFJOWl/VjtjaHnPfHqrfWzi4LcAhmlIDAgl -/ix1QzSWuyvpjrcSUE5u+JmcxXUD51Yww13AtJmNBYZbJaWK7sOdvS8MnXH383PZ -72E4cBIpDH1bXSC6hWupCIbw06EefudmckWkYSJBD/i9ClncJSPYsjjDtuevCLGN -hIA0Xt/ANO9m2XOMIeERVg4jJRt8w8hThcWI9dzKOShO/9lkKeRbJ1Defgy8Wi0w -TvHtAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBTB6L9hP/NIqZ7MK1WNB2aA5VEneTAfBgNVHSMEGDAWgBTlhlEECSUg -omd3eqqOrfY4pJIvIDANBgkqhkiG9w0BAQsFAAOCAQEAl3UVhXfeCQBBvINpIUJO -fLnpNd9cWmfgd40XgSCxb2HzFlxevr3h70MLPMS1dGY03p5GwRd95hLQZHQEY8bi -jQWktzUj+QOtuTWopJU95sMjogXcOBLQNpmmggTPLLxk/xgc/9zoDokFHK08oOt4 -IedcfbHtLgxMeL4W5rGsOOc1lESMnP98pyKDIElRCWjRAR2PoUsMr/WjRGKUNN1V -I5mjMkMgEi9gKDvKClk162hGyTn55PPWGz/IJi+zlAFs2H2cKLORLpc2MziC9U4b -dLJmNWPtxHo1TRMdN8kSlUAJZFiV+9A1LPEjcUzXrSbZ5dQU5MLHMMgy71GgPJQr -+w== +IDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDySm5jDEi+iTEMxCHq +2XsTMRLvjxk9mIVOstRQ4qmWIv9upCyGF7fx25i7JeLfFS1U0Q/6U4Ae064pUjfW +KTD2zmhjca12L1zQd5uJ97gUVVlQGGrAZpbE+uNv3BVdClXE60lVbQPSVxWO32L5 +u3T+sO2thRu8sbhrCdg+fH7d37X689szM7zUWboPCKvBfT+Rc+Pb4aPKfz5CX/DK +1Hi/N0C0qhulpxM9DfRw9hnVGSMyc3ViDRVs7gxKmoQVKlg4ZsEvqaqCkubXMzMO +t407r6rduO2dwS4hpjpX3OwopTSDz7unRaFmz+WO2rX9Pn4b223GxOI6Wdx3MuOq +4kX5AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBRVaoWCA7AEY4z8XN5YpfTwhHh2dDAfBgNVHSMEGDAWgBQPoM8lvVgX +fggedphlyUOvH0+FVjANBgkqhkiG9w0BAQsFAAOCAQEAQTsVfW4824chRNx0Nu4Z +dyoVNXKpuk0vOJSRQbG9b7owN0lh4bV/RSj72vgrxBr2ebRqKs7Y3XRCtueHtwlL +ddINNo/pcrZthwICIHTDsB3166HogVoTO6RABJD4BLBdnGTtU25MB6RRP0vnWjcm +UdSa4fx39yXVJvbQphuXU2NDkCRXMML9So9BiNcmmM0+kxG/KMPaZi0GrOAhdNrj +XVmDI7JO6dSR0O0R/IoDVRxvB8zEAVzhEqX803+K6QMkCBcDEPIGeQ3NYLChQ6eN +a64s9X/97YDckCC0igS7MguOuTgS6y8RAcTh6E79gPztra7+VJg9jpFJ/HgTN7xH +pQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID/TCCAuWgAwIBAgIUHlMRdawBqz0cPJZjiWMUnrfZJKIwDQYJKoZIhvcNAQEL +MIID/TCCAuWgAwIBAgIURwiSMlGPZRbFFc6M+UTTR9D7pg8wDQYJKoZIhvcNAQEL BQAwgYUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH DA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVu -Z2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0IEludGVybWVkaWF0ZSBDQSAyMB4XDTIy -MDgyMjA3NTEyOVoXDTI0MDgyMTA3NTEyOVowgYUxCzAJBgNVBAYTAlVTMRMwEQYD +Z2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0IEludGVybWVkaWF0ZSBDQSAyMB4XDTI0 +MDgyMTE5MTQwM1oXDTI2MDgyMTE5MTQwM1owgYUxCzAJBgNVBAYTAlVTMRMwEQYD VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQK DARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVuZ2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0 IEludGVybWVkaWF0ZSBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtVeP1pazW8NLcVS7OKyqovH8iSaTUeira1DWLpsqZJYfL/FL1JEGgKUiWrbB -ykZVsZqsQ6BgHGNF3p9NNHAgLtDXitEiDhVL3QpM1hXSz9xY0xeZ7ME5ts7MOsMW -99gl8eCplIiT1TGJAaIDkso3suo+Kl98aIZCZ0Vcd+Zq+Z8LYS8K6T56FI3hn1+h -nryJBfkwh8LOZ4ldZEoVGTWeIgFPPYM/EMvBXo8A2INUarWsuguTNYM1vMn+5U8q -qfRjxGgY+99m2fnyziKfhuK9cJEOHt1pZ85YFCJZJDs4LHfGBV5jiJ1XFmlxyh2e -x3ZE/cBzjX4jOW+0KfiXhVmHawIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUv6SulIanZkxyTbKJXu87LWXIkoUwHwYD -VR0jBBgwFoAUwei/YT/zSKmezCtVjQdmgOVRJ3kwDQYJKoZIhvcNAQELBQADggEB -AGC4FGy7fO2fOpPwejJEV4m5dOdk/t03NZXwZFa1gxj9W8awr6eFRfB3ttFypQl9 -HKfT9mlAUq8RbEx+NEsMv7utZaPvdG1Sohz/rHMxEDRNSPW2xPk6OCF43krBvFt9 -ZH5OQ+2+2QgN4+akXH4MwQRV7m+XP20aM0hhGFwvYglNtnXHnQOskw/wEdSNHFBD -l7mswAeCYxOV8ngyI3AHr6DS7q253HxceMysWLP8VXoCB46L2TimU2TFNNdCkPOY -+qrtYhWE3jMFqhB/Bm/Sw99aulCUe5GNaNWzbeiytAKoABucX2BrNIambT1pJ52K -RHHZtgVCs9Fq9RFjVcxyc70= +AQEAzQ4Pf5899qGHfzxGLhaiThO38Y85mUF0Dc6yO/3SDkfXKKTMq7n2fIsp+IWs +nOLp2ruruwxqJbITMer27ErTuB/5nATsk0Q1YjxSzWR4NvgQeDSSvZVHiiEIKDm2 +2j/ljyfHT9F0wtzOHJym6PN5Z0xkMpi/2X2/8CwUQCk95k7hqriofXjit0So9Opb +1DeFc+GHRSnqRSbRMTKifJJYt4iVYpPX29FeAPj8QP/E/M2ZojAkn4vIdJA2Q2wr +k9V7L11jB5wKS8aiCCFcj6HH8aJTpeVY3IbPBvuuTgVDZYxE/6K4wQKWSZpjuLYw +iaYJmxiWJfmBacy/n7pof9lYMwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUaURx1UZUH9sqf+0sJCUYy0xTMVswHwYD +VR0jBBgwFoAUVWqFggOwBGOM/FzeWKX08IR4dnQwDQYJKoZIhvcNAQELBQADggEB +ACM44Rh8uTuZG+Dv2nbXA2ugYBdEhDrREMAaM2fEsXE5RqvBc1JhdBmUi7/1Copn +rEUXlYYbzhmTwb9TPrHl1gW58ztb2+hq++nOo0/UOhF9SH/G4K3ydpzJD2j4zzjS +003zx0riGx9+yo5gZutPaoohOe1kRoFYDfHmfJb8RunsOIuhonIohCLbs/Ud6CZJ +5+zXHPvU3Y5Z6i33+Ndv21h61QWKKlh+Kc1PU/B3sv+DlJn/jIN+Xsj0EnuERS+4 +6chMUNySTTnUp2B9iypZCFKHQ1xlusEnEWtcZfJhGBpQG/zH6aSIfT7rBQ3rrkne +Q70XFUIbUs3y5+1C7suGRao= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID/TCCAuWgAwIBAgIUWhRPYdFyZmQyg3/couXWim1m4IgwDQYJKoZIhvcNAQEL +MIID/TCCAuWgAwIBAgIUFDnIux7vwmS1+LGO+PzDGUXxu7swDQYJKoZIhvcNAQEL BQAwgYUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH DA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVu -Z2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0IEludGVybWVkaWF0ZSBDQSAyMB4XDTIy -MDgyMjA3NTEyOVoXDTI0MDgyMTA3NTEyOVowgYUxCzAJBgNVBAYTAlVTMRMwEQYD +Z2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0IEludGVybWVkaWF0ZSBDQSAyMB4XDTI0 +MDgyMTE5MTQwM1oXDTI2MDgyMTE5MTQwM1owgYUxCzAJBgNVBAYTAlVTMRMwEQYD VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQK DARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVuZ2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0 IEludGVybWVkaWF0ZSBDQSAzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAyA8qQumi0FUgwDQf2BnIJA7S0Fcmh5PJrLyHxFv+pA+D9QCOj/ju3fXKVbuB -tuINwhtQopv4Ok4Yqq91GKZjgXywhBAnVp4k+HHwVlQ54DMXk68gjrSog/51b4+z -LkyV9ScedvibuiRNZVsTbCTZWV3wjMklSJ+/8cXVRIBjYHRUYwTQvQU1isT8AY6W -NNt8TjAb2iDhLj9LVhgfnD7j4FVqxLXeMA3GMjvI9nVYMSUT5bqf5WhoVWlPbzpZ -JUgW6LceG5mO9g/F6XXQLih9qMVJXz1/5W6HMtwgCxbGZu4RmKHYWP9zBW+0+0Yc -S/5uzj8jPfHlbAQPwpd7b+U7oQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU4DWZ/DL8HISRgBvCncXpiYIQOH0wHwYD -VR0jBBgwFoAUv6SulIanZkxyTbKJXu87LWXIkoUwDQYJKoZIhvcNAQELBQADggEB -AAH0+T2uGcyZeB5gihsrJu9MHQlvrV0c4rGzck6aYu/+GVp6z1ST1FVHYPFdTCx3 -ZFWDRFiM7Ung2EchDZmd5ltmolqSt1qFw+FlAS9OJ1lTG01AaqgE8LpMfzo+ln8j -EyLQ23o3lTGCHiQ6kFOv9GwvDRHOTSqpLh093kpeqH8w2X3hQFoQ6ydFXJP8ZnL7 -40mJ43K45PjzYUQq1fu9E0oHzGKTN+HJ3ROJlqYx9KEoIbLOEiaBwGkUYXPHJvss -glQ8fodXEfBAkOC5IbGR4MItKddaVCyMFF8xD0/IzQdzOwgSWL37mjIkSOknhxeK -eFkYHrrkjA84FdC2IqkYku0= +AQEAg9SQkje8dgpCHOY6rN2QhBCzPzWN4fXBQnfoUZfQ3GcBHVrJkxguXTieG1Gi +4GtULYVwCpAnkCehIPOoi+drr70Y+cbr8ZwGczPK9ehljBn1J+RNWtTaG5UaDsRz +2lCdVmLv5ocWA9xowWRMxL/awlAFaYFTirHUnxZZl2EXgF8X3NhkOLOv1bbnmGsj +jZdGKPcLZLxB7P6jWothgpBlTcvszYQj/0rPJ+tbA2RQlotZbt5j0mnn3RGKv10o +ePRBYAKvHSATiAdYYBdjRNP1Bc0Dnonaa6FNpAiRBZ/bN491PaqYXPRcOmOWAjsv +XTxL0SpdRAT4NnCvZgPrKQfYLwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUeD+JQi5GX8nCsG9GbVCORWS0xpIwHwYD +VR0jBBgwFoAUaURx1UZUH9sqf+0sJCUYy0xTMVswDQYJKoZIhvcNAQELBQADggEB +AL9t7cCLwwydUVexYGMiES9g3XmaGv3nHLDWXKt9z+aWgBub2sIU5Qr4nszQcU8e +NPwwl+VS6N0bcY3Rk4rHQULAtQiBzOS6cKEQt3G3CYPRUpIFjl40HVqQ0vKy/LMy +o+1+4DaYswdqJQjKk3cKMDLA/j3rurGFcnj+bEOWhmGhK2chNGns8sN/8fhmhgf6 +NN8mjK1LZrEbL972C0MShHQvnYRMWJFLWuhylm0M3e8LkShvdTZroMJcX6U15Vsc ++QeJPlxxyOB0nESvjaBTFK6wBIYbfipXdJ7P72LvGEVbe3b+ARJK7ui68CtQ2q0I +9EIp/ZPcFjNTrjpQNSf1zjY= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/test_random_cert.pem b/test/common/tls/test_data/test_random_cert.pem index 724dbfb0807c..df8631c68ced 100644 --- a/test/common/tls/test_data/test_random_cert.pem +++ b/test/common/tls/test_data/test_random_cert.pem @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIEHzCCAwegAwIBAgIULZl7kAc+Z60Xqz90WFdr2ADttwkwDQYJKoZIhvcNAQEL +MIIEHzCCAwegAwIBAgIUAsHkNCgt27m3lB69NW/ETFEjHdIwDQYJKoZIhvcNAQEL BQAwgYUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH DA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVu -Z2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0IEludGVybWVkaWF0ZSBDQSAzMB4XDTIy -MDgyMjA3NTEyOVoXDTI0MDgyMTA3NTEyOVowgYUxCzAJBgNVBAYTAlVTMRMwEQYD +Z2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0IEludGVybWVkaWF0ZSBDQSAzMB4XDTI0 +MDgyMTE5MTQwM1oXDTI2MDgyMTE5MTQwM1owgYUxCzAJBgNVBAYTAlVTMRMwEQYD VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQK DARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVuZ2luZWVyaW5nMR8wHQYDVQQDDBZUZXN0 IEludGVybWVkaWF0ZSBDQSA0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAyZCqBxQLVnrC5Anb00NV1LvSxvIODtXbql+R0l3lYcquOZaW9yzYNn8EDPvo -94zAD5XsVGsT2Db9o76mncZkLOhCd5ZTENPdHnWFYKyYE+/DcCW2VpkEwEBFKnEn -su1Nkuv3FIosN58N9VqtUQpTRQIAmDdVzxDXtttChX8udpaeTcQGpXEAmjD0x4wJ -5iHJbk4g4C1jb6YzrAwnVykb613Gbz9sEwedGFWIegf+MJSb3/y+4S1wM2vFiRl3 -9tLNXeogSlYNsUFRBxk1YEdfLaiEJ6O7i7Wt7zjchkxbdN76ycsV0CkzYL7muLLI -QqKJ/L4k7WdVSEqaXUZHJtP5AQIDAQABo4GEMIGBMA8GA1UdEwEB/wQFMAMBAf8w -DgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRsbXxcx9YWtzC+zuCQXT7+Ic5luDAf -BgNVHSMEGDAWgBTgNZn8MvwchJGAG8KdxemJghA4fTAeBgNVHREEFzAVghNzZXJ2 -ZXIxLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBAnYTELar8Vrs9Cisi -YR23oNL5VB/ZFtGj+MdBVL5BeT0xZqSNxj7hEkDQQ5JkwiMjFou296/2mRnt5/EU -KLkdM4eqfezCtgjjjZ5Q2MtpchiUHZaDyGlOuCdjyas6nDtyOhdpA6/58IFe98se -4cTF+CneV6/8FXndQXz3jmbUEYiED2PXTosL1W+dpgWDaBr92250oiApmWTIo2Vp -T3Jh/lDUmjeUluCiXOApGC5JL70HUE4mpBVAtgGhGlO2Am6JMQwEZm0mDQiU8pvc -rQCbrKZHNk/D8csV6U8ApKMihy+IfxG+MdnEkftYiDY8bUOw75tpf9CCmJ1wnn5F -TU4R +AQEAvD8dqra4FKafZ9TbYgqoLZkXawJ+/pyLCiqYehPdivIFRKsIdYDtv0u4AY33 +iuA0WSM5Ywizyd0vkpU+J0W0QQ6nKagNv2brrHySOl84pW8VCVPt5vuPQSpHiGR3 +2/RpsAPklnFUx4s7OqAlVvKBvS1NCBMSya7mFq7jmyzTqSNRVmSlEuIe/8qLdIRx +XU5zr1FJaAO4EN00y3pueR5Ve7L5SGhuGyMYf84uDjtPelDLhZVco3YfctIcSiDw +EnCMNgbhvJ+PJQvMhUg91h0XxoSOg7npyDtWVYduCSspaYqG0pkrSsyCz3ZlXT0/ +tz6sDIKNiXhUMRGK9BTRw3MxxQIDAQABo4GEMIGBMA8GA1UdEwEB/wQFMAMBAf8w +DgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRp4ZwGKxP/M89Afip39qwrn/Dg6jAf +BgNVHSMEGDAWgBR4P4lCLkZfycKwb0ZtUI5FZLTGkjAeBgNVHREEFzAVghNzZXJ2 +ZXIxLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQB1fb6zWtP6aC8ioXX9 +46dFBEmWeCxN2yc+HMKDSHemNR2Vys1MUkHGyrQxxyvx9nW203YiTJ8Ft4Cdw7gb +42K95/B8S3WKbIMEoSSMEb/1Lh/H5zJQae8s8FX0ubNGeKKbJfiTlmRVD2W9iX7Y +ju3hFjdQDjII3TJ3Wx3FooZDpYqQtw90AXdYSbPM+4ZxiofaLLDjA8IqLjmxZVcj +dELFvC0QQZAEXBh3FXwAuYo9AGRfh1u/gCjsuiS62FN1v48X+De0ngGGHDIenI94 +FTfhVA2T6zFxQJoe4dP4IvOEBDeB7jImUu52XIDaP/AODkiEUJRIhEybEQY4k0W8 +AAVf -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/ticket_key_a b/test/common/tls/test_data/ticket_key_a index 1b7e1afee53b..d51d4026c77f 100644 --- a/test/common/tls/test_data/ticket_key_a +++ b/test/common/tls/test_data/ticket_key_a @@ -1 +1 @@ -�v�E�r�f��`��䇻�1�6�fС�OL�~��U��F��Ŝ���W�?�V�T�����lA��L@�%+A0@:�ɞ�z� \ No newline at end of file +k�qЉ,�`��ٌ=�������_I�ю�K��xD���K#�!���9� �<�͑F�ls t�7���S: A���� \ No newline at end of file diff --git a/test/common/tls/test_data/ticket_key_b b/test/common/tls/test_data/ticket_key_b index 9971e4969808..cb7f8acdd50c 100644 --- a/test/common/tls/test_data/ticket_key_b +++ b/test/common/tls/test_data/ticket_key_b @@ -1 +1 @@ -m�`R;"�抵�}�����I:�VG9u��j�g�9�"R�4 k��5�˫W�c� 78=�{�O�ڊat�c��ғ�� \ No newline at end of file +��D!jЗů��@�&�B�����y(-�kR����M:TRɑ�C.z����ƽ��5^�9�tFA������" \ No newline at end of file diff --git a/test/common/tls/test_data/ticket_key_wrong_len b/test/common/tls/test_data/ticket_key_wrong_len index 1ebe6465309f..279362fce8be 100644 --- a/test/common/tls/test_data/ticket_key_wrong_len +++ b/test/common/tls/test_data/ticket_key_wrong_len @@ -1 +1 @@ -j0ُ�!���O����M9�ꍍ��S 0�y�*X���1#�p[��|�m%J�r$� ��ܿ���c@�O�ȃ�N��#K \ No newline at end of file +b��=Q����x� �m`��?�怋Z�k�Q3�4�+Kff�sTFn�[t����5���1E%� pI����$ \ No newline at end of file diff --git a/test/common/tls/test_data/unittest_cert.pem b/test/common/tls/test_data/unittest_cert.pem index 7cee3cdac03e..427a4e2c8f59 100644 --- a/test/common/tls/test_data/unittest_cert.pem +++ b/test/common/tls/test_data/unittest_cert.pem @@ -1,23 +1,23 @@ -----BEGIN CERTIFICATE----- -MIIDwzCCAqsCFGKnKUog8O1M0VeT/WcfufdDCWD7MA0GCSqGSIb3DQEBCwUAMIGd -MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu -IEZyYW5jaXNjbzENMAsGA1UECgwETHlmdDEZMBcGA1UECwwQTHlmdCBFbmdpbmVl -cmluZzEVMBMGA1UEAwwMVW5pdCBUZXN0IENBMSAwHgYJKoZIhvcNAQkBFhF1bml0 -dGVzdEBseWZ0LmNvbTAeFw0yMjA4MjIwNzUxMzRaFw0yNDA4MjEwNzUxMzRaMIGd -MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu -IEZyYW5jaXNjbzENMAsGA1UECgwETHlmdDEZMBcGA1UECwwQTHlmdCBFbmdpbmVl -cmluZzEVMBMGA1UEAwwMVW5pdCBUZXN0IENBMSAwHgYJKoZIhvcNAQkBFhF1bml0 -dGVzdEBseWZ0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALK6 -J3SMfpl1HlKUQBWll2rtbA5BD0ZzE/tGaRcP0eBl4mNgmnYdj6ESujwpXrzy4qZu -NXbeTuY5TcjVcbub2n39D/OZO0Ipp2pGaBe2g/8f/kcpRynBCitROYeUW1Q7E80y -wp4pfT/GVVVb2TrpFDSHYBCfe+fpKkD+n1M7+326zdQ3eL4qV/BNPDZ6O7iCUqUl -GPn1+PVgZ/GeBzHzJw7lSyaDlo+rK6UT3WOjV/df4v8/UinO9ehzXrs7hI8MnNaJ -6KI3k6DUL053KjZ/u8FoWmBC2avjqY6LlSim3++seVPrl+MJC4KfgW+W649VquVs -wbmPAy/mr2JY/P9dm0sCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEArS6ZyAWUayFU -1ZQMQdjWZtWKp5BHapYr2jfu/jDiQqLS5Pig/CzIKg8fKEwKqHPB3VX9Dv7aX2Xj -2V7iiEz+rClZlb3TrrtTiCxLcDBj58p9xsQzvapI+Ie5syrKqf3RpIT6iO+fbAdI -UlRHUyEg3HhJKAF5kKY6JUCQ0EN2uuLDKHJ8a5UCSNOapZRQMYLT11+VjjVM1ki6 -ooG++rHJDa9nI4K4SxS7/dN+dwRv2e1KGaHuqmS9PKX0LqJZCUHZr4W9LDm0C81U -uSew16Wn7ve6xbxPgRdMLJCErPp8LcJhr03t9Ee7/vrPvxqDd0TZcmjRaS80IwHC -IYPF9XJ0ag== +MIID6zCCAtOgAwIBAgIUD0zbm8JiESefJvmlYgUn9AntoQAwDQYJKoZIhvcNAQEL +BQAwgZ0xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH +DA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVu +Z2luZWVyaW5nMRUwEwYDVQQDDAxVbml0IFRlc3QgQ0ExIDAeBgkqhkiG9w0BCQEW +EXVuaXR0ZXN0QGx5ZnQuY29tMB4XDTI0MDgyMTE5MTQxMVoXDTI2MDgyMTE5MTQx +MVowgZ0xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH +DA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARMeWZ0MRkwFwYDVQQLDBBMeWZ0IEVu +Z2luZWVyaW5nMRUwEwYDVQQDDAxVbml0IFRlc3QgQ0ExIDAeBgkqhkiG9w0BCQEW +EXVuaXR0ZXN0QGx5ZnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA0RtYcQtwc/CkGwGAYD9w9L1KhwWW4Vn6H3d7HePYgmh4jfvywNuF8BqbtbtL +nlg7HvxNhJcb7VY19G1sufTl96WV7CywuTNFTmrwDZXne/3FDBR+jyYrC3X2Dn0N +s06xogfblHx6CCH4s7lDB+zbcC99q9EojzbYXRr1zd5lsF1tW5GRbPUeYbKt2rHI +Rb6kzAofw+9zztxgCZJlllu0l/75cuCm5UdMmGDR9BVDfTNmY3TzMO85br0FvReN +mOGoZf5ItsD5GooMqFHCxtcYVCFYeNlUpONOrMZtepmCyXu0h/kuUrmRCwOsHj64 +DtQjEISolEqy0lWFI+0Z++KybQIDAQABoyEwHzAdBgNVHQ4EFgQUva8RD+5dDrHr +keJhummbGnaLyc8wDQYJKoZIhvcNAQELBQADggEBAHd7X9gmoxAbeDIjE0/7SNLh +/IxPZydu9rJA1JEvv5udAEZDBHlueaThxFgzwRycKVPtx1ickHmukkCgf7eo1bD8 +1YIF4bd037CQDS55/dsmRW7nl4bhSRR6Bc8ASVMtkT2q0X6U0289wRYfjtqMqSPt +FO510T29kYWuqFOuVsS92td1pwjEcVDPObs36hOyQNrf5NROmZfCSqlBtp6UZut4 +90ApJBbW9UHb7+lMg+kf98JNJdmbxtVJy7HN+81T+a4GXDYbAsvvzRIVRdDmxjyL +q4++JLaJxfyoSl2IYJWyaYyywLde1oCLbnAGGNzBmW7DZufg+JHEhT6sVp+cDyY= -----END CERTIFICATE----- diff --git a/test/common/tls/test_data/unittest_cert_info.h b/test/common/tls/test_data/unittest_cert_info.h index 30bed0ecf136..d3519db7748e 100644 --- a/test/common/tls/test_data/unittest_cert_info.h +++ b/test/common/tls/test_data/unittest_cert_info.h @@ -1,10 +1,11 @@ #pragma once // NOLINT(namespace-envoy) +// This file is auto-generated by certs.sh. constexpr char TEST_UNITTEST_CERT_256_HASH[] = - "cc62a7c2e052b5e771631cdd02593fe935ee6111d34a409f98151a2e893a3fc3"; -constexpr char TEST_UNITTEST_CERT_1_HASH[] = "f14af93cbb609b7441bd959a3eb62ecf79fc8710"; -constexpr char TEST_UNITTEST_CERT_SPKI[] = "1vq9PX9Hm8ubJlG5XbU+qixpgF7AUqptvt9YW4quukw="; -constexpr char TEST_UNITTEST_CERT_SERIAL[] = "62a7294a20f0ed4cd15793fd671fb9f7430960fb"; -constexpr char TEST_UNITTEST_CERT_NOT_BEFORE[] = "Aug 22 07:51:34 2022 GMT"; -constexpr char TEST_UNITTEST_CERT_NOT_AFTER[] = "Aug 21 07:51:34 2024 GMT"; + "5c42c7ea4c95d41a6653f420264e807be75005695d47edb7d95f6f66347c6302"; +constexpr char TEST_UNITTEST_CERT_1_HASH[] = "676874cdf471252dfb0eeda53aa2da96b6c4d824"; +constexpr char TEST_UNITTEST_CERT_SPKI[] = "s0Oc2cnOs1zCtiezu9hmu81DFTimnyTxp7L9vfTFA7Y="; +constexpr char TEST_UNITTEST_CERT_SERIAL[] = "0f4cdb9bc26211279f26f9a5620527f409eda100"; +constexpr char TEST_UNITTEST_CERT_NOT_BEFORE[] = "Aug 21 19:14:11 2024 GMT"; +constexpr char TEST_UNITTEST_CERT_NOT_AFTER[] = "Aug 21 19:14:11 2026 GMT"; diff --git a/test/common/tls/test_data/unittest_key.pem b/test/common/tls/test_data/unittest_key.pem index 8b97fba3b24f..cc66bfa9a9cb 100644 --- a/test/common/tls/test_data/unittest_key.pem +++ b/test/common/tls/test_data/unittest_key.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAsrondIx+mXUeUpRAFaWXau1sDkEPRnMT+0ZpFw/R4GXiY2Ca -dh2PoRK6PClevPLipm41dt5O5jlNyNVxu5vaff0P85k7QimnakZoF7aD/x/+RylH -KcEKK1E5h5RbVDsTzTLCnil9P8ZVVVvZOukUNIdgEJ975+kqQP6fUzv7fbrN1Dd4 -vipX8E08Nno7uIJSpSUY+fX49WBn8Z4HMfMnDuVLJoOWj6srpRPdY6NX91/i/z9S -Kc716HNeuzuEjwyc1onoojeToNQvTncqNn+7wWhaYELZq+OpjouVKKbf76x5U+uX -4wkLgp+Bb5brj1Wq5WzBuY8DL+avYlj8/12bSwIDAQABAoIBAH0QzrM77QstbX6T -xxRev8pPQaHn3OyLcpwO9VLx+wdvxC+OVgf5P5yTIkcfG/BUdk3IKRl5DvUDfG7h -DakespIfF556x4DQ7RntEsIlMdDBbooVVHrfXmJZgExjgFU80epxbsaGeeK6wtPs -ZeJXX5AyewKm12m9O5gnlQ4Fl0Ku3MgiJbExdMYY4qwzL9t/W9fiJ8jWUVkoQwYS -ToXfuB9LuomURPOFKbBFnC0EG7fJD/CXc9a+ok+uSh7sI5UyuaINWN5v5JGNmIrs -xMRqLxwVwPPyfiDyds/NoaPaptD4nlPQKCt9tXRE0x95oE6fxP53ElsZgiXTfnKp -G5fy8SECgYEA60l+nl4N7YB1OgifznCOco7WwLB+OTItRbbnY9ySKVR5D20L6PSe -FLJHfO7DEoKm8niGZW9oofiCDue9tPL2d7D1j52Y1xlPX92KyhDoAmRa/8X9cgPU -OtD/bgL6RS8UqwaIRTdF4jVHMdokjIpmG98x9D6lHQE6rB+9uk6h2HcCgYEAwnYB -xM85V8t41rid03zJegED+CrA/2zHN6ygr3q49J+hB96hGzgT9c3v92g2ypp0KxXl -7+5jxsipsXac/Yhbdda9+YTT85tEiUfxT9zOeh2WvMXh5WSrJ7jbHzZOvdVAFG9K -plETEiiOgZ76G/ybUGyVrSh/rIhybNdXXkhr3M0CgYA+JiCi9lcZeAf+9042+nY1 -/lLtfPEqbH2W35RJRXb6Ic0EbRprQ0oKT3kgn/S5C/fLLljZrE7oEbtQ8peil1bR -ENYcRFWd45qayOsjKsoN77I1w3eJyUci7he6WGEBK0l7T3NpTQtRkB8pJOTolpoY -HKGWUYHNooh79Lpp3uFTSwKBgEMoD9pRGmOYkGXPIipMeSQaP62vzjEn9vDiPCf+ -AOvySOF34DmPN013Tn0pz2pOxvmuOVeQA4M9/2SbKwJf2f4rKDaIyc3ifFvQraTA -A8qmd01AJZBcIMO6EmqIDc9/Wv7zpFsluqlVuklHhuataVHv/gzr5JPIF4RBJhoY -dq+tAoGAWwPgnOytHAvmE287LyOEre7y4OKz8OB9AdAjU5AdEqSNkxepcmzEVn9n -ZbONs7ph7fGm7IhDH+FE6uNYDqRo33u7tEwBdNmpB05o3squNyro1UKwzrQ1Osa4 -hGk2FS1QOAnM+odviQm4CwIbF2naBEtBGTQz06NAws7sr3OtgdI= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDRG1hxC3Bz8KQb +AYBgP3D0vUqHBZbhWfofd3sd49iCaHiN+/LA24XwGpu1u0ueWDse/E2ElxvtVjX0 +bWy59OX3pZXsLLC5M0VOavANled7/cUMFH6PJisLdfYOfQ2zTrGiB9uUfHoIIfiz +uUMH7NtwL32r0SiPNthdGvXN3mWwXW1bkZFs9R5hsq3aschFvqTMCh/D73PO3GAJ +kmWWW7SX/vly4KblR0yYYNH0FUN9M2ZjdPMw7zluvQW9F42Y4ahl/ki2wPkaigyo +UcLG1xhUIVh42VSk406sxm16mYLJe7SH+S5SuZELA6wePrgO1CMQhKiUSrLSVYUj +7Rn74rJtAgMBAAECggEAM6/uNxcsR0RS1CgVWvUjjyNhEioEBxUOGgwXHybMREPd +lL8T3K8GlviEx7GRugS2LG0SHjWZ3hsiwBXyO674zzObcOMFFepB9eXCC6GjtAbg +16ETPYAiQLV6Sk+H/Ov1RYdqs/Pm2C7JgmdHVeSqwzrB9h//xhK4/Z6l5qrT+PlU +Ll8AhufrzTibA1HWW4zgP9Vd7iv4J18QK90i1nVMWzpk/rRJ81ogLU5jVqO04+d4 +RN1voNsCQlJYbqKwpR+o+IOy6ThJ309JtjnefQcH6qLb1KRxHZ4hQV0smgPdlOvw +Ntm1YSfSL5BNIg4YXM81xlcpekXqo5t48Y8fVetVEwKBgQD9Th/G02t5eWfJHWJ/ +4/YoKAkP02pZ9IrUT4oG6hlX5wIDgi0zzUnHSlX++SIt7/EBWwcKlUD310hNzLxG +W6deXUDftWw5+iSXp84yyfSyAjjQhMucIIRAiej8PhL3akB8c/RgrQtGWM7tGcuE +aruGe8Sab5nGcwHL9Se15UmzzwKBgQDTVNjmP5ycwjuLjoL4rnihOqTdF8ixZ9qy +8WCwebQTPyfMivcHSqdEiZpD6mk6A+8SIhsb8H40nLd3WDg1A250CR/XDuseQDqV +UZ8OY7CxPz2dXcdq0CB2MuHmOQSQRjcFbtz/+1RmL+s0OOeBQDZgDAoynBOC70ZA +I7M2Gdu5AwKBgQDM9fsGYaoUF6Vf+XPrMeTLJ2H1uUbT1OjE1DtGTwQEuXpKpnm2 +8cRiCoc9Eg+TBhSH2UUATjbMlBkAQsqRT7ZEx8YnfeA9pWcYg4J4XCuwIdYg+2LZ +SQJaSn0IJZ4pLoNRcG3sD/kQiemdtoKT+d0U+27g266dAhARHaRtLUOOxwKBgD2l +7LgOKnOYPaKSaiZ9TvdJkjpk68jE0QmOXHRerGdI7yU+DJ316yGVOolBYnzoFN+n +T10xJL/YT7Ti6VKds6Tp3H3x/iiO+AgDDXE3J54tIp47cyb3m+CfK0LrsycbNIXD +N3j9Kju9EtHjH7WWs8YE/RySZya1AjtHrsnDdVNdAoGAc2qcwXlVIq04LbPHBS2w +M2XXBdz8Kz1KAQn4mC1ln63JJUM4A18MMUof3Vei3I0riesYxWDG1hV3ABPtZ0L9 +VC8YTs667GqvcnRyG0s1CbEdHadh7b/69/jAJasHHjwbrjcueETCPMV+Uukh5dbd +WVi8K+CcTTrodCQA7vBAn3k= +-----END PRIVATE KEY----- diff --git a/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc index 75d27f987488..10bca9b670d4 100644 --- a/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc +++ b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc @@ -631,9 +631,9 @@ name: envoy.tls.cert_validator.spiffe filename: "{{ test_rundir }}/test/common/tls/test_data/intermediate_ca_cert.pem" )EOF"), time_system); - EXPECT_EQ(19956, validator().daysUntilFirstCertExpires().value()); + EXPECT_EQ(20686, validator().daysUntilFirstCertExpires().value()); time_system.setSystemTime(std::chrono::milliseconds(864000000)); - EXPECT_EQ(19946, validator().daysUntilFirstCertExpires().value()); + EXPECT_EQ(20676, validator().daysUntilFirstCertExpires().value()); } TEST_F(TestSPIFFEValidator, TestDaysUntilFirstCertExpiresExpired) { From ec09f36ff8e9d70fa5b807f17469a4a2b078962a Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Wed, 21 Aug 2024 18:39:01 -0500 Subject: [PATCH 02/53] mobile: Remove #ifdef ENVOY_ENABLE_QUIC (#35774) This PR enables Envoy Mobile to always have HTTP/3 support. Risk Level: low Testing: CI Docs Changes: n/a Release Notes: n/a Platform Specific Features: mobile Signed-off-by: Fredy Wijaya --- mobile/envoy_build_config/BUILD | 9 ++------ .../envoy_build_config/extension_registry.cc | 8 ++----- mobile/library/cc/engine_builder.cc | 14 +------------ mobile/library/cc/engine_builder.h | 2 -- mobile/library/jni/jni_impl.cc | 3 --- .../library/objective-c/EnvoyConfiguration.mm | 2 -- mobile/library/swift/EngineBuilder.swift | 7 ------- mobile/test/cc/unit/envoy_config_test.cc | 21 +------------------ 8 files changed, 6 insertions(+), 60 deletions(-) diff --git a/mobile/envoy_build_config/BUILD b/mobile/envoy_build_config/BUILD index 3419a753b273..a9fd1b483207 100644 --- a/mobile/envoy_build_config/BUILD +++ b/mobile/envoy_build_config/BUILD @@ -2,7 +2,6 @@ load( "@envoy//bazel:envoy_build_system.bzl", "envoy_cc_library", "envoy_mobile_package", - "envoy_select_enable_http3", "envoy_select_envoy_mobile_listener", ) @@ -21,6 +20,7 @@ envoy_cc_library( "extension_registry_platform_additions", "@envoy//source/common/http/matching:inputs_lib", "@envoy//source/common/network:socket_lib", + "@envoy//source/common/quic:quic_transport_socket_factory_lib", "@envoy//source/common/router:upstream_codec_filter_lib", "@envoy//source/common/tls/cert_validator:cert_validator_lib", "@envoy//source/common/upstream:default_local_address_selector_factory", @@ -52,12 +52,7 @@ envoy_cc_library( "@envoy_mobile//library/common/extensions/key_value/platform:config", "@envoy_mobile//library/common/extensions/listener_managers/api_listener_manager:api_listener_manager_lib", "@envoy_mobile//library/common/extensions/retry/options/network_configuration:config", - ] + envoy_select_enable_http3( - [ - "@envoy//source/common/quic:quic_transport_socket_factory_lib", - ], - "@envoy", - ) + envoy_select_envoy_mobile_listener( + ] + envoy_select_envoy_mobile_listener( [ "@envoy//source/extensions/udp_packet_writer/default:config", "@envoy//source/common/listener_manager:listener_manager_lib", diff --git a/mobile/envoy_build_config/extension_registry.cc b/mobile/envoy_build_config/extension_registry.cc index 7d6fc32fa0a8..8069fa349d4d 100644 --- a/mobile/envoy_build_config/extension_registry.cc +++ b/mobile/envoy_build_config/extension_registry.cc @@ -36,7 +36,6 @@ #include "source/common/listener_manager/connection_handler_impl.h" #endif -#ifdef ENVOY_ENABLE_QUIC #ifdef ENVOY_MOBILE_ENABLE_LISTENER #include "source/common/quic/server_codec_impl.h" #include "source/extensions/quic/connection_id_generator/envoy_deterministic_connection_id_generator_config.h" @@ -44,9 +43,8 @@ #include "source/extensions/quic/proof_source/envoy_quic_proof_source_factory_impl.h" #include "source/extensions/udp_packet_writer/default/config.h" #endif -#include "source/common/quic/quic_client_transport_socket_factory.h" -#endif +#include "source/common/quic/quic_client_transport_socket_factory.h" #include "extension_registry_platform_additions.h" #include "library/common/extensions/cert_validator/platform_bridge/config.h" #include "library/common/extensions/filters/http/local_error/config.h" @@ -182,8 +180,6 @@ void ExtensionRegistry::registerFactories() { Server::FilterChain::forceRegisterFilterChainNameActionFactory(); #endif -#ifdef ENVOY_ENABLE_QUIC - #ifdef ENVOY_MOBILE_ENABLE_LISTENER // These are QUIC downstream factories required if Envoy Mobile is compiled with // proxy functionality and QUIC support. @@ -195,8 +191,8 @@ void ExtensionRegistry::registerFactories() { Quic::forceRegisterEnvoyQuicProofSourceFactoryImpl(); Quic::forceRegisterEnvoyDeterministicConnectionIdGeneratorConfigFactory(); #endif + Quic::forceRegisterQuicClientTransportSocketConfigFactory(); -#endif } } // namespace Envoy diff --git a/mobile/library/cc/engine_builder.cc b/mobile/library/cc/engine_builder.cc index ac4cb04e13f5..15ec80552f6e 100644 --- a/mobile/library/cc/engine_builder.cc +++ b/mobile/library/cc/engine_builder.cc @@ -44,11 +44,7 @@ namespace Envoy { namespace Platform { -EngineBuilder::EngineBuilder() : callbacks_(std::make_unique()) { -#ifndef ENVOY_ENABLE_QUIC - enable_http3_ = false; -#endif -} +EngineBuilder::EngineBuilder() : callbacks_(std::make_unique()) {} EngineBuilder& EngineBuilder::setNetworkThreadPriority(int thread_priority) { network_thread_priority_ = thread_priority; @@ -61,7 +57,6 @@ EngineBuilder& EngineBuilder::setUseCares(bool use_cares) { return *this; } #endif - EngineBuilder& EngineBuilder::setLogLevel(Logger::Logger::Levels log_level) { log_level_ = log_level; return *this; @@ -192,7 +187,6 @@ EngineBuilder& EngineBuilder::enableSocketTagging(bool socket_tagging_on) { return *this; } -#ifdef ENVOY_ENABLE_QUIC EngineBuilder& EngineBuilder::enableHttp3(bool http3_on) { enable_http3_ = http3_on; return *this; @@ -223,8 +217,6 @@ EngineBuilder& EngineBuilder::enablePortMigration(bool enable_port_migration) { return *this; } -#endif - EngineBuilder& EngineBuilder::setForceAlwaysUsev6(bool value) { always_use_v6_ = value; return *this; @@ -382,14 +374,10 @@ std::unique_ptr EngineBuilder::generate // Set up the optional filters if (enable_http3_) { -#ifdef ENVOY_ENABLE_QUIC envoy::extensions::filters::http::alternate_protocols_cache::v3::FilterConfig cache_config; auto* cache_filter = hcm->add_http_filters(); cache_filter->set_name("alternate_protocols_cache"); cache_filter->mutable_typed_config()->PackFrom(cache_config); -#else - throw std::runtime_error("http3 functionality was not compiled in this build of Envoy Mobile"); -#endif } if (gzip_decompression_filter_) { diff --git a/mobile/library/cc/engine_builder.h b/mobile/library/cc/engine_builder.h index 174a57a8b2df..748c9cb1fc66 100644 --- a/mobile/library/cc/engine_builder.h +++ b/mobile/library/cc/engine_builder.h @@ -56,14 +56,12 @@ class EngineBuilder { EngineBuilder& enableGzipDecompression(bool gzip_decompression_on); EngineBuilder& enableBrotliDecompression(bool brotli_decompression_on); EngineBuilder& enableSocketTagging(bool socket_tagging_on); -#ifdef ENVOY_ENABLE_QUIC EngineBuilder& enableHttp3(bool http3_on); EngineBuilder& setHttp3ConnectionOptions(std::string options); EngineBuilder& setHttp3ClientConnectionOptions(std::string options); EngineBuilder& addQuicHint(std::string host, int port); EngineBuilder& addQuicCanonicalSuffix(std::string suffix); EngineBuilder& enablePortMigration(bool enable_port_migration); -#endif EngineBuilder& enableInterfaceBinding(bool interface_binding_on); EngineBuilder& enableDrainPostDnsRefresh(bool drain_post_dns_refresh_on); // Sets whether to use GRO for upstream UDP sockets (QUIC/HTTP3). diff --git a/mobile/library/jni/jni_impl.cc b/mobile/library/jni/jni_impl.cc index 0e0c21d17e93..6465a2ec0d65 100644 --- a/mobile/library/jni/jni_impl.cc +++ b/mobile/library/jni/jni_impl.cc @@ -1229,7 +1229,6 @@ void configureBuilder(Envoy::JNI::JniHelper& jni_helper, jlong connect_timeout_s builder.enableGzipDecompression(enable_gzip_decompression == JNI_TRUE); builder.enableBrotliDecompression(enable_brotli_decompression == JNI_TRUE); builder.enableSocketTagging(enable_socket_tagging == JNI_TRUE); -#ifdef ENVOY_ENABLE_QUIC builder.enableHttp3(enable_http3 == JNI_TRUE); builder.setHttp3ConnectionOptions( Envoy::JNI::javaStringToCppString(jni_helper, http3_connection_options)); @@ -1245,8 +1244,6 @@ void configureBuilder(Envoy::JNI::JniHelper& jni_helper, jlong connect_timeout_s builder.addQuicCanonicalSuffix(suffix); } builder.enablePortMigration(enable_port_migration); - -#endif builder.setUseCares(use_cares == JNI_TRUE); builder.setUseGroIfAvailable(use_gro == JNI_TRUE); builder.enableInterfaceBinding(enable_interface_binding == JNI_TRUE); diff --git a/mobile/library/objective-c/EnvoyConfiguration.mm b/mobile/library/objective-c/EnvoyConfiguration.mm index bf3591564782..eb804f48c095 100644 --- a/mobile/library/objective-c/EnvoyConfiguration.mm +++ b/mobile/library/objective-c/EnvoyConfiguration.mm @@ -166,7 +166,6 @@ - (instancetype)initWithConnectTimeoutSeconds:(UInt32)connectTimeoutSeconds builder.addPlatformFilter([filterFactory.filterName toCXXString]); } -#ifdef ENVOY_ENABLE_QUIC builder.enableHttp3(self.enableHttp3); for (NSString *host in self.quicHints) { builder.addQuicHint([host toCXXString], [[self.quicHints objectForKey:host] intValue]); @@ -174,7 +173,6 @@ - (instancetype)initWithConnectTimeoutSeconds:(UInt32)connectTimeoutSeconds for (NSString *suffix in self.quicCanonicalSuffixes) { builder.addQuicCanonicalSuffix([suffix toCXXString]); } -#endif builder.enableGzipDecompression(self.enableGzipDecompression); builder.enableBrotliDecompression(self.enableBrotliDecompression); diff --git a/mobile/library/swift/EngineBuilder.swift b/mobile/library/swift/EngineBuilder.swift index f8ee3891ed82..e2e0ca1b6e6c 100644 --- a/mobile/library/swift/EngineBuilder.swift +++ b/mobile/library/swift/EngineBuilder.swift @@ -4,7 +4,6 @@ import Foundation /// Builder used for creating and running a new Engine instance. @objcMembers open class EngineBuilder: NSObject { - // swiftlint:disable:previous type_body_length private var engineType: EnvoyEngine.Type = EnvoyEngineImpl.self private var logLevel: LogLevel = .info private var connectTimeoutSeconds: UInt32 = 30 @@ -18,11 +17,7 @@ open class EngineBuilder: NSObject { private var dnsCacheSaveIntervalSeconds: UInt32 = 1 private var enableGzipDecompression: Bool = true private var enableBrotliDecompression: Bool = false -#if ENVOY_ENABLE_QUIC private var enableHttp3: Bool = true -#else - private var enableHttp3: Bool = false -#endif private var quicHints: [String: Int] = [:] private var quicCanonicalSuffixes: [String] = [] private var enableInterfaceBinding: Bool = false @@ -174,7 +169,6 @@ open class EngineBuilder: NSObject { return self } -#if ENVOY_ENABLE_QUIC /// Specify whether to enable support for HTTP/3 or not. Defaults to true. /// /// - parameter enableHttp3: whether or not to enable HTTP/3. @@ -208,7 +202,6 @@ open class EngineBuilder: NSObject { self.quicCanonicalSuffixes.append(suffix) return self } -#endif /// Specify whether sockets may attempt to bind to a specific interface, based on network /// conditions. diff --git a/mobile/test/cc/unit/envoy_config_test.cc b/mobile/test/cc/unit/envoy_config_test.cc index 376ba54d7591..97958a679883 100644 --- a/mobile/test/cc/unit/envoy_config_test.cc +++ b/mobile/test/cc/unit/envoy_config_test.cc @@ -64,16 +64,13 @@ bool socketAddressesEqual( TEST(TestConfig, ConfigIsApplied) { EngineBuilder engine_builder; - engine_builder -#ifdef ENVOY_ENABLE_QUIC - .setHttp3ConnectionOptions("5RTO") + engine_builder.setHttp3ConnectionOptions("5RTO") .setHttp3ClientConnectionOptions("MPQC") .addQuicHint("www.abc.com", 443) .addQuicHint("www.def.com", 443) .addQuicCanonicalSuffix(".opq.com") .addQuicCanonicalSuffix(".xyz.com") .enablePortMigration(true) -#endif .addConnectTimeoutSeconds(123) .addDnsRefreshSeconds(456) .addDnsMinRefreshSeconds(567) @@ -101,7 +98,6 @@ TEST(TestConfig, ConfigIsApplied) { "dns_failure_refresh_rate { base_interval { seconds: 789 } max_interval { seconds: 987 } }", "connection_idle_interval { nanos: 222000000 }", "connection_keepalive { timeout { seconds: 333 }", -#ifdef ENVOY_ENABLE_QUIC "connection_options: \"5RTO\"", "client_connection_options: \"MPQC\"", "hostname: \"www.abc.com\"", @@ -110,7 +106,6 @@ TEST(TestConfig, ConfigIsApplied) { "canonical_suffixes: \".xyz.com\"", "num_timeouts_to_trigger_port_migration { value: 4 }", "idle_network_timeout { seconds: 30 }", -#endif "key: \"dns_persistent_cache\" save_interval { seconds: 101 }", "key: \"always_use_v6\" value { bool_value: true }", "key: \"prefer_quic_client_udp_gro\" value { bool_value: true }", @@ -191,13 +186,11 @@ TEST(TestConfig, SetSocketTag) { EXPECT_THAT(bootstrap->DebugString(), HasSubstr("http.socket_tag.SocketTag")); } -#ifdef ENVOY_ENABLE_QUIC TEST(TestConfig, SetAltSvcCache) { EngineBuilder engine_builder; std::unique_ptr bootstrap = engine_builder.generateBootstrap(); EXPECT_THAT(bootstrap->DebugString(), HasSubstr("alternate_protocols_cache")); } -#endif TEST(TestConfig, StreamIdleTimeout) { EngineBuilder engine_builder; @@ -311,26 +304,15 @@ TEST(TestConfig, DisableHttp3) { EngineBuilder engine_builder; std::unique_ptr bootstrap = engine_builder.generateBootstrap(); -#ifdef ENVOY_ENABLE_QUIC EXPECT_THAT(bootstrap->ShortDebugString(), HasSubstr("envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig")); -#endif -#ifndef ENVOY_ENABLE_QUIC - EXPECT_THAT( - bootstrap->ShortDebugString(), - Not(HasSubstr("envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig"))); -#endif - -#ifdef ENVOY_ENABLE_QUIC engine_builder.enableHttp3(false); bootstrap = engine_builder.generateBootstrap(); EXPECT_THAT( bootstrap->ShortDebugString(), Not(HasSubstr("envoy.extensions.filters.http.alternate_protocols_cache.v3.FilterConfig"))); -#endif } -#ifdef ENVOY_ENABLE_QUIC TEST(TestConfig, UdpSocketReceiveBufferSize) { EngineBuilder engine_builder; engine_builder.enableHttp3(true); @@ -392,7 +374,6 @@ TEST(TestConfig, UdpSocketSendBufferSize) { EXPECT_TRUE(snd_buf_option->type().has_datagram()); EXPECT_EQ(snd_buf_option->int_value(), 1452 * 20); } -#endif TEST(TestConfig, EnablePlatformCertificatesValidation) { EngineBuilder engine_builder; From 38960487e6a5e833e204867a484f59ad250501a4 Mon Sep 17 00:00:00 2001 From: bsurber <73970703+bsurber@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:04:06 -0700 Subject: [PATCH 03/53] RLQS: Refactor traffic processing in the RLQS filter & fix a broken expiration check (#35723) Commit Message: Refactor the RLQS filter's traffic processing & fix the broken action-assignment expiration check. Additional Description: Current behavior: - Every request that hits the RLQS filter results in the cache thinking that its entry has expired due to the initial / default action of a newly created BucketCache index not having a TTL. - If the TTL was fixed, it would still start failing all expiration checks shortly after assignments were received, even if those assignments were sent routinely (not going stale). This is because the expiration time was calculated off of a private field set on BucketCache index creation, and never updated when receiving assignments. - Note: Integration testing was previously passing as it was incorrectly expecting multiple RLQS usage reports. Risk Level: minor - filter is in-development and currently in a broken state Testing: Docs Changes: Release Notes: Platform Specific Features: --------- Signed-off-by: Brian Surber --- .../http/rate_limit_quota/client_impl.cc | 9 +- .../filters/http/rate_limit_quota/filter.cc | 262 +++++++++------ .../filters/http/rate_limit_quota/filter.h | 8 + .../rate_limit_quota/quota_bucket_cache.h | 10 +- .../http/rate_limit_quota/integration_test.cc | 298 +++++++++++++++++- 5 files changed, 485 insertions(+), 102 deletions(-) diff --git a/source/extensions/filters/http/rate_limit_quota/client_impl.cc b/source/extensions/filters/http/rate_limit_quota/client_impl.cc index f454695b55bc..44851acc2349 100644 --- a/source/extensions/filters/http/rate_limit_quota/client_impl.cc +++ b/source/extensions/filters/http/rate_limit_quota/client_impl.cc @@ -85,7 +85,7 @@ void RateLimitClientImpl::onReceiveMessage(RateLimitQuotaResponsePtr&& response) // Get the hash id value from BucketId in the response. const size_t bucket_id = MessageUtil::hash(action.bucket_id()); - ENVOY_LOG(trace, + ENVOY_LOG(debug, "Received a response for bucket id proto :\n {}, and generated " "the associated hashed bucket id: {}", action.bucket_id().DebugString(), bucket_id); @@ -97,10 +97,11 @@ void RateLimitClientImpl::onReceiveMessage(RateLimitQuotaResponsePtr&& response) switch (action.bucket_action_case()) { case envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse_BucketAction:: kQuotaAssignmentAction: { - quota_buckets_[bucket_id]->bucket_action = action; - if (quota_buckets_[bucket_id]->bucket_action.has_quota_assignment_action()) { + quota_buckets_[bucket_id]->cached_action = action; + quota_buckets_[bucket_id]->current_assignment_time = time_source_.monotonicTime(); + if (quota_buckets_[bucket_id]->cached_action->has_quota_assignment_action()) { auto rate_limit_strategy = quota_buckets_[bucket_id] - ->bucket_action.quota_assignment_action() + ->cached_action->quota_assignment_action() .rate_limit_strategy(); if (rate_limit_strategy.has_token_bucket()) { diff --git a/source/extensions/filters/http/rate_limit_quota/filter.cc b/source/extensions/filters/http/rate_limit_quota/filter.cc index 7cbb29fcdb4f..e984ae290857 100644 --- a/source/extensions/filters/http/rate_limit_quota/filter.cc +++ b/source/extensions/filters/http/rate_limit_quota/filter.cc @@ -9,6 +9,8 @@ namespace Extensions { namespace HttpFilters { namespace RateLimitQuota { +using envoy::type::v3::RateLimitStrategy; + const char kBucketMetadataNamespace[] = "envoy.extensions.http_filters.rate_limit_quota.bucket"; Http::FilterHeadersStatus RateLimitQuotaFilter::decodeHeaders(Http::RequestHeaderMap& headers, @@ -123,34 +125,36 @@ void RateLimitQuotaFilter::createNewBucket(const BucketId& bucket_id, // Create new bucket and store it into quota cache. std::unique_ptr new_bucket = std::make_unique(); - // The first matched request doesn't have quota assignment from the RLQS server yet, so the - // action is performed based on pre-configured strategy from no assignment behavior config. + // The first matched request doesn't have quota assignment from the RLQS + // server yet, so the action is performed based on pre-configured strategy + // from no assignment behavior config. auto mutable_rate_limit_strategy = - new_bucket->bucket_action.mutable_quota_assignment_action()->mutable_rate_limit_strategy(); + new_bucket->default_action.mutable_quota_assignment_action()->mutable_rate_limit_strategy(); if (match_action.bucketSettings().has_no_assignment_behavior()) { *mutable_rate_limit_strategy = match_action.bucketSettings().no_assignment_behavior().fallback_rate_limit(); } else { - // When `no_assignment_behavior` is not configured, default blanket rule is set to ALLOW_ALL. - // (i.e., fail-open). - mutable_rate_limit_strategy->set_blanket_rule(envoy::type::v3::RateLimitStrategy::ALLOW_ALL); + // When `no_assignment_behavior` is not configured, default blanket rule is + // set to ALLOW_ALL. (i.e., fail-open). + mutable_rate_limit_strategy->set_blanket_rule(RateLimitStrategy::ALLOW_ALL); } // Set up the bucket id. new_bucket->bucket_id = bucket_id; - // Set up the first time assignment time. - new_bucket->first_assignment_time = time_source_.monotonicTime(); + // Mark the assignment time. + auto now = time_source_.monotonicTime(); + new_bucket->current_assignment_time = now; // Set up the quota usage. QuotaUsage quota_usage; - quota_usage.last_report = std::chrono::duration_cast( - time_source_.monotonicTime().time_since_epoch()); + quota_usage.last_report = + std::chrono::duration_cast(now.time_since_epoch()); switch (mutable_rate_limit_strategy->blanket_rule()) { PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; - case envoy::type::v3::RateLimitStrategy::ALLOW_ALL: + case RateLimitStrategy::ALLOW_ALL: quota_usage.num_requests_allowed++; break; - case envoy::type::v3::RateLimitStrategy::DENY_ALL: + case RateLimitStrategy::DENY_ALL: quota_usage.num_requests_denied++; break; } @@ -202,102 +206,174 @@ RateLimitQuotaFilter::sendImmediateReport(const size_t bucket_id, // bucket_matchers for the first time) should be already set based on no assignment behavior in // `createNewBucket` when the bucket is initially created. ASSERT(quota_buckets_.find(bucket_id) != quota_buckets_.end()); - if (quota_buckets_[bucket_id] - ->bucket_action.quota_assignment_action() - .rate_limit_strategy() - .blanket_rule() == envoy::type::v3::RateLimitStrategy::ALLOW_ALL) { - ENVOY_LOG( - trace, - "For first matched request with hashed bucket_id {}, it is allowed by ALLOW_ALL strategy.", - bucket_id); + // If not given a default blanket rule, the first matched request is allowed. + if (!quota_buckets_[bucket_id]->default_action.has_quota_assignment_action() || + !quota_buckets_[bucket_id] + ->default_action.quota_assignment_action() + .has_rate_limit_strategy() || + !quota_buckets_[bucket_id] + ->default_action.quota_assignment_action() + .rate_limit_strategy() + .has_blanket_rule()) { + ENVOY_LOG(trace, "Without a default blanket rule configured, the first matched " + "request with hashed bucket_id {} is allowed through."); + ENVOY_LOG(debug, "Default action for bucket_id {} does not contain a blanket action: {}", + bucket_id, quota_buckets_[bucket_id]->default_action.DebugString()); return Http::FilterHeadersStatus::Continue; - } else { - // For the request that is rejected due to DENY_ALL no_assignment_behavior, immediate report is - // still sent to RLQS server above, and here the local reply with deny response is sent. - ENVOY_LOG( - trace, - "For first matched request with hashed bucket_id {}, it is throttled by DENY_ALL strategy.", - bucket_id); + } + auto blanket_rule = quota_buckets_[bucket_id] + ->default_action.quota_assignment_action() + .rate_limit_strategy() + .blanket_rule(); + if (blanket_rule == RateLimitStrategy::DENY_ALL) { + // For the request that is rejected due to DENY_ALL + // no_assignment_behavior, immediate report is still sent to RLQS server + // above, and here the local reply with deny response is sent. + ENVOY_LOG(trace, + "For first matched request with hashed bucket_id {}, it is " + "throttled by DENY_ALL strategy.", + bucket_id); + ENVOY_LOG(debug, "Hit configured default DENY_ALL for bucket_id {}", bucket_id); sendDenyResponse(); return Envoy::Http::FilterHeadersStatus::StopIteration; } + + ENVOY_LOG(trace, + "For first matched request with hashed bucket_id {}, it is " + "allowed by the configured default ALLOW_ALL strategy.", + bucket_id); + ENVOY_LOG(debug, "Hit configured default ALLOW_ALL for bucket_id {}", bucket_id); + return Http::FilterHeadersStatus::Continue; } -Http::FilterHeadersStatus -RateLimitQuotaFilter::processCachedBucket(size_t bucket_id, - const RateLimitOnMatchAction& match_action) { +Http::FilterHeadersStatus RateLimitQuotaFilter::getStatusFromAction(const BucketAction& action, + size_t bucket_id) { + if (!action.has_quota_assignment_action() || + !action.quota_assignment_action().has_rate_limit_strategy()) { + ENVOY_LOG(debug, + "Selected bucket action defaulting to ALLOW_ALL as it does not " + "have an assignment for bucket_id {}", + bucket_id); + return Envoy::Http::FilterHeadersStatus::Continue; + } + + // TODO(tyxia) Currently, blanket rule and token bucket strategies are + // implemented. Change to switch case when `RequestsPerTimeUnit` strategy is + // implemented. + auto rate_limit_strategy = action.quota_assignment_action().rate_limit_strategy(); + if (rate_limit_strategy.has_blanket_rule()) { + bool allow = (rate_limit_strategy.blanket_rule() != RateLimitStrategy::DENY_ALL); + ENVOY_LOG(trace, "Request with hashed bucket_id {} is {} by the selected blanket rule.", + bucket_id, allow ? "allowed" : "denied"); + return allow ? Envoy::Http::FilterHeadersStatus::Continue + : Envoy::Http::FilterHeadersStatus::StopIteration; + } + + if (rate_limit_strategy.has_token_bucket()) { + auto token_bucket = quota_buckets_[bucket_id]->token_bucket_limiter.get(); + ASSERT(token_bucket); + + // Try to consume 1 token from the bucket. + if (token_bucket->consume(1, /*allow_partial=*/false)) { + // Request is allowed. + ENVOY_LOG(trace, + "Request with hashed bucket_id {} is allowed by token bucket " + "limiter.", + bucket_id); + ENVOY_LOG(debug, + "Allowing request as token bucket is not empty for bucket_id " + "{}. Initial assignment: {}.", + bucket_id, rate_limit_strategy.token_bucket().ShortDebugString()); + return Envoy::Http::FilterHeadersStatus::Continue; + } + // Request is throttled. + ENVOY_LOG(trace, + "Request with hashed bucket_id {} is throttled by token " + "bucket limiter", + bucket_id); + ENVOY_LOG(debug, + "Denying request as token bucket is exhausted for bucket_id {}. " + "Initial assignment: {}.", + bucket_id, rate_limit_strategy.token_bucket().ShortDebugString()); + return Envoy::Http::FilterHeadersStatus::StopIteration; + } + + ENVOY_LOG(error, + "Failing open as selected bucket action for bucket_id {} contains " + "an unsupported rate limit strategy: {}", + bucket_id, rate_limit_strategy.DebugString()); + return Envoy::Http::FilterHeadersStatus::Continue; +} + +bool isCachedActionExpired(TimeSource& time_source, const Bucket& bucket) { // First, check if assignment has expired nor not. auto now = std::chrono::duration_cast( - time_source_.monotonicTime().time_since_epoch()); + time_source.monotonicTime().time_since_epoch()); auto assignment_time_elapsed = Protobuf::util::TimeUtil::NanosecondsToDuration( (now - std::chrono::duration_cast( - quota_buckets_[bucket_id]->first_assignment_time.time_since_epoch())) + bucket.current_assignment_time.time_since_epoch())) .count()); - if (assignment_time_elapsed > quota_buckets_[bucket_id] - ->bucket_action.quota_assignment_action() - .assignment_time_to_live()) { - // If expired, remove the cache entry. - quota_buckets_.erase(bucket_id); - - // Default strategy is fail-Open (i.e., allow_all). - auto ret_status = Envoy::Http::FilterHeadersStatus::Continue; - // Check the expired assignment behavior if configured. - // Note, only fail-open and fail-close are supported, more advanced expired assignment can be - // supported as needed. - if (match_action.bucketSettings().has_expired_assignment_behavior()) { - if (match_action.bucketSettings() - .expired_assignment_behavior() - .fallback_rate_limit() - .blanket_rule() == envoy::type::v3::RateLimitStrategy::DENY_ALL) { - sendDenyResponse(); - ret_status = Envoy::Http::FilterHeadersStatus::StopIteration; - } - } - return ret_status; + return (assignment_time_elapsed > + bucket.cached_action->quota_assignment_action().assignment_time_to_live()); +} + +Http::FilterHeadersStatus +RateLimitQuotaFilter::processCachedBucket(size_t bucket_id, + const RateLimitOnMatchAction& match_action) { + auto* cached_bucket = quota_buckets_[bucket_id].get(); + Http::FilterHeadersStatus ret_status; + + if (!cached_bucket->cached_action.has_value()) { + // If no cached action, use the default action. + ret_status = getStatusFromAction(cached_bucket->default_action, bucket_id); + } else if (isCachedActionExpired(time_source_, *cached_bucket)) { + // If expired, remove the expired action & fallback. + ret_status = processExpiredBucket(bucket_id, match_action); + cached_bucket->cached_action = absl::nullopt; + } else { + // If not expired, use the cached action. + ret_status = getStatusFromAction(*cached_bucket->cached_action, bucket_id); } - // Second, get the quota assignment (if exists) from the cached bucket action. - if (quota_buckets_[bucket_id]->bucket_action.has_quota_assignment_action()) { - auto rate_limit_strategy = - quota_buckets_[bucket_id]->bucket_action.quota_assignment_action().rate_limit_strategy(); - - // TODO(tyxia) Currently, blanket rule and token bucket strategies are implemented. - // Change to switch case when `RequestsPerTimeUnit` strategy is implemented. - if (rate_limit_strategy.has_blanket_rule()) { - if (rate_limit_strategy.blanket_rule() == envoy::type::v3::RateLimitStrategy::ALLOW_ALL) { - quota_buckets_[bucket_id]->quota_usage.num_requests_allowed += 1; - ENVOY_LOG(trace, - "Request with hashed bucket_id {} is allowed by cached ALLOW_ALL strategy.", - bucket_id); - } else if (rate_limit_strategy.blanket_rule() == - envoy::type::v3::RateLimitStrategy::DENY_ALL) { - quota_buckets_[bucket_id]->quota_usage.num_requests_denied += 1; - ENVOY_LOG(trace, - "Request with hashed bucket_id {} is throttled by cached DENY_ALL strategy.", - bucket_id); - sendDenyResponse(); - return Envoy::Http::FilterHeadersStatus::StopIteration; - } - } else if (rate_limit_strategy.has_token_bucket()) { - ASSERT(quota_buckets_[bucket_id]->token_bucket_limiter != nullptr); - TokenBucket* limiter = quota_buckets_[bucket_id]->token_bucket_limiter.get(); - // Try to consume 1 token from the bucket. - if (limiter->consume(1, /*allow_partial=*/false)) { - // Request is allowed. - quota_buckets_[bucket_id]->quota_usage.num_requests_allowed += 1; - ENVOY_LOG(trace, "Request with hashed bucket_id {} is allowed by token bucket limiter.", - bucket_id); - } else { - // Request is throttled. - quota_buckets_[bucket_id]->quota_usage.num_requests_denied += 1; - ENVOY_LOG(trace, "Request with hashed bucket_id {} is throttled by token bucket limiter", - bucket_id); - sendDenyResponse(); - return Envoy::Http::FilterHeadersStatus::StopIteration; - } - } + if (ret_status == Envoy::Http::FilterHeadersStatus::StopIteration) { + sendDenyResponse(); + quota_buckets_[bucket_id]->quota_usage.num_requests_denied += 1; + } else { + quota_buckets_[bucket_id]->quota_usage.num_requests_allowed += 1; + } + + return ret_status; +} + +// Note: does not remove the expired entity from the cache. +Http::FilterHeadersStatus +RateLimitQuotaFilter::processExpiredBucket(size_t bucket_id, + const RateLimitOnMatchAction& match_action) { + auto* cached_bucket = quota_buckets_[bucket_id].get(); + + if (!match_action.bucketSettings().has_expired_assignment_behavior() || + !match_action.bucketSettings().expired_assignment_behavior().has_fallback_rate_limit()) { + ENVOY_LOG(debug, "Selecting default action for bucket_id as expiration " + "fallback assignment doesn't have a configured override {}"); + return getStatusFromAction(cached_bucket->default_action, bucket_id); } + + const RateLimitStrategy& fallback_rate_limit = + match_action.bucketSettings().expired_assignment_behavior().fallback_rate_limit(); + if (fallback_rate_limit.has_blanket_rule() && + fallback_rate_limit.blanket_rule() == RateLimitStrategy::DENY_ALL) { + ENVOY_LOG(debug, + "Exipred action falling back to configured DENY_ALL for " + "bucket_id {}", + bucket_id); + return Envoy::Http::FilterHeadersStatus::StopIteration; + } + + ENVOY_LOG(debug, + "Exipred action falling back to configured ALLOW_ALL for " + "bucket_id {}", + bucket_id); return Envoy::Http::FilterHeadersStatus::Continue; } diff --git a/source/extensions/filters/http/rate_limit_quota/filter.h b/source/extensions/filters/http/rate_limit_quota/filter.h index e1302214affb..570e7245efec 100644 --- a/source/extensions/filters/http/rate_limit_quota/filter.h +++ b/source/extensions/filters/http/rate_limit_quota/filter.h @@ -93,6 +93,8 @@ class RateLimitQuotaFilter : public Http::PassThroughFilter, Http::FilterHeadersStatus sendImmediateReport(const size_t bucket_id, const RateLimitOnMatchAction& match_action); + Http::FilterHeadersStatus getStatusFromAction(const BucketAction& action, size_t bucket_id); + Http::FilterHeadersStatus processCachedBucket(size_t bucket_id, const RateLimitOnMatchAction& match_action); // TODO(tyxia) Build the customized response based on `DenyResponseSettings`. @@ -101,6 +103,12 @@ class RateLimitQuotaFilter : public Http::PassThroughFilter, callbacks_->streamInfo().setResponseFlag(StreamInfo::CoreResponseFlag::RateLimited); } + // Get the FilterHeadersStatus to return when a selected bucket has an expired + // assignment. Note: this does not actually remove the expired entity from the + // cache. + Http::FilterHeadersStatus processExpiredBucket(size_t bucket_id, + const RateLimitOnMatchAction& match_action); + FilterConfigConstSharedPtr config_; Grpc::GrpcServiceConfigWithHashKey config_with_hash_key_; Server::Configuration::FactoryContext& factory_context_; diff --git a/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h b/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h index e2923b9156d2..1896a1e24983 100644 --- a/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h +++ b/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h @@ -41,13 +41,17 @@ struct Bucket { // RLQS server. BucketId bucket_id; // Cached action from the response that was received from the RLQS server. - BucketAction bucket_action; + absl::optional cached_action = absl::nullopt; + // Default action defined by the bucket's no_assignment_behavior setting. Used + // when the bucket is waiting for an assigned action from the RLQS server + // (e.g. during initial bucket hits & after stale assignments expire). + BucketAction default_action; // Cache quota usage. QuotaUsage quota_usage; // Rate limiter based on token bucket algorithm. TokenBucketPtr token_bucket_limiter; - // First assignment time. - Envoy::MonotonicTime first_assignment_time = {}; + // Most recent assignment time. + Envoy::MonotonicTime current_assignment_time; }; using BucketsCache = absl::flat_hash_map>; diff --git a/test/extensions/filters/http/rate_limit_quota/integration_test.cc b/test/extensions/filters/http/rate_limit_quota/integration_test.cc index ec4e45a89113..bc83c88a539e 100644 --- a/test/extensions/filters/http/rate_limit_quota/integration_test.cc +++ b/test/extensions/filters/http/rate_limit_quota/integration_test.cc @@ -28,6 +28,7 @@ enum class BlanketRule { struct ConfigOption { bool valid_rlqs_server = true; BlanketRule no_assignment_blanket_rule = BlanketRule::NOT_SPECIFIED; + bool unsupported_no_assignment_strategy = false; BlanketRule expired_assignment_blanket_rule = BlanketRule::NOT_SPECIFIED; }; @@ -110,6 +111,12 @@ class RateLimitQuotaIntegrationTest ->mutable_fallback_rate_limit() ->set_blanket_rule(envoy::type::v3::RateLimitStrategy::DENY_ALL); } + } else if (config_option.unsupported_no_assignment_strategy) { + auto* requests_per_time_unit = mutable_bucket_settings.mutable_no_assignment_behavior() + ->mutable_fallback_rate_limit() + ->mutable_requests_per_time_unit(); + requests_per_time_unit->set_requests_per_time_unit(100); + requests_per_time_unit->set_time_unit(envoy::type::v3::RateLimitUnit::SECOND); } if (config_option.expired_assignment_blanket_rule != BlanketRule::NOT_SPECIFIED) { @@ -934,6 +941,153 @@ TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithTokenBucket) { } } +TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithUnsupportedStrategy) { + initializeConfig(); + HttpIntegrationTest::initialize(); + absl::flat_hash_map custom_headers = {{"environment", "staging"}, + {"group", "envoy"}}; + + for (int i = 0; i < 2; ++i) { + // Send downstream client request to upstream. + sendClientRequest(&custom_headers); + + // Handle the request received by upstream. All requests will be allowed + // since the strategy is not supported. + ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); + ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); + ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); + upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); + upstream_request_->encodeData(100, true); + + // Verify the response to downstream. + ASSERT_TRUE(response_->waitForEndStream()); + EXPECT_TRUE(response_->complete()); + EXPECT_EQ(response_->headers().getStatusValue(), "200"); + + // Only first downstream client request will trigger the reports to RLQS + // server as the subsequent requests will find the entry in the cache. + if (i == 0) { + // Start the gRPC stream to RLQS server. + ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); + ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); + + envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; + ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + rlqs_stream_->startGrpcStream(); + + // Build the response. + envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; + absl::flat_hash_map custom_headers_cpy = custom_headers; + custom_headers_cpy.insert({"name", "prod"}); + auto* bucket_action = rlqs_response.add_bucket_action(); + for (const auto& [key, value] : custom_headers_cpy) { + (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); + auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); + quota_assignment->mutable_assignment_time_to_live()->set_seconds(120); + auto* strategy = quota_assignment->mutable_rate_limit_strategy(); + auto* unsupported_strategy = strategy->mutable_requests_per_time_unit(); + unsupported_strategy->set_requests_per_time_unit(10); + unsupported_strategy->set_time_unit(envoy::type::v3::RateLimitUnit::SECOND); + } + + // Send the response from RLQS server. + rlqs_stream_->sendGrpcMessage(rlqs_response); + absl::SleepFor(absl::Seconds(1)); + } + + cleanUp(); + } +} + +TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithUnsetStrategy) { + initializeConfig(); + HttpIntegrationTest::initialize(); + absl::flat_hash_map custom_headers = {{"environment", "staging"}, + {"group", "envoy"}}; + + for (int i = 0; i < 2; ++i) { + // Send downstream client request to upstream. + sendClientRequest(&custom_headers); + + // Handle the request received by upstream. All requests will be allowed + // since the strategy is not set. + ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); + ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); + ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); + upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); + upstream_request_->encodeData(100, true); + + // Verify the response to downstream. + ASSERT_TRUE(response_->waitForEndStream()); + EXPECT_TRUE(response_->complete()); + EXPECT_EQ(response_->headers().getStatusValue(), "200"); + + // Only first downstream client request will trigger the reports to RLQS + // server as the subsequent requests will find the entry in the cache. + if (i == 0) { + // Start the gRPC stream to RLQS server. + ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); + ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); + + envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; + ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + rlqs_stream_->startGrpcStream(); + + // Build the response. + envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; + absl::flat_hash_map custom_headers_cpy = custom_headers; + custom_headers_cpy.insert({"name", "prod"}); + auto* bucket_action = rlqs_response.add_bucket_action(); + for (const auto& [key, value] : custom_headers_cpy) { + (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); + auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); + quota_assignment->mutable_assignment_time_to_live()->set_seconds(120); + } + + // Send the response from RLQS server. + rlqs_stream_->sendGrpcMessage(rlqs_response); + absl::SleepFor(absl::Seconds(1)); + } + + cleanUp(); + } +} + +TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithUnsupportedDefaultAction) { + ConfigOption option; + option.unsupported_no_assignment_strategy = true; + initializeConfig(option); + HttpIntegrationTest::initialize(); + absl::flat_hash_map custom_headers = {{"environment", "staging"}, + {"group", "envoy"}}; + + // Send downstream client request to upstream. + sendClientRequest(&custom_headers); + + // Handle the request received by upstream. All requests will be allowed + // since the strategy is not set. + ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); + ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); + ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); + upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); + upstream_request_->encodeData(100, true); + + // Verify the response to downstream. + ASSERT_TRUE(response_->waitForEndStream()); + EXPECT_TRUE(response_->complete()); + EXPECT_EQ(response_->headers().getStatusValue(), "200"); + + // Start the gRPC stream to RLQS server. + ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); + ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); + + envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; + ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + rlqs_stream_->startGrpcStream(); + + cleanUp(); +} + TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpiredAssignmentDeny) { ConfigOption option; option.expired_assignment_blanket_rule = BlanketRule::DENY_ALL; @@ -1031,9 +1185,10 @@ TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpiredAssignmentAllow ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); rlqs_stream_->startGrpcStream(); } else { - // 3rd request won't start gRPC stream again since it is kept open. + // 3rd request won't start gRPC stream again since it is kept open and the usage will be + // aggregated instead of spawning an immediate report. envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; - ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + ASSERT_FALSE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); } // Build the response. @@ -1073,6 +1228,145 @@ TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpiredAssignmentAllow } } +TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpirationToDefaultDeny) { + ConfigOption option; + option.expired_assignment_blanket_rule = BlanketRule::DENY_ALL; + option.no_assignment_blanket_rule = BlanketRule::ALLOW_ALL; + initializeConfig(option); + HttpIntegrationTest::initialize(); + absl::flat_hash_map custom_headers = {{"environment", "staging"}, + {"group", "envoy"}}; + + for (int i = 0; i < 4; ++i) { + // Advance the time to make cached assignment expired. + if (i > 0) { + simTime().advanceTimeWait(std::chrono::seconds(15)); + } + // Send downstream client request to upstream. + sendClientRequest(&custom_headers); + + // Query 1: ALLOW_ALL by default. Query 2: DENY_ALL by assignment. + // Query 3: DENY_ALL by assignment expiration. Query 4: ALLOW_ALL by default. + if (i == 0 || i == 3) { + // Handle the request received by upstream. + ASSERT_TRUE( + fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); + ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); + ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); + upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); + upstream_request_->encodeData(100, true); + + // Verify the response to downstream. + ASSERT_TRUE(response_->waitForEndStream()); + EXPECT_TRUE(response_->complete()); + EXPECT_EQ(response_->headers().getStatusValue(), "200"); + + if (i == 0) { + // Start the gRPC stream to RLQS server & send the initial report. + ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); + ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); + + envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; + ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + rlqs_stream_->startGrpcStream(); + + // Build the response. + envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; + absl::flat_hash_map custom_headers_cpy = custom_headers; + custom_headers_cpy.insert({"name", "prod"}); + auto* bucket_action = rlqs_response.add_bucket_action(); + + for (const auto& [key, value] : custom_headers_cpy) { + (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); + auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); + quota_assignment->mutable_assignment_time_to_live()->set_seconds(15); + auto* strategy = quota_assignment->mutable_rate_limit_strategy(); + strategy->set_blanket_rule(envoy::type::v3::RateLimitStrategy::DENY_ALL); + } + + // Send the response from RLQS server. + rlqs_stream_->sendGrpcMessage(rlqs_response); + absl::SleepFor(absl::Seconds(1)); + } + } else { + ASSERT_TRUE(response_->waitForEndStream(std::chrono::seconds(5))); + EXPECT_TRUE(response_->complete()); + EXPECT_EQ(response_->headers().getStatusValue(), "429"); + } + + cleanUp(); + } +} + +TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpirationWithoutFallback) { + ConfigOption option; + option.no_assignment_blanket_rule = BlanketRule::ALLOW_ALL; + initializeConfig(option); + HttpIntegrationTest::initialize(); + absl::flat_hash_map custom_headers = {{"environment", "staging"}, + {"group", "envoy"}}; + + for (int i = 0; i < 3; ++i) { + // Advance the time to make cached assignment expired. + if (i > 0) { + simTime().advanceTimeWait(std::chrono::seconds(15)); + } + // Send downstream client request to upstream. + sendClientRequest(&custom_headers); + + // Query 1: ALLOW_ALL by default. Query 2: DENY_ALL by assignment. + // Query 3: DENY_ALL by assignment expiration. Query 4: ALLOW_ALL by default. + if (i == 0 || i == 2) { + // Handle the request received by upstream. + ASSERT_TRUE( + fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); + ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); + ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); + upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); + upstream_request_->encodeData(100, true); + + // Verify the response to downstream. + ASSERT_TRUE(response_->waitForEndStream()); + EXPECT_TRUE(response_->complete()); + EXPECT_EQ(response_->headers().getStatusValue(), "200"); + + if (i == 0) { + // Start the gRPC stream to RLQS server & send the initial report. + ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); + ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); + + envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; + ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + rlqs_stream_->startGrpcStream(); + + // Build the response. + envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; + absl::flat_hash_map custom_headers_cpy = custom_headers; + custom_headers_cpy.insert({"name", "prod"}); + auto* bucket_action = rlqs_response.add_bucket_action(); + + for (const auto& [key, value] : custom_headers_cpy) { + (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); + auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); + quota_assignment->mutable_assignment_time_to_live()->set_seconds(15); + auto* strategy = quota_assignment->mutable_rate_limit_strategy(); + strategy->set_blanket_rule(envoy::type::v3::RateLimitStrategy::DENY_ALL); + } + + // Send the response from RLQS server. + rlqs_stream_->sendGrpcMessage(rlqs_response); + absl::SleepFor(absl::Seconds(1)); + } + } else { + ASSERT_TRUE(response_->waitForEndStream(std::chrono::seconds(5))); + EXPECT_TRUE(response_->complete()); + EXPECT_EQ(response_->headers().getStatusValue(), "429"); + } + + cleanUp(); + } +} + TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithAbandonAction) { initializeConfig(); HttpIntegrationTest::initialize(); From c337d0ac767daf4e23c83aeadcfbe3a41a56473a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 09:34:12 +0100 Subject: [PATCH 04/53] build(deps): bump envoy-base-utils from 0.5.2 to 0.5.5 in /tools/base (#35750) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 9e1bd10ef742..2f6896810d12 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -497,9 +497,9 @@ docutils==0.20.1 \ # envoy-docs-sphinx-runner # sphinx # sphinx-rtd-theme -envoy-base-utils==0.5.2 \ - --hash=sha256:29d1384aded102b1c2cbfab44b07dbb35bc08a181e9e87a990ea0b90540ea54c \ - --hash=sha256:facd099692d3ec02d0597a2a2ff002a1702ccea1da31633d171420a791265e09 +envoy-base-utils==0.5.5 \ + --hash=sha256:2341b7618c92969e3ac5fc43dd16fcc39d132981ffff3f0ddbabf08a336a6fa1 \ + --hash=sha256:a72af1df5680d4fcdeb91f06d19b7495d740f8b9a8a1549c012272e10fdd59ea # via # -r requirements.in # envoy-code-check @@ -1156,7 +1156,9 @@ python-dateutil==2.9.0.post0 \ python-gnupg==0.5.2 \ --hash=sha256:01d8013931c9fa3f45824bbea7054c03d6e11f258a72e7e086e168dbcb91854c \ --hash=sha256:72ce142af6da7f07e433fef148b445fb3e07854acd2f88739008838745c0e9f5 - # via envoy-gpg-identity + # via + # envoy-base-utils + # envoy-gpg-identity pytz==2024.1 \ --hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \ --hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319 From 63269129eb1652ed44f556e71730f5e25a2f472a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 09:34:20 +0100 Subject: [PATCH 05/53] build(deps): bump aiohttp from 3.10.3 to 3.10.5 in /tools/base (#35752) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 169 ++++++++++++++++++++---------------- 1 file changed, 92 insertions(+), 77 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 2f6896810d12..2d2a817b5137 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -92,83 +92,98 @@ aiohappyeyeballs==2.3.5 \ --hash=sha256:4d6dea59215537dbc746e93e779caea8178c866856a721c9c660d7a5a7b8be03 \ --hash=sha256:6fa48b9f1317254f122a07a131a86b71ca6946ca989ce6326fff54a99a920105 # via aiohttp -aiohttp==3.10.3 \ - --hash=sha256:05d66203a530209cbe40f102ebaac0b2214aba2a33c075d0bf825987c36f1f0b \ - --hash=sha256:08bd0754d257b2db27d6bab208c74601df6f21bfe4cb2ec7b258ba691aac64b3 \ - --hash=sha256:0974f3b5b0132edcec92c3306f858ad4356a63d26b18021d859c9927616ebf27 \ - --hash=sha256:09bc79275737d4dc066e0ae2951866bb36d9c6b460cb7564f111cc0427f14844 \ - --hash=sha256:123e5819bfe1b87204575515cf448ab3bf1489cdeb3b61012bde716cda5853e7 \ - --hash=sha256:13031e7ec1188274bad243255c328cc3019e36a5a907978501256000d57a7201 \ - --hash=sha256:166de65e2e4e63357cfa8417cf952a519ac42f1654cb2d43ed76899e2319b1ee \ - --hash=sha256:214277dcb07ab3875f17ee1c777d446dcce75bea85846849cc9d139ab8f5081f \ - --hash=sha256:21650e7032cc2d31fc23d353d7123e771354f2a3d5b05a5647fc30fea214e696 \ - --hash=sha256:24fade6dae446b183e2410a8628b80df9b7a42205c6bfc2eff783cbeedc224a2 \ - --hash=sha256:2a5d0ea8a6467b15d53b00c4e8ea8811e47c3cc1bdbc62b1aceb3076403d551f \ - --hash=sha256:2b0f670502100cdc567188c49415bebba947eb3edaa2028e1a50dd81bd13363f \ - --hash=sha256:2bbc55a964b8eecb341e492ae91c3bd0848324d313e1e71a27e3d96e6ee7e8e8 \ - --hash=sha256:32007fdcaab789689c2ecaaf4b71f8e37bf012a15cd02c0a9db8c4d0e7989fa8 \ - --hash=sha256:3461d9294941937f07bbbaa6227ba799bc71cc3b22c40222568dc1cca5118f68 \ - --hash=sha256:3731a73ddc26969d65f90471c635abd4e1546a25299b687e654ea6d2fc052394 \ - --hash=sha256:38d91b98b4320ffe66efa56cb0f614a05af53b675ce1b8607cdb2ac826a8d58e \ - --hash=sha256:3a9dcdccf50284b1b0dc72bc57e5bbd3cc9bf019060dfa0668f63241ccc16aa7 \ - --hash=sha256:434b3ab75833accd0b931d11874e206e816f6e6626fd69f643d6a8269cd9166a \ - --hash=sha256:43b09f38a67679e32d380fe512189ccb0b25e15afc79b23fbd5b5e48e4fc8fd9 \ - --hash=sha256:44bb159b55926b57812dca1b21c34528e800963ffe130d08b049b2d6b994ada7 \ - --hash=sha256:48665433bb59144aaf502c324694bec25867eb6630fcd831f7a893ca473fcde4 \ - --hash=sha256:50544fe498c81cb98912afabfc4e4d9d85e89f86238348e3712f7ca6a2f01dab \ - --hash=sha256:5337cc742a03f9e3213b097abff8781f79de7190bbfaa987bd2b7ceb5bb0bdec \ - --hash=sha256:56fb94bae2be58f68d000d046172d8b8e6b1b571eb02ceee5535e9633dcd559c \ - --hash=sha256:59c489661edbd863edb30a8bd69ecb044bd381d1818022bc698ba1b6f80e5dd1 \ - --hash=sha256:5ba2e838b5e6a8755ac8297275c9460e729dc1522b6454aee1766c6de6d56e5e \ - --hash=sha256:61ccb867b2f2f53df6598eb2a93329b5eee0b00646ee79ea67d68844747a418e \ - --hash=sha256:671efce3a4a0281060edf9a07a2f7e6230dca3a1cbc61d110eee7753d28405f7 \ - --hash=sha256:673bb6e3249dc8825df1105f6ef74e2eab779b7ff78e96c15cadb78b04a83752 \ - --hash=sha256:6ae9ae382d1c9617a91647575255ad55a48bfdde34cc2185dd558ce476bf16e9 \ - --hash=sha256:6c51ed03e19c885c8e91f574e4bbe7381793f56f93229731597e4a499ffef2a5 \ - --hash=sha256:6d881353264e6156f215b3cb778c9ac3184f5465c2ece5e6fce82e68946868ef \ - --hash=sha256:7084876352ba3833d5d214e02b32d794e3fd9cf21fdba99cff5acabeb90d9806 \ - --hash=sha256:70b4a4984a70a2322b70e088d654528129783ac1ebbf7dd76627b3bd22db2f17 \ - --hash=sha256:71bb1d97bfe7e6726267cea169fdf5df7658831bb68ec02c9c6b9f3511e108bb \ - --hash=sha256:7c126f532caf238031c19d169cfae3c6a59129452c990a6e84d6e7b198a001dc \ - --hash=sha256:7f9159ae530297f61a00116771e57516f89a3de6ba33f314402e41560872b50a \ - --hash=sha256:812121a201f0c02491a5db335a737b4113151926a79ae9ed1a9f41ea225c0e3f \ - --hash=sha256:8542c9e5bcb2bd3115acdf5adc41cda394e7360916197805e7e32b93d821ef93 \ - --hash=sha256:85466b5a695c2a7db13eb2c200af552d13e6a9313d7fa92e4ffe04a2c0ea74c1 \ - --hash=sha256:8d98c604c93403288591d7d6d7d6cc8a63459168f8846aeffd5b3a7f3b3e5e09 \ - --hash=sha256:8da6b48c20ce78f5721068f383e0e113dde034e868f1b2f5ee7cb1e95f91db57 \ - --hash=sha256:926e68438f05703e500b06fe7148ef3013dd6f276de65c68558fa9974eeb59ad \ - --hash=sha256:9743fa34a10a36ddd448bba8a3adc2a66a1c575c3c2940301bacd6cc896c6bf1 \ - --hash=sha256:a541414578ff47c0a9b0b8b77381ea86b0c8531ab37fc587572cb662ccd80b88 \ - --hash=sha256:ab3361159fd3dcd0e48bbe804006d5cfb074b382666e6c064112056eb234f1a9 \ - --hash=sha256:aed12a54d4e1ee647376fa541e1b7621505001f9f939debf51397b9329fd88b9 \ - --hash=sha256:af4dbec58e37f5afff4f91cdf235e8e4b0bd0127a2a4fd1040e2cad3369d2f06 \ - --hash=sha256:b031ce229114825f49cec4434fa844ccb5225e266c3e146cb4bdd025a6da52f1 \ - --hash=sha256:b22cae3c9dd55a6b4c48c63081d31c00fc11fa9db1a20c8a50ee38c1a29539d2 \ - --hash=sha256:b51aef59370baf7444de1572f7830f59ddbabd04e5292fa4218d02f085f8d299 \ - --hash=sha256:b69d832e5f5fa15b1b6b2c8eb6a9fd2c0ec1fd7729cb4322ed27771afc9fc2ac \ - --hash=sha256:b84857b66fa6510a163bb083c1199d1ee091a40163cfcbbd0642495fed096204 \ - --hash=sha256:b97dc9a17a59f350c0caa453a3cb35671a2ffa3a29a6ef3568b523b9113d84e5 \ - --hash=sha256:ba562736d3fbfe9241dad46c1a8994478d4a0e50796d80e29d50cabe8fbfcc3f \ - --hash=sha256:bac352fceed158620ce2d701ad39d4c1c76d114255a7c530e057e2b9f55bdf9f \ - --hash=sha256:baec1eb274f78b2de54471fc4c69ecbea4275965eab4b556ef7a7698dee18bf2 \ - --hash=sha256:bc8e9f15939dacb0e1f2d15f9c41b786051c10472c7a926f5771e99b49a5957f \ - --hash=sha256:bf75716377aad2c718cdf66451c5cf02042085d84522aec1f9246d3e4b8641a6 \ - --hash=sha256:c124b9206b1befe0491f48185fd30a0dd51b0f4e0e7e43ac1236066215aff272 \ - --hash=sha256:c9ed607dbbdd0d4d39b597e5bf6b0d40d844dfb0ac6a123ed79042ef08c1f87e \ - --hash=sha256:cc36cbdedf6f259371dbbbcaae5bb0e95b879bc501668ab6306af867577eb5db \ - --hash=sha256:cd788602e239ace64f257d1c9d39898ca65525583f0fbf0988bcba19418fe93f \ - --hash=sha256:d1100e68e70eb72eadba2b932b185ebf0f28fd2f0dbfe576cfa9d9894ef49752 \ - --hash=sha256:d35235a44ec38109b811c3600d15d8383297a8fab8e3dec6147477ec8636712a \ - --hash=sha256:d3e66d5b506832e56add66af88c288c1d5ba0c38b535a1a59e436b300b57b23e \ - --hash=sha256:d5548444ef60bf4c7b19ace21f032fa42d822e516a6940d36579f7bfa8513f9c \ - --hash=sha256:d5a9ec959b5381271c8ec9310aae1713b2aec29efa32e232e5ef7dcca0df0279 \ - --hash=sha256:d73b073a25a0bb8bf014345374fe2d0f63681ab5da4c22f9d2025ca3e3ea54fc \ - --hash=sha256:e021c4c778644e8cdc09487d65564265e6b149896a17d7c0f52e9a088cc44e1b \ - --hash=sha256:e1128c5d3a466279cb23c4aa32a0f6cb0e7d2961e74e9e421f90e74f75ec1edf \ - --hash=sha256:e8cc0564b286b625e673a2615ede60a1704d0cbbf1b24604e28c31ed37dc62aa \ - --hash=sha256:f25d6c4e82d7489be84f2b1c8212fafc021b3731abdb61a563c90e37cced3a21 \ - --hash=sha256:f817a54059a4cfbc385a7f51696359c642088710e731e8df80d0607193ed2b73 \ - --hash=sha256:fda91ad797e4914cca0afa8b6cccd5d2b3569ccc88731be202f6adce39503189 +aiohttp==3.10.5 \ + --hash=sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277 \ + --hash=sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1 \ + --hash=sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe \ + --hash=sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb \ + --hash=sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca \ + --hash=sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91 \ + --hash=sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972 \ + --hash=sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a \ + --hash=sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3 \ + --hash=sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa \ + --hash=sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77 \ + --hash=sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b \ + --hash=sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8 \ + --hash=sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599 \ + --hash=sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc \ + --hash=sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf \ + --hash=sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511 \ + --hash=sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699 \ + --hash=sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487 \ + --hash=sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987 \ + --hash=sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff \ + --hash=sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db \ + --hash=sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022 \ + --hash=sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce \ + --hash=sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a \ + --hash=sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5 \ + --hash=sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7 \ + --hash=sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820 \ + --hash=sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf \ + --hash=sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e \ + --hash=sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf \ + --hash=sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5 \ + --hash=sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6 \ + --hash=sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6 \ + --hash=sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91 \ + --hash=sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3 \ + --hash=sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a \ + --hash=sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d \ + --hash=sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088 \ + --hash=sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc \ + --hash=sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f \ + --hash=sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75 \ + --hash=sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471 \ + --hash=sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e \ + --hash=sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697 \ + --hash=sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092 \ + --hash=sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69 \ + --hash=sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3 \ + --hash=sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32 \ + --hash=sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589 \ + --hash=sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178 \ + --hash=sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92 \ + --hash=sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2 \ + --hash=sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e \ + --hash=sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058 \ + --hash=sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857 \ + --hash=sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1 \ + --hash=sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6 \ + --hash=sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22 \ + --hash=sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0 \ + --hash=sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b \ + --hash=sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57 \ + --hash=sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f \ + --hash=sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e \ + --hash=sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16 \ + --hash=sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1 \ + --hash=sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f \ + --hash=sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6 \ + --hash=sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04 \ + --hash=sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae \ + --hash=sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d \ + --hash=sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b \ + --hash=sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f \ + --hash=sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862 \ + --hash=sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689 \ + --hash=sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c \ + --hash=sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683 \ + --hash=sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef \ + --hash=sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f \ + --hash=sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12 \ + --hash=sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73 \ + --hash=sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061 \ + --hash=sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072 \ + --hash=sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11 \ + --hash=sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691 \ + --hash=sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77 \ + --hash=sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385 \ + --hash=sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172 \ + --hash=sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569 \ + --hash=sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f \ + --hash=sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5 # via # -r requirements.in # aio-api-github From ced41510028f12c803f0b7f32f83ce3ce293618d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 09:34:29 +0100 Subject: [PATCH 06/53] build(deps): bump github/codeql-action from 3.26.0 to 3.26.4 (#35787) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-daily.yml | 4 ++-- .github/workflows/codeql-push.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index a1d208e6feea..fca0a8a43a65 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -34,7 +34,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # codeql-bundle-v3.26.0 + uses: github/codeql-action/init@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -68,4 +68,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # codeql-bundle-v3.26.0 + uses: github/codeql-action/analyze@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 5a763a564744..94cb412ee164 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -65,7 +65,7 @@ jobs: - name: Initialize CodeQL if: ${{ env.BUILD_TARGETS != '' }} - uses: github/codeql-action/init@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # codeql-bundle-v3.26.0 + uses: github/codeql-action/init@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 with: languages: cpp @@ -109,4 +109,4 @@ jobs: - name: Perform CodeQL Analysis if: ${{ env.BUILD_TARGETS != '' }} - uses: github/codeql-action/analyze@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # codeql-bundle-v3.26.0 + uses: github/codeql-action/analyze@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 0b3ba9d388ad..b92ce6d670e5 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -40,6 +40,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0 + uses: github/codeql-action/upload-sarif@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # v3.26.4 with: sarif_file: results.sarif From df2b5c722112a30ae05b634694902d49dfabc743 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:47:35 +0100 Subject: [PATCH 07/53] deps: Bump `bazel_features` -> 1.15.0 (#35795) Fix #35657 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 0ea9c9a24b3c..a1832adde567 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -33,11 +33,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Bazel features", project_desc = "Support Bazel feature detection from starlark", project_url = "https://github.com/bazel-contrib/bazel_features", - version = "1.14.0", - sha256 = "5ac743bf5f05d88e84962e978811f2524df09602b789c92cf7ae2111ecdeda94", + version = "1.15.0", + sha256 = "ba1282c1aa1d1fffdcf994ab32131d7c7551a9bc960fbf05f42d55a1b930cbfb", urls = ["https://github.com/bazel-contrib/bazel_features/releases/download/v{version}/bazel_features-v{version}.tar.gz"], strip_prefix = "bazel_features-{version}", - release_date = "2024-07-16", + release_date = "2024-08-09", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/bazel-contrib/bazel_features/blob/v{version}/LICENSE", From 6da9193f32ac88cccab9f31196f5c7381912bb78 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:48:04 +0100 Subject: [PATCH 08/53] deps/api: Bump `com_github_bufbuild_buf` -> 1.37.0 (#35793) Fix #35735 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index a9862e1dfb39..c02bf5e55ed3 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -144,11 +144,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "buf", project_desc = "A new way of working with Protocol Buffers.", # Used for breaking change detection in API protobufs project_url = "https://buf.build", - version = "1.35.0", - sha256 = "a75c622b5d6fae792a0e64a04baa296681eacba7ce0c3c35d25c8b42da2f71e1", + version = "1.37.0", + sha256 = "a76d94f27f1e1a1b74601bb8b179e170f1138c8692d6ddcfe15ee8b77e5b90a6", strip_prefix = "buf", urls = ["https://github.com/bufbuild/buf/releases/download/v{version}/buf-Linux-x86_64.tar.gz"], - release_date = "2024-07-22", + release_date = "2024-08-16", use_category = ["api"], license = "Apache-2.0", license_url = "https://github.com/bufbuild/buf/blob/v{version}/LICENSE", From 95770b51738c044f7fedc04bf27182b1fb4016d2 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 09:49:20 +0000 Subject: [PATCH 09/53] deps: Bump `aspect_bazel_lib` -> 2.8.1 (#35792) Fix #35755 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index a1832adde567..5fe2898251db 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -180,12 +180,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Aspect Bazel helpers", project_desc = "Base Starlark libraries and basic Bazel rules which are useful for constructing rulesets and BUILD files", project_url = "https://github.com/aspect-build/bazel-lib", - version = "2.7.9", - sha256 = "ccb66940aff9dfded4b03b929c83803f386807ef5ea4960404dfa8a7715cb74f", + version = "2.8.1", + sha256 = "d96f4dc5c129a033e6851a03b04219513bd32aed66f13f93d87879e3cb0349db", strip_prefix = "bazel-lib-{version}", urls = ["https://github.com/aspect-build/bazel-lib/archive/v{version}.tar.gz"], use_category = ["build"], - release_date = "2024-07-20", + release_date = "2024-08-19", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/aspect-build/bazel-lib/blob/v{version}/LICENSE", From 760112dc9a27f5646abaa5ce79ced4d3bdde77b3 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 09:51:58 +0000 Subject: [PATCH 10/53] deps: Bump `com_github_maxmind_libmaxminddb` -> 1.11.0 (#35791) Fix #35789 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 5fe2898251db..5e0eac9473b0 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1550,13 +1550,13 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "maxmind_libmaxminddb", project_desc = "C library for reading MaxMind DB files", project_url = "https://github.com/maxmind/libmaxminddb", - version = "1.10.0", - sha256 = "5e6db72df423ae225bfe8897069f6def40faa8931f456b99d79b8b4d664c6671", + version = "1.11.0", + sha256 = "b2eea79a96fed77ad4d6c39ec34fed83d45fcb75a31c58956813d58dcf30b19f", strip_prefix = "libmaxminddb-{version}", urls = ["https://github.com/maxmind/libmaxminddb/releases/download/{version}/libmaxminddb-{version}.tar.gz"], use_category = ["dataplane_ext"], extensions = ["envoy.geoip_providers.maxmind"], - release_date = "2024-06-10", + release_date = "2024-08-21", cpe = "cpe:2.3:a:maxmind:libmaxminddb:*", license = "Apache-2.0", license_url = "https://github.com/maxmind/libmaxminddb/blob/{version}/LICENSE", From e3ab25e592b4ee610975d719fbdc97637e07d453 Mon Sep 17 00:00:00 2001 From: code Date: Thu, 22 Aug 2024 19:50:29 +0800 Subject: [PATCH 11/53] tools/ci: minor optimization to the ci scripts for macos (#35800) Commit Message: tools/ci: minor optimization to the ci scripts for macos Additional Description: Risk Level: low. Testing: n/a. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping --- ci/build_setup.sh | 9 +++- ci/do_ci.sh | 127 +++++++++++++++++++++++++--------------------- 2 files changed, 76 insertions(+), 60 deletions(-) diff --git a/ci/build_setup.sh b/ci/build_setup.sh index 598cbcac45f1..36f325417582 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -13,7 +13,14 @@ fi export PPROF_PATH=/thirdparty_build/bin/pprof -[ -z "${NUM_CPUS}" ] && NUM_CPUS=$(grep -c ^processor /proc/cpuinfo) +if [[ -z "${NUM_CPUS}" ]]; then + if [[ "${OSTYPE}" == darwin* ]]; then + NUM_CPUS=$(sysctl -n hw.ncpu) + else + NUM_CPUS=$(grep -c ^processor /proc/cpuinfo) + fi +fi + [ -z "${ENVOY_SRCDIR}" ] && export ENVOY_SRCDIR=/source [ -z "${ENVOY_BUILD_TARGET}" ] && export ENVOY_BUILD_TARGET=//source/exe:envoy-static [ -z "${ENVOY_BUILD_DEBUG_INFORMATION}" ] && export ENVOY_BUILD_DEBUG_INFORMATION=//source/exe:envoy-static.dwp diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 038a7c7e4c06..ed856b0af883 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -235,6 +235,70 @@ function bazel_contrib_binary_build() { bazel_binary_build "$1" "${ENVOY_CONTRIB_BUILD_TARGET}" "${ENVOY_CONTRIB_BUILD_DEBUG_INFORMATION}" envoy-contrib } +function bazel_envoy_api_build() { + # Use libstdc++ because the API booster links to prebuilt libclang*/libLLVM* installed in /opt/llvm/lib, + # which is built with libstdc++. Using libstdc++ for whole of the API CI job to avoid unnecessary rebuild. + ENVOY_STDLIB="libstdc++" + setup_clang_toolchain + export CLANG_TOOLCHAIN_SETUP=1 + export LLVM_CONFIG="${LLVM_ROOT}"/bin/llvm-config + echo "Run protoxform test" + bazel run "${BAZEL_BUILD_OPTIONS[@]}" \ + --//tools/api_proto_plugin:default_type_db_target=//tools/testdata/protoxform:fix_protos \ + --//tools/api_proto_plugin:extra_args=api_version:3.7 \ + //tools/protoprint:protoprint_test + echo "Validating API structure..." + "${ENVOY_SRCDIR}"/tools/api/validate_structure.py + echo "Testing API..." + bazel_with_collection \ + test "${BAZEL_BUILD_OPTIONS[@]}" \ + --remote_download_minimal \ + -c fastbuild \ + @envoy_api//test/... \ + @envoy_api//tools/... \ + @envoy_api//tools:tap2pcap_test + echo "Building API..." + bazel build "${BAZEL_BUILD_OPTIONS[@]}" \ + -c fastbuild @envoy_api//envoy/... +} + +function bazel_envoy_api_go_build() { + if [[ -z "$CLANG_TOOLCHAIN_SETUP" ]]; then + setup_clang_toolchain + fi + GO_IMPORT_BASE="github.com/envoyproxy/go-control-plane" + GO_TARGETS=(@envoy_api//...) + read -r -a GO_PROTOS <<< "$(bazel query "${BAZEL_GLOBAL_OPTIONS[@]}" "kind('go_proto_library', ${GO_TARGETS[*]})" | tr '\n' ' ')" + echo "${GO_PROTOS[@]}" | grep -q envoy_api || echo "No go proto targets found" + bazel build "${BAZEL_BUILD_OPTIONS[@]}" \ + --experimental_proto_descriptor_sets_include_source_info \ + --remote_download_outputs=all \ + "${GO_PROTOS[@]}" + rm -rf build_go + mkdir -p build_go + echo "Copying go protos -> build_go" + BAZEL_BIN="$(bazel info "${BAZEL_BUILD_OPTIONS[@]}" bazel-bin)" + for GO_PROTO in "${GO_PROTOS[@]}"; do + # strip @envoy_api// + RULE_DIR="$(echo "${GO_PROTO:12}" | cut -d: -f1)" + PROTO="$(echo "${GO_PROTO:12}" | cut -d: -f2)" + INPUT_DIR="${BAZEL_BIN}/external/envoy_api/${RULE_DIR}/${PROTO}_/${GO_IMPORT_BASE}/${RULE_DIR}" + OUTPUT_DIR="build_go/${RULE_DIR}" + mkdir -p "$OUTPUT_DIR" + if [[ ! -e "$INPUT_DIR" ]]; then + echo "Unable to find input ${INPUT_DIR}" >&2 + exit 1 + fi + # echo "Copying go files ${INPUT_DIR} -> ${OUTPUT_DIR}" + while read -r GO_FILE; do + cp -a "$GO_FILE" "$OUTPUT_DIR" + if [[ "$GO_FILE" = *.validate.go ]]; then + sed -i '1s;^;//go:build !disable_pgv\n;' "$OUTPUT_DIR/$(basename "$GO_FILE")" + fi + done <<< "$(find "$INPUT_DIR" -name "*.go")" + done +} + CI_TARGET=$1 shift @@ -261,70 +325,15 @@ fi case $CI_TARGET in api) - # Use libstdc++ because the API booster links to prebuilt libclang*/libLLVM* installed in /opt/llvm/lib, - # which is built with libstdc++. Using libstdc++ for whole of the API CI job to avoid unnecessary rebuild. - ENVOY_STDLIB="libstdc++" - setup_clang_toolchain - export CLANG_TOOLCHAIN_SETUP=1 - export LLVM_CONFIG="${LLVM_ROOT}"/bin/llvm-config - echo "Run protoxform test" - bazel run "${BAZEL_BUILD_OPTIONS[@]}" \ - --//tools/api_proto_plugin:default_type_db_target=//tools/testdata/protoxform:fix_protos \ - --//tools/api_proto_plugin:extra_args=api_version:3.7 \ - //tools/protoprint:protoprint_test - echo "Validating API structure..." - "${ENVOY_SRCDIR}"/tools/api/validate_structure.py - echo "Testing API..." - bazel_with_collection \ - test "${BAZEL_BUILD_OPTIONS[@]}" \ - --remote_download_minimal \ - -c fastbuild \ - @envoy_api//test/... \ - @envoy_api//tools/... \ - @envoy_api//tools:tap2pcap_test - echo "Building API..." - bazel build "${BAZEL_BUILD_OPTIONS[@]}" \ - -c fastbuild @envoy_api//envoy/... + bazel_envoy_api_build if [[ -n "$ENVOY_API_ONLY" ]]; then exit 0 fi - ;& + bazel_envoy_api_go_build + ;; api.go) - if [[ -z "$CLANG_TOOLCHAIN_SETUP" ]]; then - setup_clang_toolchain - fi - GO_IMPORT_BASE="github.com/envoyproxy/go-control-plane" - GO_TARGETS=(@envoy_api//...) - read -r -a GO_PROTOS <<< "$(bazel query "${BAZEL_GLOBAL_OPTIONS[@]}" "kind('go_proto_library', ${GO_TARGETS[*]})" | tr '\n' ' ')" - echo "${GO_PROTOS[@]}" | grep -q envoy_api || echo "No go proto targets found" - bazel build "${BAZEL_BUILD_OPTIONS[@]}" \ - --experimental_proto_descriptor_sets_include_source_info \ - --remote_download_outputs=all \ - "${GO_PROTOS[@]}" - rm -rf build_go - mkdir -p build_go - echo "Copying go protos -> build_go" - BAZEL_BIN="$(bazel info "${BAZEL_BUILD_OPTIONS[@]}" bazel-bin)" - for GO_PROTO in "${GO_PROTOS[@]}"; do - # strip @envoy_api// - RULE_DIR="$(echo "${GO_PROTO:12}" | cut -d: -f1)" - PROTO="$(echo "${GO_PROTO:12}" | cut -d: -f2)" - INPUT_DIR="${BAZEL_BIN}/external/envoy_api/${RULE_DIR}/${PROTO}_/${GO_IMPORT_BASE}/${RULE_DIR}" - OUTPUT_DIR="build_go/${RULE_DIR}" - mkdir -p "$OUTPUT_DIR" - if [[ ! -e "$INPUT_DIR" ]]; then - echo "Unable to find input ${INPUT_DIR}" >&2 - exit 1 - fi - # echo "Copying go files ${INPUT_DIR} -> ${OUTPUT_DIR}" - while read -r GO_FILE; do - cp -a "$GO_FILE" "$OUTPUT_DIR" - if [[ "$GO_FILE" = *.validate.go ]]; then - sed -i '1s;^;//go:build !disable_pgv\n;' "$OUTPUT_DIR/$(basename "$GO_FILE")" - fi - done <<< "$(find "$INPUT_DIR" -name "*.go")" - done + bazel_envoy_api_go_build ;; api_compat) From b7a79586d71fd7cd0eea294284e875ccf4acfd16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:52:22 +0100 Subject: [PATCH 12/53] build(deps): bump setuptools from 72.1.0 to 73.0.1 in /tools/base (#35766) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 2d2a817b5137..4906368d55c2 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1715,7 +1715,7 @@ zstandard==0.23.0 \ # via envoy-base-utils # The following packages are considered to be unsafe in a requirements file: -setuptools==72.1.0 \ - --hash=sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1 \ - --hash=sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec +setuptools==73.0.1 \ + --hash=sha256:b208925fcb9f7af924ed2dc04708ea89791e24bde0d3020b27df0e116088b34e \ + --hash=sha256:d59a3e788ab7e012ab2c4baed1b376da6366883ee20d7a5fc426816e3d7b1193 # via -r requirements.in From 075150b0bcfea44d59c76aae8eca6bbff82a9a5e Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:13:54 +0100 Subject: [PATCH 13/53] deps: Bump `com_github_axboe_liburing` -> 2.7 (#35794) Fix #35734 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 5e0eac9473b0..eb097a94c114 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -222,12 +222,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "liburing", project_desc = "C helpers to set up and tear down io_uring instances", project_url = "https://github.com/axboe/liburing", - version = "2.5", - sha256 = "456f5f882165630f0dc7b75e8fd53bd01a955d5d4720729b4323097e6e9f2a98", + version = "2.7", + sha256 = "56202ad443c50e684dde3692819be3b91bbe003e1c14bf5abfa11973669978c1", strip_prefix = "liburing-liburing-{version}", urls = ["https://github.com/axboe/liburing/archive/liburing-{version}.tar.gz"], use_category = ["dataplane_core", "controlplane"], - release_date = "2023-11-29", + release_date = "2024-08-16", cpe = "N/A", ), # This dependency is built only when performance tracing is enabled with the From 04bb74ce01b4bc60c4f92a7582af8b573b53d327 Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Thu, 22 Aug 2024 10:49:55 -0400 Subject: [PATCH 14/53] style-guide: update testing links (#35757) Signed-off-by: Adi Suissa-Peleg --- STYLE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/STYLE.md b/STYLE.md index 42d255be31a1..401b55c78889 100644 --- a/STYLE.md +++ b/STYLE.md @@ -233,8 +233,8 @@ environment. In general, there should be no non-local network access. In additio Tests should be deterministic. They should not rely on randomness or details such as the current time. Instead, mocks such as -[`MockRandomGenerator`](test/mocks/runtime/mocks.h) and -[`Mock*TimeSource`](test/mocks/common.h) should be used. +[`MockRandomGenerator`](test/mocks/common.h) and +[`SimulatedTimeSystem`](test/test_common/simulated_time_system.h) should be used. # Google style guides for other languages From f615e1479a261aab0ad4342c0a48128498f72b90 Mon Sep 17 00:00:00 2001 From: code Date: Thu, 22 Aug 2024 22:52:29 +0800 Subject: [PATCH 15/53] use bash source rather than dirname $0 (#35804) Commit Message: use bash source rather than dirname $0 Additional Description: Risk Level: low. Testing: n/a. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping --- bazel/sh_test_wrapper.sh | 2 +- ci/build_setup.sh | 6 ++++-- ci/do_ci.sh | 4 +++- ci/envoy_build_sha.sh | 3 ++- ci/run_envoy_docker.sh | 4 +++- mobile/bazelw | 2 +- mobile/remote | 2 +- mobile/tools/check_format.sh | 2 +- test/common/tls/ocsp/test_data/certs.sh | 2 +- test/common/tls/test_data/certs.sh | 2 +- .../network/thrift_proxy/driver/generate_bindings.sh | 2 +- tools/bazel-test-docker.sh | 5 +++-- tools/debugging/run-valgrind.sh | 5 +++-- tools/git/modified_since_last_github_commit.sh | 2 +- 14 files changed, 26 insertions(+), 17 deletions(-) diff --git a/bazel/sh_test_wrapper.sh b/bazel/sh_test_wrapper.sh index fd10ffee5671..85edf3a9d4d2 100755 --- a/bazel/sh_test_wrapper.sh +++ b/bazel/sh_test_wrapper.sh @@ -4,7 +4,7 @@ # TODO(lizan): remove when we have a solution for # https://github.com/bazelbuild/bazel/issues/3510 -cd "$(dirname "$0")" || exit 1 +cd "$(realpath "$(dirname "${BASH_SOURCE[0]}")")" || exit 1 if [ $# -gt 0 ]; then "./${1}" "${@:2}" diff --git a/ci/build_setup.sh b/ci/build_setup.sh index 36f325417582..abdbea03859b 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -11,6 +11,8 @@ if [[ -n "$NO_BUILD_SETUP" ]]; then return fi +CURRENT_SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + export PPROF_PATH=/thirdparty_build/bin/pprof if [[ -z "${NUM_CPUS}" ]]; then @@ -118,7 +120,7 @@ export BAZEL_BUILD_OPTION_LIST export BAZEL_GLOBAL_OPTION_LIST if [[ -e "${LLVM_ROOT}" ]]; then - "$(dirname "$0")/../bazel/setup_clang.sh" "${LLVM_ROOT}" + "${CURRENT_SCRIPT_DIR}/../bazel/setup_clang.sh" "${LLVM_ROOT}" else echo "LLVM_ROOT not found, not setting up llvm." fi @@ -155,7 +157,7 @@ mkdir -p "${ENVOY_BUILD_PROFILE}" if [[ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "true" ]]; then # shellcheck source=ci/filter_example_setup.sh - . "$(dirname "$0")"/filter_example_setup.sh + . "${CURRENT_SCRIPT_DIR}"/filter_example_setup.sh else echo "Skip setting up Envoy Filter Example." fi diff --git a/ci/do_ci.sh b/ci/do_ci.sh index ed856b0af883..1d51f478f15c 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -8,8 +8,10 @@ set -e export SRCDIR="${SRCDIR:-$PWD}" export ENVOY_SRCDIR="${ENVOY_SRCDIR:-$PWD}" +CURRENT_SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + # shellcheck source=ci/build_setup.sh -. "$(dirname "$0")"/build_setup.sh +. "${CURRENT_SCRIPT_DIR}"/build_setup.sh echo "building using ${NUM_CPUS} CPUs" echo "building for ${ENVOY_BUILD_ARCH}" diff --git a/ci/envoy_build_sha.sh b/ci/envoy_build_sha.sh index 916da9b84b76..0a6243ed82d9 100644 --- a/ci/envoy_build_sha.sh +++ b/ci/envoy_build_sha.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash +CURRENT_SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" -ENVOY_BUILD_CONTAINER="$(grep envoyproxy/envoy-build-ubuntu "$(dirname "$0")"/../.bazelrc | sed -e 's#.*envoyproxy/envoy-build-ubuntu:\(.*\)#\1#' | uniq)" +ENVOY_BUILD_CONTAINER="$(grep envoyproxy/envoy-build-ubuntu "${CURRENT_SCRIPT_DIR}"/../.bazelrc | sed -e 's#.*envoyproxy/envoy-build-ubuntu:\(.*\)#\1#' | uniq)" ENVOY_BUILD_SHA="$(echo "${ENVOY_BUILD_CONTAINER}" | cut -d@ -f1)" ENVOY_BUILD_CONTAINER_SHA="$(echo "${ENVOY_BUILD_CONTAINER}" | cut -d@ -f2)" diff --git a/ci/run_envoy_docker.sh b/ci/run_envoy_docker.sh index 809d141fb9da..d73964e8cc1c 100755 --- a/ci/run_envoy_docker.sh +++ b/ci/run_envoy_docker.sh @@ -2,8 +2,10 @@ set -e +CURRENT_SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + # shellcheck source=ci/envoy_build_sha.sh -. "$(dirname "$0")"/envoy_build_sha.sh +. "${CURRENT_SCRIPT_DIR}"/envoy_build_sha.sh function is_windows() { [[ "$(uname -s)" == *NT* ]] diff --git a/mobile/bazelw b/mobile/bazelw index 7d16ff11b932..f461863b9e76 100755 --- a/mobile/bazelw +++ b/mobile/bazelw @@ -42,7 +42,7 @@ case "$bazel_platform" in esac readonly bazel_version_url="https://github.com/bazelbuild/bazelisk/releases/download/v$bazelisk_version/bazelisk-$bazel_platform" -script_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +script_root="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" readonly bazelisk="$script_root/tmp/bazel/versions/bazelisk-$bazelisk_version-$bazel_platform" if [[ ! -x "$bazelisk" ]]; then diff --git a/mobile/remote b/mobile/remote index d6828af230ac..1b5ea4099101 100755 --- a/mobile/remote +++ b/mobile/remote @@ -2,7 +2,7 @@ set -euo pipefail -script_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +script_root="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" certificate="$script_root/tmp/certs/engflow.crt" key="$script_root/tmp/certs/engflow.key" diff --git a/mobile/tools/check_format.sh b/mobile/tools/check_format.sh index 257a8e97506b..d4d00e06bf35 100755 --- a/mobile/tools/check_format.sh +++ b/mobile/tools/check_format.sh @@ -45,7 +45,7 @@ FORMAT_ARGS+=( export ENVOY_BAZEL_PREFIX="@envoy" && ./bazelw run @envoy//tools/code_format:check_format -- "${ENVOY_FORMAT_ACTION}" --path "$PWD" "${FORMAT_ARGS[@]}" -KTFMT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"/ktfmt.sh +KTFMT="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"/ktfmt.sh KOTLIN_DIRS=( "library/kotlin" "test/kotlin" diff --git a/test/common/tls/ocsp/test_data/certs.sh b/test/common/tls/ocsp/test_data/certs.sh index bc531ad2e94d..633a5304c3f0 100755 --- a/test/common/tls/ocsp/test_data/certs.sh +++ b/test/common/tls/ocsp/test_data/certs.sh @@ -5,7 +5,7 @@ set -e readonly DEFAULT_VALIDITY_DAYS=${DEFAULT_VALIDITY_DAYS:-730} -HERE=$(cd "$(dirname "$0")" && pwd) +HERE="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" readonly HERE cd "$HERE" || exit 1 diff --git a/test/common/tls/test_data/certs.sh b/test/common/tls/test_data/certs.sh index d1ba810665bd..2a89c216de46 100755 --- a/test/common/tls/test_data/certs.sh +++ b/test/common/tls/test_data/certs.sh @@ -3,7 +3,7 @@ set -e readonly DEFAULT_VALIDITY_DAYS=${DEFAULT_VALIDITY_DAYS:-730} -HERE=$(cd "$(dirname "$0")" && pwd) +HERE="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" readonly HERE cd "$HERE" || exit 1 diff --git a/test/extensions/filters/network/thrift_proxy/driver/generate_bindings.sh b/test/extensions/filters/network/thrift_proxy/driver/generate_bindings.sh index 0ba2827b95f5..d70964c64ae4 100755 --- a/test/extensions/filters/network/thrift_proxy/driver/generate_bindings.sh +++ b/test/extensions/filters/network/thrift_proxy/driver/generate_bindings.sh @@ -3,7 +3,7 @@ # Generates the thrift bindings for example.thrift. Requires that # apache-thrift's thrift generator is installed and on the path. -DIR=$(cd "$(dirname "$0")" && pwd) +DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" cd "${DIR}" || exit 1 thrift --gen py --out ./generated example.thrift diff --git a/tools/bazel-test-docker.sh b/tools/bazel-test-docker.sh index e6575a5fe81c..ff76215a045a 100755 --- a/tools/bazel-test-docker.sh +++ b/tools/bazel-test-docker.sh @@ -14,7 +14,7 @@ if [[ -z "$1" ]]; then exit 1 fi -SCRIPT_DIR="$(realpath "$(dirname "$0")")" +SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" [[ -z "${BAZEL}" ]] && BAZEL=bazel [[ -z "${DOCKER}" ]] && DOCKER=docker @@ -42,7 +42,8 @@ cat > "${DOCKER_ENV}" < Date: Thu, 22 Aug 2024 17:05:22 +0200 Subject: [PATCH 16/53] [Geoip] Mmdb hot reload support (#32490) Commit Message: Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: NA Fixes #30250 --------- Signed-off-by: Kateryna Nezdolii --- changelogs/current.yaml | 3 + .../http/http_filters/geoip_filter.rst | 2 + source/common/runtime/runtime_features.cc | 1 + .../extensions/geoip_providers/maxmind/BUILD | 1 + .../geoip_providers/maxmind/config.cc | 4 +- .../geoip_providers/maxmind/geoip_provider.cc | 222 +- .../geoip_providers/maxmind/geoip_provider.h | 59 +- test/extensions/geoip_providers/maxmind/BUILD | 1 + .../geoip_providers/maxmind/config_test.cc | 59 +- .../maxmind/geoip_provider_test.cc | 439 ++- .../GeoIP2-Anonymous-IP-Test-Updated.mmdb | Bin 0 -> 4374 bytes .../test_data/GeoLite2-ASN-Test-Updated.mmdb | Bin 0 -> 12662 bytes .../test_data/GeoLite2-City-Test-Updated.mmdb | Bin 0 -> 3461 bytes .../maxmind/test_data/README.md | 13 + .../libmaxminddb-offset-integer-overflow.mmdb | 2369 +++++++++++++++++ 15 files changed, 3069 insertions(+), 104 deletions(-) create mode 100644 test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test-Updated.mmdb create mode 100644 test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test-Updated.mmdb create mode 100644 test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test-Updated.mmdb create mode 100644 test/extensions/geoip_providers/maxmind/test_data/README.md create mode 100644 test/extensions/geoip_providers/maxmind/test_data/libmaxminddb-offset-integer-overflow.mmdb diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 43b611011d06..c0e1c53809ad 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -227,5 +227,8 @@ new_features: :ref:`happy_eyeballs_config `. A default configuration will be used if not provided. This behavior can be reverted by setting the runtime guard ``envoy.reloadable_features.use_config_in_happy_eyeballs`` to false. +- area: geoip + change: | + Added ``envoy.reloadable_features.mmdb_files_reload_enabled`` runtime flag that enables reload of mmdb files by default. deprecated: diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index 0c6c18d7ac15..ed232749edd7 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -76,5 +76,7 @@ per geolocation database type (rooted at ``.maxmind.``). Database t ``.total``, Counter, Total number of lookups performed for a given geolocation database file. ``.hit``, Counter, Total number of successful lookups (with non empty lookup result) performed for a given geolocation database file. ``.lookup_error``, Counter, Total number of errors that occured during lookups for a given geolocation database file. + ``.db_reload_success``, Counter, Total number of times when the geolocation database file was reloaded successfully. + ``.db_reload_error``, Counter, Total number of times when the geolocation database file failed to reload. diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index cff3db99a0bb..7089ef8daa47 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -66,6 +66,7 @@ RUNTIME_GUARD(envoy_reloadable_features_internal_authority_header_validator); RUNTIME_GUARD(envoy_reloadable_features_jwt_authn_remove_jwt_from_query_params); RUNTIME_GUARD(envoy_reloadable_features_jwt_authn_validate_uri); RUNTIME_GUARD(envoy_reloadable_features_lua_flow_control_while_http_call); +RUNTIME_GUARD(envoy_reloadable_features_mmdb_files_reload_enabled); RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name); RUNTIME_GUARD(envoy_reloadable_features_no_timer_based_rate_limit_token_bucket); RUNTIME_GUARD(envoy_reloadable_features_original_dst_rely_on_idle_timeout); diff --git a/source/extensions/geoip_providers/maxmind/BUILD b/source/extensions/geoip_providers/maxmind/BUILD index d0a9fc323375..016d6ebad64f 100644 --- a/source/extensions/geoip_providers/maxmind/BUILD +++ b/source/extensions/geoip_providers/maxmind/BUILD @@ -43,6 +43,7 @@ envoy_cc_library( deps = [ "//bazel/foreign_cc:maxmind_linux_darwin", "//envoy/geoip:geoip_provider_driver_interface", + "//source/common/common:thread_synchronizer_lib", "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc index d75a56b3e659..b2534b6e97be 100644 --- a/source/extensions/geoip_providers/maxmind/config.cc +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -35,7 +35,9 @@ class DriverSingleton : public Envoy::Singleton::Instance { } else { const auto& provider_config = std::make_shared(proto_config, stat_prefix, context.scope()); - driver = std::make_shared(singleton, provider_config); + driver = std::make_shared( + context.serverFactoryContext().mainThreadDispatcher(), + context.serverFactoryContext().api(), singleton, provider_config); drivers_[key] = driver; } return driver; diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.cc b/source/extensions/geoip_providers/maxmind/geoip_provider.cc index 5af87388c318..e56d9250c75e 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.cc +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.cc @@ -2,6 +2,7 @@ #include "source/common/common/assert.h" #include "source/common/protobuf/protobuf.h" +#include "source/common/runtime/runtime_features.h" namespace Envoy { namespace Extensions { @@ -16,6 +17,10 @@ static constexpr const char* MMDB_ASN_LOOKUP_ARGS[] = {"autonomous_system_number static constexpr const char* MMDB_ANON_LOOKUP_ARGS[] = {"is_anonymous", "is_anonymous_vpn", "is_hosting_provider", "is_tor_exit_node", "is_public_proxy"}; + +static constexpr absl::string_view CITY_DB_TYPE = "city_db"; +static constexpr absl::string_view ISP_DB_TYPE = "isp_db"; +static constexpr absl::string_view ANON_DB_TYPE = "anon_db"; } // namespace GeoipProviderConfig::GeoipProviderConfig( @@ -60,20 +65,22 @@ GeoipProviderConfig::GeoipProviderConfig( "city_db_path, isp_db_path or anon_db_path"); } if (city_db_path_) { - registerGeoDbStats("city_db"); + registerGeoDbStats(CITY_DB_TYPE); } if (isp_db_path_) { - registerGeoDbStats("isp_db"); + registerGeoDbStats(ISP_DB_TYPE); } if (anon_db_path_) { - registerGeoDbStats("anon_db"); + registerGeoDbStats(ANON_DB_TYPE); } }; -void GeoipProviderConfig::registerGeoDbStats(const std::string& db_type) { +void GeoipProviderConfig::registerGeoDbStats(const absl::string_view& db_type) { stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".total")); stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".hit")); stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".lookup_error")); + stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".db_reload_error")); + stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".db_reload_success")); } bool GeoipProviderConfig::isLookupEnabledForHeader(const absl::optional& header) { @@ -84,30 +91,57 @@ void GeoipProviderConfig::incCounter(Stats::StatName name) { stats_scope_->counterFromStatName(name).inc(); } +GeoipProvider::GeoipProvider(Event::Dispatcher& dispatcher, Api::Api& api, + Singleton::InstanceSharedPtr owner, + GeoipProviderConfigSharedPtr config) + : config_(config), owner_(owner) { + city_db_ = + config_->cityDbPath() ? initMaxmindDb(config_->cityDbPath().value(), CITY_DB_TYPE) : nullptr; + isp_db_ = + config_->ispDbPath() ? initMaxmindDb(config_->ispDbPath().value(), ISP_DB_TYPE) : nullptr; + anon_db_ = + config_->anonDbPath() ? initMaxmindDb(config_->anonDbPath().value(), ANON_DB_TYPE) : nullptr; + mmdb_reload_dispatcher_ = api.allocateDispatcher("mmdb_reload_routine"); + mmdb_watcher_ = dispatcher.createFilesystemWatcher(); + mmdb_reload_thread_ = api.threadFactory().createThread( + [this]() -> void { + ENVOY_LOG_MISC(debug, "Started mmdb_reload_routine"); + if (config_->cityDbPath() && + Runtime::runtimeFeatureEnabled("envoy.reloadable_features.mmdb_files_reload_enabled")) { + THROW_IF_NOT_OK(mmdb_watcher_->addWatch( + config_->cityDbPath().value(), Filesystem::Watcher::Events::MovedTo, + [this](uint32_t) { + return onMaxmindDbUpdate(config_->cityDbPath().value(), CITY_DB_TYPE); + })); + } + if (config_->ispDbPath() && + Runtime::runtimeFeatureEnabled("envoy.reloadable_features.mmdb_files_reload_enabled")) { + THROW_IF_NOT_OK(mmdb_watcher_->addWatch( + config_->ispDbPath().value(), Filesystem::Watcher::Events::MovedTo, [this](uint32_t) { + return onMaxmindDbUpdate(config_->ispDbPath().value(), ISP_DB_TYPE); + })); + } + if (config_->anonDbPath() && + Runtime::runtimeFeatureEnabled("envoy.reloadable_features.mmdb_files_reload_enabled")) { + THROW_IF_NOT_OK(mmdb_watcher_->addWatch( + config_->anonDbPath().value(), Filesystem::Watcher::Events::MovedTo, + [this](uint32_t) { + return onMaxmindDbUpdate(config_->anonDbPath().value(), ANON_DB_TYPE); + })); + } + mmdb_reload_dispatcher_->run(Event::Dispatcher::RunType::RunUntilExit); + }, + Thread::Options{std::string("mmdb_reload_routine")}); +}; + GeoipProvider::~GeoipProvider() { ENVOY_LOG(debug, "Shutting down Maxmind geolocation provider"); - if (city_db_) { - MMDB_close(city_db_.get()); - } - if (isp_db_) { - MMDB_close(isp_db_.get()); + if (mmdb_reload_dispatcher_) { + mmdb_reload_dispatcher_->exit(); } - if (anon_db_) { - MMDB_close(anon_db_.get()); - } -} - -MaxmindDbPtr GeoipProvider::initMaxMindDb(const absl::optional& db_path) { - if (db_path) { - MMDB_s maxmind_db; - int result_code = MMDB_open(db_path.value().c_str(), MMDB_MODE_MMAP, &maxmind_db); - RELEASE_ASSERT(MMDB_SUCCESS == result_code, - fmt::format("Unable to open Maxmind database file {}. Error {}", db_path.value(), - std::string(MMDB_strerror(result_code)))); - return std::make_unique(maxmind_db); - } else { - ENVOY_LOG(debug, "Geolocation database path is empty, skipping database creation"); - return nullptr; + if (mmdb_reload_thread_) { + mmdb_reload_thread_->join(); + mmdb_reload_thread_.reset(); } } @@ -127,11 +161,19 @@ void GeoipProvider::lookupInCityDb( if (config_->isLookupEnabledForHeader(config_->cityHeader()) || config_->isLookupEnabledForHeader(config_->regionHeader()) || config_->isLookupEnabledForHeader(config_->countryHeader())) { - ASSERT(city_db_, "Maxmind city database is not initialised for performing lookups"); int mmdb_error; - const uint32_t n_prev_hits = lookup_result.size(); + auto city_db_ptr = getCityDb(); + // Used for testing. + synchronizer_.syncPoint(std::string(CITY_DB_TYPE).append("_lookup_pre_complete")); + if (!city_db_ptr) { + IS_ENVOY_BUG("Maxmind city database must be initialised for performing lookups"); + return; + } + auto city_db = city_db_ptr.get(); MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( - city_db_.get(), reinterpret_cast(remote_address->sockAddr()), &mmdb_error); + city_db->mmdb(), reinterpret_cast(remote_address->sockAddr()), + &mmdb_error); + const uint32_t n_prev_hits = lookup_result.size(); if (!mmdb_error) { MMDB_entry_data_list_s* entry_data_list; int status = MMDB_get_entry_data_list(&mmdb_lookup_result.entry, &entry_data_list); @@ -152,15 +194,15 @@ void GeoipProvider::lookupInCityDb( MMDB_COUNTRY_LOOKUP_ARGS[1]); } if (lookup_result.size() > n_prev_hits) { - config_->incHit("city_db"); + config_->incHit(CITY_DB_TYPE); } MMDB_free_entry_data_list(entry_data_list); } } else { - config_->incLookupError("city_db"); + config_->incLookupError(CITY_DB_TYPE); } - config_->incTotal("city_db"); + config_->incTotal(CITY_DB_TYPE); } } @@ -168,11 +210,18 @@ void GeoipProvider::lookupInAsnDb( const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const { if (config_->isLookupEnabledForHeader(config_->asnHeader())) { - RELEASE_ASSERT(isp_db_, "Maxmind asn database is not initialized for performing lookups"); int mmdb_error; - const uint32_t n_prev_hits = lookup_result.size(); + auto isp_db_ptr = getIspDb(); + // Used for testing. + synchronizer_.syncPoint(std::string(ISP_DB_TYPE).append("_lookup_pre_complete")); + if (!isp_db_ptr) { + IS_ENVOY_BUG("Maxmind asn database must be initialised for performing lookups"); + return; + } MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( - isp_db_.get(), reinterpret_cast(remote_address->sockAddr()), &mmdb_error); + isp_db_ptr->mmdb(), reinterpret_cast(remote_address->sockAddr()), + &mmdb_error); + const uint32_t n_prev_hits = lookup_result.size(); if (!mmdb_error) { MMDB_entry_data_list_s* entry_data_list; int status = MMDB_get_entry_data_list(&mmdb_lookup_result.entry, &entry_data_list); @@ -181,13 +230,13 @@ void GeoipProvider::lookupInAsnDb( MMDB_ASN_LOOKUP_ARGS[0]); MMDB_free_entry_data_list(entry_data_list); if (lookup_result.size() > n_prev_hits) { - config_->incHit("isp_db"); + config_->incHit(ISP_DB_TYPE); } } else { - config_->incLookupError("isp_db"); + config_->incLookupError(ISP_DB_TYPE); } } - config_->incTotal("isp_db"); + config_->incTotal(ISP_DB_TYPE); } } @@ -195,11 +244,19 @@ void GeoipProvider::lookupInAnonDb( const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const { if (config_->isLookupEnabledForHeader(config_->anonHeader()) || config_->anonVpnHeader()) { - ASSERT(anon_db_, "Maxmind city database is not initialised for performing lookups"); int mmdb_error; - const uint32_t n_prev_hits = lookup_result.size(); + auto anon_db_ptr = getAnonDb(); + // Used for testing. + synchronizer_.syncPoint(std::string(ANON_DB_TYPE).append("_lookup_pre_complete")); + if (!anon_db_ptr) { + IS_ENVOY_BUG("Maxmind anon database must be initialised for performing lookups"); + return; + } + auto anon_db = anon_db_ptr.get(); MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( - anon_db_.get(), reinterpret_cast(remote_address->sockAddr()), &mmdb_error); + anon_db->mmdb(), reinterpret_cast(remote_address->sockAddr()), + &mmdb_error); + const uint32_t n_prev_hits = lookup_result.size(); if (!mmdb_error) { MMDB_entry_data_list_s* entry_data_list; int status = MMDB_get_entry_data_list(&mmdb_lookup_result.entry, &entry_data_list); @@ -225,15 +282,94 @@ void GeoipProvider::lookupInAnonDb( config_->anonProxyHeader().value(), MMDB_ANON_LOOKUP_ARGS[4]); } if (lookup_result.size() > n_prev_hits) { - config_->incHit("anon_db"); + config_->incHit(ANON_DB_TYPE); } MMDB_free_entry_data_list(entry_data_list); } else { - config_->incLookupError("anon_db"); + config_->incLookupError(ANON_DB_TYPE); } } - config_->incTotal("anon_db"); + config_->incTotal(ANON_DB_TYPE); + } +} + +MaxmindDbSharedPtr GeoipProvider::initMaxmindDb(const std::string& db_path, + const absl::string_view& db_type, bool reload) { + MMDB_s maxmind_db; + int result_code = MMDB_open(db_path.c_str(), MMDB_MODE_MMAP, &maxmind_db); + + if (reload && MMDB_SUCCESS != result_code) { + ENVOY_LOG(error, "Failed to reload Maxmind database {} from file {}. Error {}", db_type, + db_path, std::string(MMDB_strerror(result_code))); + return nullptr; + } else if (MMDB_SUCCESS != result_code) { + // Crash if this is a failure during initial load. + RELEASE_ASSERT(MMDB_SUCCESS == result_code, + fmt::format("Unable to open Maxmind database file {}. Error {}", db_path, + std::string(MMDB_strerror(result_code)))); + return nullptr; + } + + ENVOY_LOG(info, "Succeeded to reload Maxmind database {} from file {}.", db_type, db_path); + return std::make_shared(std::move(maxmind_db)); +} + +absl::Status GeoipProvider::mmdbReload(const MaxmindDbSharedPtr reloaded_db, + const absl::string_view& db_type) { + if (reloaded_db) { + if (db_type == CITY_DB_TYPE) { + updateCityDb(reloaded_db); + config_->incDbReloadSuccess(db_type); + } else if (db_type == ISP_DB_TYPE) { + updateIspDb(reloaded_db); + config_->incDbReloadSuccess(db_type); + } else if (db_type == ANON_DB_TYPE) { + updateAnonDb(reloaded_db); + config_->incDbReloadSuccess(db_type); + } else { + ENVOY_LOG(error, "Unsupported maxmind db type {}", db_type); + return absl::InvalidArgumentError(fmt::format("Unsupported maxmind db type {}", db_type)); + } + } else { + config_->incDbReloadError(db_type); } + return absl::OkStatus(); +} + +MaxmindDbSharedPtr GeoipProvider::getCityDb() const ABSL_LOCKS_EXCLUDED(mmdb_mutex_) { + absl::ReaderMutexLock lock(&mmdb_mutex_); + return city_db_; +} + +void GeoipProvider::updateCityDb(MaxmindDbSharedPtr city_db) ABSL_LOCKS_EXCLUDED(mmdb_mutex_) { + absl::MutexLock lock(&mmdb_mutex_); + city_db_ = city_db; +} + +MaxmindDbSharedPtr GeoipProvider::getIspDb() const ABSL_LOCKS_EXCLUDED(mmdb_mutex_) { + absl::ReaderMutexLock lock(&mmdb_mutex_); + return isp_db_; +} + +void GeoipProvider::updateIspDb(MaxmindDbSharedPtr isp_db) ABSL_LOCKS_EXCLUDED(mmdb_mutex_) { + absl::MutexLock lock(&mmdb_mutex_); + isp_db_ = isp_db; +} + +MaxmindDbSharedPtr GeoipProvider::getAnonDb() const ABSL_LOCKS_EXCLUDED(mmdb_mutex_) { + absl::ReaderMutexLock lock(&mmdb_mutex_); + return anon_db_; +} + +void GeoipProvider::updateAnonDb(MaxmindDbSharedPtr anon_db) ABSL_LOCKS_EXCLUDED(mmdb_mutex_) { + absl::MutexLock lock(&mmdb_mutex_); + anon_db_ = anon_db; +} + +absl::Status GeoipProvider::onMaxmindDbUpdate(const std::string& db_path, + const absl::string_view& db_type) { + MaxmindDbSharedPtr reloaded_db = initMaxmindDb(db_path, db_type, true /* reload */); + return mmdbReload(reloaded_db, db_type); } template diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h index 25f5c11b3a51..2ecf71b6497d 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.h +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -5,6 +5,7 @@ #include "envoy/geoip/geoip_provider_driver.h" #include "source/common/common/logger.h" +#include "source/common/common/thread_synchronizer.h" #include "maxminddb.h" @@ -48,7 +49,17 @@ class GeoipProviderConfig { incCounter(stat_name_set_->getBuiltin(absl::StrCat(maxmind_db_type, ".hit"), unknown_hit_)); } - void registerGeoDbStats(const std::string& db_type); + void incDbReloadSuccess(absl::string_view maxmind_db_type) { + incCounter(stat_name_set_->getBuiltin(absl::StrCat(maxmind_db_type, ".db_reload_success"), + unknown_hit_)); + } + + void incDbReloadError(absl::string_view maxmind_db_type) { + incCounter(stat_name_set_->getBuiltin(absl::StrCat(maxmind_db_type, ".db_reload_error"), + unknown_hit_)); + } + + void registerGeoDbStats(const absl::string_view& db_type); Stats::Scope& getStatsScopeForTest() const { return *stats_scope_; } @@ -76,17 +87,25 @@ class GeoipProviderConfig { using GeoipProviderConfigSharedPtr = std::shared_ptr; -using MaxmindDbPtr = std::unique_ptr; +// Wrapper class for MMDB_s type that ensures a proper cleanup of the MMDB_s +// instance resources prior to its destruction. +class MaxmindDb { +public: + MaxmindDb(MMDB_s&& db) : db_(db) {} + ~MaxmindDb() { MMDB_close(&db_); } + const MMDB_s* mmdb() const { return &db_; } + +private: + MMDB_s db_; +}; + +using MaxmindDbSharedPtr = std::shared_ptr; class GeoipProvider : public Envoy::Geolocation::Driver, public Logger::Loggable { public: - GeoipProvider(Singleton::InstanceSharedPtr owner, GeoipProviderConfigSharedPtr config) - : config_(config), owner_(owner) { - city_db_ = initMaxMindDb(config_->cityDbPath()); - isp_db_ = initMaxMindDb(config_->ispDbPath()); - anon_db_ = initMaxMindDb(config_->anonDbPath()); - }; + GeoipProvider(Event::Dispatcher& dispatcher, Api::Api& api, Singleton::InstanceSharedPtr owner, + GeoipProviderConfigSharedPtr config); ~GeoipProvider() override; @@ -97,22 +116,38 @@ class GeoipProvider : public Envoy::Geolocation::Driver, // Allow the unit test to have access to private members. friend class GeoipProviderPeer; GeoipProviderConfigSharedPtr config_; - MaxmindDbPtr city_db_; - MaxmindDbPtr isp_db_; - MaxmindDbPtr anon_db_; - MaxmindDbPtr initMaxMindDb(const absl::optional& db_path); + mutable absl::Mutex mmdb_mutex_; + MaxmindDbSharedPtr city_db_ ABSL_GUARDED_BY(mmdb_mutex_); + MaxmindDbSharedPtr isp_db_ ABSL_GUARDED_BY(mmdb_mutex_); + MaxmindDbSharedPtr anon_db_ ABSL_GUARDED_BY(mmdb_mutex_); + Thread::ThreadPtr mmdb_reload_thread_; + Event::DispatcherPtr mmdb_reload_dispatcher_; + Filesystem::WatcherPtr mmdb_watcher_; + MaxmindDbSharedPtr initMaxmindDb(const std::string& db_path, const absl::string_view& db_type, + bool reload = false); void lookupInCityDb(const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const; void lookupInAsnDb(const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const; void lookupInAnonDb(const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const; + absl::Status onMaxmindDbUpdate(const std::string& db_path, const absl::string_view& db_type); + absl::Status mmdbReload(const MaxmindDbSharedPtr reloaded_db, const absl::string_view& db_type) + ABSL_LOCKS_EXCLUDED(mmdb_mutex_); template void populateGeoLookupResult(MMDB_lookup_result_s& mmdb_lookup_result, absl::flat_hash_map& lookup_result, const std::string& result_key, Params... lookup_params) const; + MaxmindDbSharedPtr getCityDb() const ABSL_LOCKS_EXCLUDED(mmdb_mutex_); + MaxmindDbSharedPtr getIspDb() const ABSL_LOCKS_EXCLUDED(mmdb_mutex_); + MaxmindDbSharedPtr getAnonDb() const ABSL_LOCKS_EXCLUDED(mmdb_mutex_); + void updateCityDb(MaxmindDbSharedPtr city_db) ABSL_LOCKS_EXCLUDED(mmdb_mutex_); + void updateIspDb(MaxmindDbSharedPtr isp_db) ABSL_LOCKS_EXCLUDED(mmdb_mutex_); + void updateAnonDb(MaxmindDbSharedPtr anon_db) ABSL_LOCKS_EXCLUDED(mmdb_mutex_); // A shared_ptr to keep the provider singleton alive as long as any of its providers are in use. const Singleton::InstanceSharedPtr owner_; + // Used for testing only. + mutable Thread::ThreadSynchronizer synchronizer_; }; using GeoipProviderSharedPtr = std::shared_ptr; diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index c39b4eb33382..2262723c8acf 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -50,6 +50,7 @@ envoy_extension_cc_test( "//source/extensions/geoip_providers/maxmind:config", "//source/extensions/geoip_providers/maxmind:provider_impl", "//test/mocks/server:factory_context_mocks", + "//test/test_common:test_runtime_lib", "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/geoip_providers/maxmind/config_test.cc b/test/extensions/geoip_providers/maxmind/config_test.cc index 53b40ec948f3..2e4d72417bf7 100644 --- a/test/extensions/geoip_providers/maxmind/config_test.cc +++ b/test/extensions/geoip_providers/maxmind/config_test.cc @@ -11,7 +11,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using ::testing::AllOf; +using testing::AllOf; +using testing::InvokeWithoutArgs; +using testing::Return; +using testing::ReturnRef; namespace Envoy { namespace Extensions { @@ -183,12 +186,35 @@ std::string genGeoDbFilePath(std::string db_name) { "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/" + db_name); } -TEST(MaxmindProviderConfigTest, EmptyProto) { +class MaxmindProviderConfigTest : public testing::Test { +public: + MaxmindProviderConfigTest() : api_(Api::createApiForTest(stats_store_)) { + EXPECT_CALL(context_, serverFactoryContext()) + .WillRepeatedly(ReturnRef(server_factory_context_)); + EXPECT_CALL(server_factory_context_, api()).WillRepeatedly(ReturnRef(*api_)); + EXPECT_CALL(server_factory_context_, mainThreadDispatcher()) + .WillRepeatedly(ReturnRef(dispatcher_)); + EXPECT_CALL(dispatcher_, createFilesystemWatcher_()).WillRepeatedly(InvokeWithoutArgs([&] { + Filesystem::MockWatcher* mock_watcher = new NiceMock(); + EXPECT_CALL(*mock_watcher, addWatch(_, Filesystem::Watcher::Events::MovedTo, _)) + .WillRepeatedly(Return(absl::OkStatus())); + return mock_watcher; + })); + } + + Api::ApiPtr api_; + Stats::IsolatedStoreImpl stats_store_; + Event::MockDispatcher dispatcher_; + NiceMock server_factory_context_; + NiceMock context_; +}; + +TEST_F(MaxmindProviderConfigTest, EmptyProto) { MaxmindProviderFactory factory; EXPECT_TRUE(factory.createEmptyConfigProto() != nullptr); } -TEST(MaxmindProviderConfigTest, ProviderConfigWithCorrectProto) { +TEST_F(MaxmindProviderConfigTest, ProviderConfigWithCorrectProto) { const auto provider_config_yaml = R"EOF( common_provider_config: geo_headers_to_add: @@ -213,11 +239,9 @@ TEST(MaxmindProviderConfigTest, ProviderConfigWithCorrectProto) { auto processed_provider_config_yaml = absl::StrFormat(provider_config_yaml, city_db_path, asn_db_path, anon_db_path); TestUtility::loadFromYaml(processed_provider_config_yaml, provider_config); - NiceMock context; - EXPECT_CALL(context, messageValidationVisitor()); MaxmindProviderFactory factory; Geolocation::DriverSharedPtr driver = - factory.createGeoipProviderDriver(provider_config, "maxmind", context); + factory.createGeoipProviderDriver(provider_config, "maxmind", context_); EXPECT_THAT(driver, AllOf(HasCityDbPath(city_db_path), HasIspDbPath(asn_db_path), HasAnonDbPath(anon_db_path), HasCountryHeader("x-geo-country"), HasCityHeader("x-geo-city"), HasRegionHeader("x-geo-region"), @@ -226,7 +250,7 @@ TEST(MaxmindProviderConfigTest, ProviderConfigWithCorrectProto) { HasAnonHostingHeader("x-anon-hosting"))); } -TEST(MaxmindProviderConfigTest, ProviderConfigWithNoDbPaths) { +TEST_F(MaxmindProviderConfigTest, ProviderConfigWithNoDbPaths) { std::string provider_config_yaml = R"EOF( common_provider_config: geo_headers_to_add: @@ -236,7 +260,6 @@ TEST(MaxmindProviderConfigTest, ProviderConfigWithNoDbPaths) { MaxmindProviderConfig provider_config; TestUtility::loadFromYaml(provider_config_yaml, provider_config); NiceMock context; - EXPECT_CALL(context, messageValidationVisitor()); MaxmindProviderFactory factory; EXPECT_THROW_WITH_MESSAGE(factory.createGeoipProviderDriver(provider_config, "maxmind", context), Envoy::EnvoyException, @@ -244,7 +267,7 @@ TEST(MaxmindProviderConfigTest, ProviderConfigWithNoDbPaths) { "city_db_path, isp_db_path or anon_db_path"); } -TEST(MaxmindProviderConfigTest, ProviderConfigWithNoGeoHeaders) { +TEST_F(MaxmindProviderConfigTest, ProviderConfigWithNoGeoHeaders) { std::string provider_config_yaml = R"EOF( isp_db_path: "/geoip2/Isp.mmdb" )EOF"; @@ -258,7 +281,7 @@ TEST(MaxmindProviderConfigTest, ProviderConfigWithNoGeoHeaders) { "Proto constraint validation failed.*value is required.*"); } -TEST(MaxmindProviderConfigTest, DbPathFormatValidatedWhenNonEmptyValue) { +TEST_F(MaxmindProviderConfigTest, DbPathFormatValidatedWhenNonEmptyValue) { std::string provider_config_yaml = R"EOF( isp_db_path: "/geoip2/Isp.exe" )EOF"; @@ -273,7 +296,7 @@ TEST(MaxmindProviderConfigTest, DbPathFormatValidatedWhenNonEmptyValue) { "Proto constraint validation failed.*value does not match regex pattern.*"); } -TEST(MaxmindProviderConfigTest, ReusesProviderInstanceForSameProtoConfig) { +TEST_F(MaxmindProviderConfigTest, ReusesProviderInstanceForSameProtoConfig) { const auto provider_config_yaml = R"EOF( common_provider_config: geo_headers_to_add: @@ -295,17 +318,15 @@ TEST(MaxmindProviderConfigTest, ReusesProviderInstanceForSameProtoConfig) { auto processed_provider_config_yaml = absl::StrFormat(provider_config_yaml, city_db_path, asn_db_path, anon_db_path); TestUtility::loadFromYaml(processed_provider_config_yaml, provider_config); - NiceMock context; - EXPECT_CALL(context, messageValidationVisitor()).Times(2); MaxmindProviderFactory factory; Geolocation::DriverSharedPtr driver1 = - factory.createGeoipProviderDriver(provider_config, "maxmind", context); + factory.createGeoipProviderDriver(provider_config, "maxmind", context_); Geolocation::DriverSharedPtr driver2 = - factory.createGeoipProviderDriver(provider_config, "maxmind", context); + factory.createGeoipProviderDriver(provider_config, "maxmind", context_); EXPECT_EQ(driver1.get(), driver2.get()); } -TEST(MaxmindProviderConfigTest, DifferentProviderInstancesForDifferentProtoConfig) { +TEST_F(MaxmindProviderConfigTest, DifferentProviderInstancesForDifferentProtoConfig) { const auto provider_config_yaml1 = R"EOF( common_provider_config: geo_headers_to_add: @@ -343,13 +364,11 @@ TEST(MaxmindProviderConfigTest, DifferentProviderInstancesForDifferentProtoConfi absl::StrFormat(provider_config_yaml2, city_db_path, anon_db_path); TestUtility::loadFromYaml(processed_provider_config_yaml1, provider_config1); TestUtility::loadFromYaml(processed_provider_config_yaml2, provider_config2); - NiceMock context; - EXPECT_CALL(context, messageValidationVisitor()).Times(2); MaxmindProviderFactory factory; Geolocation::DriverSharedPtr driver1 = - factory.createGeoipProviderDriver(provider_config1, "maxmind", context); + factory.createGeoipProviderDriver(provider_config1, "maxmind", context_); Geolocation::DriverSharedPtr driver2 = - factory.createGeoipProviderDriver(provider_config2, "maxmind", context); + factory.createGeoipProviderDriver(provider_config2, "maxmind", context_); EXPECT_NE(driver1.get(), driver2.get()); } diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 0b49b72e0d96..1d4eae7932ed 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -9,12 +9,14 @@ #include "test/mocks/server/factory_context.h" #include "test/mocks/stats/mocks.h" #include "test/test_common/environment.h" +#include "test/test_common/test_runtime.h" #include "test/test_common/utility.h" #include "gmock/gmock.h" #include "gtest/gtest.h" using testing::_; +using testing::InvokeWithoutArgs; using testing::NiceMock; using testing::ReturnRef; using testing::SaveArg; @@ -30,25 +32,99 @@ class GeoipProviderPeer { auto provider = std::static_pointer_cast(driver); return provider->config_->getStatsScopeForTest(); } + static Thread::ThreadSynchronizer& synchronizer(const DriverSharedPtr& driver) { + auto provider = std::static_pointer_cast(driver); + return provider->synchronizer_; + } }; -class GeoipProviderTest : public testing::Test { +namespace { +const std::string default_city_db_path = + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb"; + +const std::string default_updated_city_db_path = + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test-Updated.mmdb"; + +const std::string default_city_config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + )EOF"; + +const std::string default_isp_db_path = + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb"; + +const std::string default_updated_isp_db_path = + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test-Updated.mmdb"; + +const std::string default_isp_config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + asn: "x-geo-asn" + isp_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb" + )EOF"; + +const std::string default_anon_db_path = + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb"; + +const std::string default_updated_anon_db_path = + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test-Updated.mmdb"; + +const std::string default_anon_config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + is_anon: "x-geo-anon" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + )EOF"; +} // namespace + +class GeoipProviderTestBase { public: - GeoipProviderTest() { + GeoipProviderTestBase() : api_(Api::createApiForTest(stats_store_)) { provider_factory_ = dynamic_cast( Registry::FactoryRegistry::getFactory( "envoy.geoip_providers.maxmind")); ASSERT(provider_factory_); } + ~GeoipProviderTestBase() { + absl::WriterMutexLock lock(&mutex_); + on_changed_cbs_.clear(); + }; + void initializeProvider(const std::string& yaml) { EXPECT_CALL(context_, scope()).WillRepeatedly(ReturnRef(*scope_)); + EXPECT_CALL(context_, serverFactoryContext()) + .WillRepeatedly(ReturnRef(server_factory_context_)); + EXPECT_CALL(server_factory_context_, api()).WillRepeatedly(ReturnRef(*api_)); + EXPECT_CALL(dispatcher_, createFilesystemWatcher_()).WillRepeatedly(InvokeWithoutArgs([this] { + Filesystem::MockWatcher* mock_watcher = new NiceMock(); + EXPECT_CALL(*mock_watcher, addWatch(_, Filesystem::Watcher::Events::MovedTo, _)) + .WillRepeatedly( + Invoke([this](absl::string_view, uint32_t, Filesystem::Watcher::OnChangedCb cb) { + absl::WriterMutexLock lock(&mutex_); + on_changed_cbs_.emplace_back(std::move(cb)); + return absl::OkStatus(); + })); + return mock_watcher; + })); + EXPECT_CALL(server_factory_context_, mainThreadDispatcher()) + .WillRepeatedly(ReturnRef(dispatcher_)); envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig config; TestUtility::loadFromYaml(TestEnvironment::substitute(yaml), config); provider_ = provider_factory_->createGeoipProviderDriver(config, "prefix.", context_); } - void expectStats(const std::string& db_type, const uint32_t total_count = 1, + void expectStats(const absl::string_view& db_type, const uint32_t total_count = 1, const uint32_t hit_count = 1, const uint32_t error_count = 0) { auto& provider_scope = GeoipProviderPeer::providerScope(provider_); EXPECT_EQ(provider_scope.counterFromString(absl::StrCat(db_type, ".total")).value(), @@ -58,14 +134,31 @@ class GeoipProviderTest : public testing::Test { error_count); } + void expectReloadStats(const absl::string_view& db_type, const uint32_t reload_success_count = 0, + const uint32_t reload_error_count = 0) { + auto& provider_scope = GeoipProviderPeer::providerScope(provider_); + EXPECT_EQ(provider_scope.counterFromString(absl::StrCat(db_type, ".db_reload_success")).value(), + reload_success_count); + EXPECT_EQ(provider_scope.counterFromString(absl::StrCat(db_type, ".db_reload_error")).value(), + reload_error_count); + } + + Event::MockDispatcher dispatcher_; Stats::IsolatedStoreImpl stats_store_; Stats::ScopeSharedPtr scope_{stats_store_.createScope("")}; + Api::ApiPtr api_; + NiceMock server_factory_context_; NiceMock context_; DriverSharedPtr provider_; MaxmindProviderFactory* provider_factory_; + Event::SimulatedTimeSystem time_system_; absl::flat_hash_map captured_lookup_response_; + absl::Mutex mutex_; + std::vector on_changed_cbs_ ABSL_GUARDED_BY(mutex_); }; +class GeoipProviderTest : public testing::Test, public GeoipProviderTestBase {}; + TEST_F(GeoipProviderTest, ValidConfigCityAndIspDbsSuccessfulLookup) { const std::string config_yaml = R"EOF( common_provider_config: @@ -217,13 +310,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonProxySuccessfulLookup) { } TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { - const std::string config_yaml = R"EOF( - common_provider_config: - geo_headers_to_add: - is_anon: "x-geo-anon" - anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" - )EOF"; - initializeProvider(config_yaml); + initializeProvider(default_anon_config_yaml); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("10.10.10.10"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -236,15 +323,7 @@ TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { } TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { - const std::string config_yaml = R"EOF( - common_provider_config: - geo_headers_to_add: - country: "x-geo-country" - region: "x-geo-region" - city: "x-geo-city" - city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" - )EOF"; - initializeProvider(config_yaml); + initializeProvider(default_city_config_yaml); Network::Address::InstanceConstSharedPtr remote_address1 = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); Geolocation::LookupRequest lookup_rq1{std::move(remote_address1)}; @@ -265,28 +344,110 @@ TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { expectStats("city_db", 2, 2); } -using GeoipProviderDeathTest = GeoipProviderTest; +TEST_F(GeoipProviderTest, DbReloadedOnMmdbFileUpdate) { + constexpr absl::string_view config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + city_db_path: {} + )EOF"; + std::string city_db_path = TestEnvironment::substitute( + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb"); + std::string reloaded_city_db_path = TestEnvironment::substitute( + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test-Updated.mmdb"); + const std::string formatted_config = + fmt::format(config_yaml, TestEnvironment::substitute(city_db_path)); + initializeProvider(formatted_config); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(3, captured_lookup_response_.size()); + const auto& city_it = captured_lookup_response_.find("x-geo-city"); + EXPECT_EQ("Boxford", city_it->second); + TestEnvironment::renameFile(city_db_path, city_db_path + "1"); + TestEnvironment::renameFile(reloaded_city_db_path, city_db_path); + { + absl::MutexLock guard(&mutex_); + EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); + } + expectReloadStats("city_db", 1, 0); + captured_lookup_response_.clear(); + EXPECT_EQ(0, captured_lookup_response_.size()); + remote_address = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); + Geolocation::LookupRequest lookup_rq2{std::move(remote_address)}; + testing::MockFunction lookup_cb2; + auto lookup_cb_std2 = lookup_cb2.AsStdFunction(); + EXPECT_CALL(lookup_cb2, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq2), std::move(lookup_cb_std2)); + const auto& city1_it = captured_lookup_response_.find("x-geo-city"); + EXPECT_EQ("BoxfordImaginary", city1_it->second); + // Clean up modifications to mmdb file names. + TestEnvironment::renameFile(city_db_path, reloaded_city_db_path); + TestEnvironment::renameFile(city_db_path + "1", city_db_path); +} -TEST_F(GeoipProviderDeathTest, GeoDbNotSetForConfiguredHeader) { - const std::string config_yaml = R"EOF( +TEST_F(GeoipProviderTest, DbReloadError) { + constexpr absl::string_view config_yaml = R"EOF( common_provider_config: geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" city: "x-geo-city" - asn: "x-geo-asn" - city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + city_db_path: {} )EOF"; - initializeProvider(config_yaml); + std::string city_db_path = TestEnvironment::substitute( + "{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb"); + std::string reloaded_invalid_city_db_path = + TestEnvironment::substitute("{{ test_rundir " + "}}/test/extensions/geoip_providers/maxmind/test_data/" + "libmaxminddb-offset-integer-overflow.mmdb"); + const std::string formatted_config = + fmt::format(config_yaml, TestEnvironment::substitute(city_db_path)); + initializeProvider(formatted_config); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; testing::MockFunction lookup_cb; auto lookup_cb_std = lookup_cb.AsStdFunction(); EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); - EXPECT_DEATH(provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)), - "assert failure: isp_db_. Details: Maxmind asn database is not initialized for " - "performing lookups"); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(3, captured_lookup_response_.size()); + const auto& city_it = captured_lookup_response_.find("x-geo-city"); + EXPECT_EQ("Boxford", city_it->second); + TestEnvironment::renameFile(city_db_path, city_db_path + "1"); + TestEnvironment::renameFile(reloaded_invalid_city_db_path, city_db_path); + { + absl::MutexLock guard(&mutex_); + EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); + } + // On mmdb reload error the old mmdb instance should be used for subsequent lookup requests. + expectReloadStats("city_db", 0, 1); + captured_lookup_response_.clear(); + EXPECT_EQ(0, captured_lookup_response_.size()); + remote_address = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); + Geolocation::LookupRequest lookup_rq2{std::move(remote_address)}; + testing::MockFunction lookup_cb2; + auto lookup_cb_std2 = lookup_cb2.AsStdFunction(); + EXPECT_CALL(lookup_cb2, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq2), std::move(lookup_cb_std2)); + const auto& city1_it = captured_lookup_response_.find("x-geo-city"); + EXPECT_EQ("Boxford", city1_it->second); + // Clean up modifications to mmdb file names. + TestEnvironment::renameFile(city_db_path, reloaded_invalid_city_db_path); + TestEnvironment::renameFile(city_db_path + "1", city_db_path); } +using GeoipProviderDeathTest = GeoipProviderTest; + TEST_F(GeoipProviderDeathTest, GeoDbPathDoesNotExist) { const std::string config_yaml = R"EOF( common_provider_config: @@ -297,6 +458,228 @@ TEST_F(GeoipProviderDeathTest, GeoDbPathDoesNotExist) { EXPECT_DEATH(initializeProvider(config_yaml), ".*Unable to open Maxmind database file.*"); } +struct GeoipProviderGeoDbNotSetTestCase { + GeoipProviderGeoDbNotSetTestCase() = default; + GeoipProviderGeoDbNotSetTestCase(const std::string& yaml_config, const std::string& db_type) + : yaml_config_(yaml_config), db_type_(db_type) {} + GeoipProviderGeoDbNotSetTestCase(const GeoipProviderGeoDbNotSetTestCase& rhs) = default; + + std::string yaml_config_; + std::string db_type_; +}; + +class GeoipProviderGeoDbNotSetDeathTest + : public ::testing::TestWithParam, + public GeoipProviderTestBase {}; + +TEST_P(GeoipProviderGeoDbNotSetDeathTest, GeoDbNotSetForConfiguredHeader) { + GeoipProviderGeoDbNotSetTestCase test_case = GetParam(); + initializeProvider(test_case.yaml_config_); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + EXPECT_ENVOY_BUG( + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)), + fmt::format("envoy bug failure: false. Details: Maxmind {} database must be initialised for " + "performing lookups", + test_case.db_type_)); +} + +struct GeoipProviderGeoDbNotSetTestCase geo_db_not_set_test_cases[] = { + { + R"EOF( + common_provider_config: + geo_headers_to_add: + city: "x-geo-city" + asn: "x-geo-asn" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + )EOF", + "asn"}, + { + R"EOF( + common_provider_config: + geo_headers_to_add: + city: "x-geo-city" + asn: "x-geo-asn" + isp_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb" + )EOF", + "city"}, + { + R"EOF( + common_provider_config: + geo_headers_to_add: + is_anon: "x-geo-anon" + asn: "x-geo-asn" + isp_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb" + )EOF", + "anon"}, +}; + +INSTANTIATE_TEST_SUITE_P(TestName, GeoipProviderGeoDbNotSetDeathTest, + ::testing::ValuesIn(geo_db_not_set_test_cases)); + +struct MmdbReloadTestCase { + + MmdbReloadTestCase() = default; + MmdbReloadTestCase(const std::string& yaml_config, const std::string& db_type, + const std::string& source_db_file_path, + const std::string& reloaded_db_file_path, + const std::string& expected_header_name, + const std::string& expected_header_value, + const std::string& expected_reloaded_header_value, const std::string& ip) + : yaml_config_(yaml_config), db_type_(db_type), source_db_file_path_(source_db_file_path), + reloaded_db_file_path_(reloaded_db_file_path), expected_header_name_(expected_header_name), + expected_header_value_(expected_header_value), + expected_reloaded_header_value_(expected_reloaded_header_value), ip_(ip) {} + MmdbReloadTestCase(const MmdbReloadTestCase& rhs) = default; + + std::string yaml_config_; + std::string db_type_; + std::string source_db_file_path_; + std::string reloaded_db_file_path_; + std::string expected_header_name_; + std::string expected_header_value_; + std::string expected_reloaded_header_value_; + std::string ip_; +}; + +class MmdbReloadImplTest : public ::testing::TestWithParam, + public GeoipProviderTestBase {}; + +TEST_P(MmdbReloadImplTest, MmdbReloaded) { + MmdbReloadTestCase test_case = GetParam(); + initializeProvider(test_case.yaml_config_); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddressNoThrow(test_case.ip_); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + const auto& geoip_header_it = captured_lookup_response_.find(test_case.expected_header_name_); + EXPECT_EQ(test_case.expected_header_value_, geoip_header_it->second); + expectStats(test_case.db_type_, 1, 1); + std::string source_db_file_path = TestEnvironment::substitute(test_case.source_db_file_path_); + std::string reloaded_db_file_path = TestEnvironment::substitute(test_case.reloaded_db_file_path_); + TestEnvironment::renameFile(source_db_file_path, source_db_file_path + "1"); + TestEnvironment::renameFile(reloaded_db_file_path, source_db_file_path); + { + absl::MutexLock guard(&mutex_); + EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); + } + expectReloadStats(test_case.db_type_, 1, 0); + captured_lookup_response_.clear(); + remote_address = Network::Utility::parseInternetAddressNoThrow(test_case.ip_); + Geolocation::LookupRequest lookup_rq2{std::move(remote_address)}; + testing::MockFunction lookup_cb2; + auto lookup_cb_std2 = lookup_cb2.AsStdFunction(); + EXPECT_CALL(lookup_cb2, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq2), std::move(lookup_cb_std2)); + const auto& geoip_header1_it = captured_lookup_response_.find(test_case.expected_header_name_); + EXPECT_EQ(test_case.expected_reloaded_header_value_, geoip_header1_it->second); + // Clean up modifications to mmdb file names. + TestEnvironment::renameFile(source_db_file_path, reloaded_db_file_path); + TestEnvironment::renameFile(source_db_file_path + "1", source_db_file_path); +} + +TEST_P(MmdbReloadImplTest, MmdbReloadedInFlightReadsNotAffected) { + MmdbReloadTestCase test_case = GetParam(); + initializeProvider(test_case.yaml_config_); + GeoipProviderPeer::synchronizer(provider_).enable(); + const auto lookup_sync_point_name = test_case.db_type_.append("_lookup_pre_complete"); + // Start a thread that performs geoip lookup and wait in the worker thread right after reading the + // copy of mmdb instance. + GeoipProviderPeer::synchronizer(provider_).waitOn(lookup_sync_point_name); + std::thread t0([&] { + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddressNoThrow(test_case.ip_); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + const auto& geoip_header_it = captured_lookup_response_.find(test_case.expected_header_name_); + EXPECT_EQ(test_case.expected_header_value_, geoip_header_it->second); + // Second lookup should read the updated value. + captured_lookup_response_.clear(); + remote_address = Network::Utility::parseInternetAddressNoThrow(test_case.ip_); + Geolocation::LookupRequest lookup_rq2{std::move(remote_address)}; + testing::MockFunction lookup_cb2; + auto lookup_cb_std2 = lookup_cb2.AsStdFunction(); + EXPECT_CALL(lookup_cb2, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq2), std::move(lookup_cb_std2)); + const auto& geoip_header1_it = captured_lookup_response_.find(test_case.expected_header_name_); + EXPECT_EQ(test_case.expected_reloaded_header_value_, geoip_header1_it->second); + }); + // Wait until the thread is actually waiting. + GeoipProviderPeer::synchronizer(provider_).barrierOn(lookup_sync_point_name); + std::string source_db_file_path = TestEnvironment::substitute(test_case.source_db_file_path_); + std::string reloaded_db_file_path = TestEnvironment::substitute(test_case.reloaded_db_file_path_); + TestEnvironment::renameFile(source_db_file_path, source_db_file_path + "1"); + TestEnvironment::renameFile(reloaded_db_file_path, source_db_file_path); + { + absl::MutexLock guard(&mutex_); + EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); + } + GeoipProviderPeer::synchronizer(provider_).signal(lookup_sync_point_name); + t0.join(); + // Clean up modifications to mmdb file names. + TestEnvironment::renameFile(source_db_file_path, reloaded_db_file_path); + TestEnvironment::renameFile(source_db_file_path + "1", source_db_file_path); +} + +TEST_P(MmdbReloadImplTest, MmdbNotReloadedRuntimeFeatureDisabled) { + TestScopedRuntime scoped_runtime_; + scoped_runtime_.mergeValues({{"envoy.reloadable_features.mmdb_files_reload_enabled", "false"}}); + MmdbReloadTestCase test_case = GetParam(); + initializeProvider(test_case.yaml_config_); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddressNoThrow(test_case.ip_); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + const auto& geoip_header_it = captured_lookup_response_.find(test_case.expected_header_name_); + EXPECT_EQ(test_case.expected_header_value_, geoip_header_it->second); + expectStats(test_case.db_type_, 1, 1); + std::string source_db_file_path = TestEnvironment::substitute(test_case.source_db_file_path_); + std::string reloaded_db_file_path = TestEnvironment::substitute(test_case.reloaded_db_file_path_); + TestEnvironment::renameFile(source_db_file_path, source_db_file_path + "1"); + TestEnvironment::renameFile(reloaded_db_file_path, source_db_file_path); + { + absl::MutexLock guard(&mutex_); + EXPECT_EQ(0, on_changed_cbs_.size()); + } + expectReloadStats(test_case.db_type_, 0, 0); + captured_lookup_response_.clear(); + remote_address = Network::Utility::parseInternetAddressNoThrow(test_case.ip_); + Geolocation::LookupRequest lookup_rq2{std::move(remote_address)}; + testing::MockFunction lookup_cb2; + auto lookup_cb_std2 = lookup_cb2.AsStdFunction(); + EXPECT_CALL(lookup_cb2, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq2), std::move(lookup_cb_std2)); + const auto& geoip_header1_it = captured_lookup_response_.find(test_case.expected_header_name_); + EXPECT_EQ(test_case.expected_header_value_, geoip_header1_it->second); + // Clean up modifications to mmdb file names. + TestEnvironment::renameFile(source_db_file_path, reloaded_db_file_path); + TestEnvironment::renameFile(source_db_file_path + "1", source_db_file_path); +} + +struct MmdbReloadTestCase mmdb_reload_test_cases[] = { + {default_city_config_yaml, "city_db", default_city_db_path, default_updated_city_db_path, + "x-geo-city", "Boxford", "BoxfordImaginary", "78.26.243.166"}, + {default_isp_config_yaml, "isp_db", default_isp_db_path, default_updated_isp_db_path, + "x-geo-asn", "15169", "77777", "78.26.243.166"}, + {default_anon_config_yaml, "anon_db", default_anon_db_path, default_updated_anon_db_path, + "x-geo-anon", "true", "false", "65.4.3.2"}, +}; + +INSTANTIATE_TEST_SUITE_P(TestName, MmdbReloadImplTest, ::testing::ValuesIn(mmdb_reload_test_cases)); + } // namespace Maxmind } // namespace GeoipProviders } // namespace Extensions diff --git a/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test-Updated.mmdb b/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test-Updated.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..0fc9cf03ad44731656bacdc9416936256fd94e19 GIT binary patch literal 4374 zcmZA32Y3|K8piSW41uNhUWZWnKorHyCXW8Av1V!wk-fO$|3S!6J zd%=!k@0Fq`dau}fJ2U@e=U(&Vd47D~`A(gg93&%|`y|Ky?klyh(OFUvQA=nAF=%Z| z4w2drwS{)j9y&lr=medi3v`8U&>ea}Pv`}`p%3(he$XEVz(5!TE)0etFcgNta2Nq2 zVHAvpF)$X!K{1Sn9bf`Xgh{X?>;yZ*F0d=?2D`%^uqW&Vd&53pA5-wCCc_k%3e#XZ z><9b94EP6>z)UEGSx^SEVGfkT0rv6RAr2&(3-jP0I2i0p60Gx3I1CPl`EUd*fFmIe z3n3xtDXGG8np8M4TuJv;(&{LA70ESlHCz+otdy=}l)K{zBxeksh?WeO!8|kkrG{BlLR|9xJrjXAw@j4xWG~*_eG! zPus!1B>9Z=tc~6!dQMtzqt~V93xnwe+BU$8@DjWXufVJDTH$4QgO$ArZ^7H}PDrrM z=HI4V-0Yi zg&n$$Oc7B_XazB79n$puHDTJ3w7W6w!%dkEG9BsA2|7cUsIn`S-DJAc)&qJ*CB4ED zJB#TPCHuIn3Autq%*|t%X43`-}a%4!*&(0TiA1yP6 zwy}jaGmf@mnekDwslx=BiFBA0we2Xg6A>#jyF_ifGT3f1yVGwE*c0}GyJdnFpg$9+G)DiXNflQFsg%k58j6l;6wNbHo_*@3|ru1_yo4Xr|=nUgU{g$ zuy>dcc}#w zK}%=_F=!2Kpe?k6_Rs-3LMP}9U7#y;gYM7+dO|Pg4Sk?5^n?B|00zP!aA7bEfuS%A zhQkQpEwHB`hr7`k9lqYq7#JJ=H^s5{U$HIW#&gD#w4MI{XXEBssa!mf_S22EeqGMQ z%KtZv*Jsiuw#9W!%;VzFISy_e0U{Pb$)@2#nH)Viv)qApdFjC&cs za#4{}HSMhlWywT7QIW`b@qA;(n>)kvOUfq|Pia1q;*#>xq?fDArZRau{HCd1dch=$ z+(MCCQtr<4a(Q=p(^&4Ps>Bk{ZK?}q80Xs6x?V$~HdEudnYwJo&v`l5PuDb#o|(!N tmfxzRCXueLOH_L~Q{*n68Ju&x(yvSB*Eu_sX1z*3n~djD%e>Y7{{m0VGgklr literal 0 HcmV?d00001 diff --git a/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test-Updated.mmdb b/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test-Updated.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..c8b6fe84663210c5d3e8e8b7a2c8311a84619d25 GIT binary patch literal 12662 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 Q3Kg5`Xidla{Z*s?7fbf^>;M1& literal 0 HcmV?d00001 diff --git a/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test-Updated.mmdb b/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test-Updated.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..58b6aa62baa075f6339ffa6f0b1faa06edcbea42 GIT binary patch literal 3461 zcmZA233wFc8Nl&(BZ~KJJWBM#qXs0PC|=bHn=Hv@a~Xk%fXifOvYD_uvz^_gBrPq? z7PU<+1)JK|R!yswqGF(60YR$twzivIwAHrCk`&rnd*9bL^M_s9JkLJAec$hUzjHPt z5)ug|MXEFzk>fOP7nwwKJe&ZN;Y5wjoJ4dooC2r9X>dB60cXNla5kI+=fZhV4d=rJ za3Nd-Z-FUL0~f<3pkOLo3YWp-u7p~c2Gijxm;rS#6K28Ha1G3cYvDSW1J}b1 za3kCVH^bZD7PuAk#rSu08_b1y5QchafC$WoMreX4G(!wppcUGn9XjB45&4TqC(#|S z02aa`=z=?8G28`9U@0tvyCDwC!O-*FC(^BXw@8Ad36@Uwi}Vobr&xM}6Y@{VCfNro zAO&e~zzy(gM1S5v(t|AIAP+0yodH4JDyCf{GEhmr>*!j7E~`b}qi1-($a^bYbiw-= zY!C|NHeD3dt%ZBw-lJp62lQZ{Ciy{;p>mykNaTLq_MpgzE6H{A{0OXv4e$Vb6o%nr z0saa;&dNRkpM;0tQvrT2|MM_B0*~rN926PRd|Tu*BtHv}>Ezc$9@p#?`5eh7U?Y4U zHo=qd6g&-^;Taf(EwEJ&y+h;+MB89HJPTh8II{Sod)QS@%5$8=Zjn6{JP&)}OO>84 z(DOx+eYAZUzEbJ()$)0My^{Qf$Tus|OCsN*?&We)FUwzoD)Q4x@@FJ}F7g@$uUFa*h?L5aKm2$(k_qa5A##Yi z!|+S^75p0BfZxEI@Y{f3x4&bs-@_k7{z#WU!Jo@Lb?>0yukbhcJNyIw3IBqB!+!!o zj28+KRl#vE362kt z6Wk2E|3bGA-3t1N^Dq21m<#hD4E4|e5#aq7Y9wlcC^Tz&xapXLT1d7+8?-}*W{HGu zC+dVdU;!+IMbHIz!eY29KtE2wR{R|;mC&+EbT?~>OX!#`2FY$nNXVqXs?_O`jwv|u z8nh|sgB6g1w1k{Wxl2-y^1pu*4GBBff1o*OxsH*x;UJ;RQXDRB9a~d;zPPtI8X4%Vt8be>@zfI& z+qO0)+`NxakMV4pTj-AZusbc${)!%fS=v6gs3mrRW znJQ*GNz+ZM<*`oP(N#Kay2^@my8T8zZPn>m^|h1+A1e)RE)_PF26w8}>J7DaX>mhw zd-1vAj^Zx8t}S|XJH`f!qs2Yib!vG2p`k6~5AA76xd|g@yUxLOBaz5^MxsCN8K#}j zj+jj;-IB|jR`1;CYr(-sQ?8RFwO9Ys^Z%kbTOa&@>sYP9;aRgS9t}7f<)g^scT~;=y!j`up+iUAiYnN3OAJm)G*HPS7+%q;* z+^LG|i`(@n>>9gIpTHV5+;Zsgy$5$cGro4{aAD-hm)~qPR<+uWIWys=4=?Es9+$X& zc+y5Lo;LbiFTT?9{DqHH{eP>zmU8Q(vF^N`GUHapP4rHxvi9%a&}tevqua<@@mzn# ziZxnpv}1N%y?%0Irj<>2cE-Pe1NwPgHl0T0H>w5xo*ItSs@fi7g{6+P`y + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MaxMind-DB/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb at main · maxmind/MaxMind-DB · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ Skip to content + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + + + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + / + + MaxMind-DB + + + Public +
+ + +
+ +
+ + +
+
+ +
+
+ + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + +

Latest commit

 

History

History
412 Bytes

libmaxminddb-offset-integer-overflow.mmdb

File metadata and controls

412 Bytes
+
+ + + + +
+ +
+ +
+
+ +
+ +
+

Footer

+ + + + +
+
+ + + + + © 2024 GitHub, Inc. + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + +
+ +
+
+ + From 6277f4601357550b0eba93fa3fd2a4154d63416b Mon Sep 17 00:00:00 2001 From: Nigel Brittain <108375408+nbaws@users.noreply.github.com> Date: Fri, 23 Aug 2024 06:35:26 +1000 Subject: [PATCH 17/53] aws: flip async provider runtime guard to default true (#35747) Signed-off-by: Nigel Brittain --- changelogs/current.yaml | 4 +++ .../http_filters/_include/aws_credentials.rst | 23 ++++++++------- source/common/runtime/runtime_features.cc | 6 +--- .../aws/credentials_provider_impl_test.cc | 17 +++++------ .../aws_request_signing_integration_test.cc | 28 ++----------------- 5 files changed, 27 insertions(+), 51 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index c0e1c53809ad..cb4c0defc775 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -66,6 +66,10 @@ minor_behavior_changes: When computing SNI and SAN value for the auto-sni and auto-san verification feature, route host manipulations are now taken into account. This behavior can be reverted by setting the runtime guard ``envoy_reloadable_features_use_route_host_mutation_for_auto_sni_san`` to false. +- area: aws + change: | + Aws request signing common code uses http async client by default, moving curl to deprecation path. This behavior change can be + reverted by setting the ``envoy_reloadable_features_use_http_client_to_fetch_aws_credentials`` runtime flag to ``false``. bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* diff --git a/docs/root/configuration/http/http_filters/_include/aws_credentials.rst b/docs/root/configuration/http/http_filters/_include/aws_credentials.rst index 99dfc80efb4a..eac00b89262f 100644 --- a/docs/root/configuration/http/http_filters/_include/aws_credentials.rst +++ b/docs/root/configuration/http/http_filters/_include/aws_credentials.rst @@ -15,11 +15,11 @@ secret access key (the session token is optional). towards AWS Security Token Service using ``WebIdentityToken`` read from a file pointed by ``AWS_WEB_IDENTITY_TOKEN_FILE`` environment variable and role arn read from ``AWS_ROLE_ARN`` environment variable. The credentials are extracted from the fields ``AccessKeyId``, ``SecretAccessKey``, and ``SessionToken`` are used, and credentials are cached for 1 hour or until they expire (according to the field - ``Expiration``). To enable this credentials provider set ``envoy.reloadable_features.use_http_client_to_fetch_aws_credentials`` to ``true`` - so that it can use http async client to fetch the credentials. This provider is not compatible with :ref:`Grpc Credentials AWS AwsIamConfig - ` plugin which can only support deprecated libcurl credentials - fetcher (see `issue #30626 `_). To fetch the credentials a static cluster is created with the name - ``sts_token_service_internal-`` pointing towards regional AWS Security Token Service. + ``Expiration``). + This provider is not compatible with :ref:`Grpc Credentials AWS AwsIamConfig ` + plugin which can only support deprecated libcurl credentials fetcher (see `issue #30626 `_). + To fetch the credentials a static cluster is created with the name ``sts_token_service_internal-`` pointing towards regional + AWS Security Token Service. Note: If ``signing_algorithm: AWS_SIGV4A`` is set, the logic for STS cluster host generation is as follows: - If the ``region`` is configured (either through profile, environment or inline) as a SigV4A region set @@ -38,19 +38,18 @@ secret access key (the session token is optional). containing the string required in the Authorization header sent to the EKS Pod Identity Agent. The fields ``AccessKeyId``, ``SecretAccessKey``, and ``Token`` are used, and credentials are cached for 1 hour or until they expire (according to the field ``Expiration``). Note that the latest update on AWS credentials provider utility provides an option to use http async client functionality instead of libcurl - to fetch the credentials. This behavior can be changed by setting ``envoy.reloadable_features.use_http_client_to_fetch_aws_credentials`` to ``true``. - The usage of libcurl is on the deprecation path and will be removed soon. To fetch the credentials from either EC2 instance - metadata or ECS task metadata a static cluster is required pointing towards the credentials provider. The static cluster name has to be - ``ec2_instance_metadata_server_internal`` for fetching from EC2 instance metadata or ``ecs_task_metadata_server_internal`` for fetching - from ECS task metadata. If these clusters are not provided in the bootstrap configuration then either of these will be added by default. + to fetch the credentials. To fetch the credentials from either EC2 instance metadata or ECS task metadata a static cluster pointing + towards the credentials provider is required. The static cluster name has to be ``ec2_instance_metadata_server_internal`` for fetching from EC2 instance + metadata or ``ecs_task_metadata_server_internal`` for fetching from ECS task metadata. + + If these clusters are not provided in the bootstrap configuration then either of these will be added by default. The static internal cluster will still be added even if initially ``envoy.reloadable_features.use_http_client_to_fetch_aws_credentials`` is not set so that subsequently if the reloadable feature is set to ``true`` the cluster config is available to fetch the credentials. Statistics ---------- -When using the ``envoy.reloadable_features.use_http_client_to_fetch_aws_credentials`` reloadable feature, the following -statistics are output under the ``aws.metadata_credentials_provider`` namespace: +The following statistics are output under the ``aws.metadata_credentials_provider`` namespace: .. csv-table:: :header: Name, Type, Description diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 7089ef8daa47..1acdd3d55a31 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -93,6 +93,7 @@ RUNTIME_GUARD(envoy_reloadable_features_uhv_allow_malformed_url_encoding); RUNTIME_GUARD(envoy_reloadable_features_upstream_remote_address_use_connection); RUNTIME_GUARD(envoy_reloadable_features_use_config_in_happy_eyeballs); RUNTIME_GUARD(envoy_reloadable_features_use_http3_header_normalisation); +RUNTIME_GUARD(envoy_reloadable_features_use_http_client_to_fetch_aws_credentials); RUNTIME_GUARD(envoy_reloadable_features_use_route_host_mutation_for_auto_sni_san); RUNTIME_GUARD(envoy_reloadable_features_use_typed_metadata_in_proxy_protocol_listener); RUNTIME_GUARD(envoy_reloadable_features_validate_connect); @@ -127,11 +128,6 @@ FALSE_RUNTIME_GUARD(envoy_reloadable_features_always_use_v6); FALSE_RUNTIME_GUARD(envoy_restart_features_upstream_http_filters_with_tcp_proxy); // TODO(danzh) false deprecate it once QUICHE has its own enable/disable flag. FALSE_RUNTIME_GUARD(envoy_reloadable_features_quic_reject_all); -// TODO(suniltheta): Once the newly added http async technique is stabilized move it under -// RUNTIME_GUARD so that this option becomes default enabled. Once this option proves effective -// remove the feature flag and remove code path that relies on old technique to fetch credentials -// via libcurl and remove the bazel steps to pull and test the curl dependency. -FALSE_RUNTIME_GUARD(envoy_reloadable_features_use_http_client_to_fetch_aws_credentials); // TODO(#10646) change to true when UHV is sufficiently tested // For more information about Universal Header Validation, please see // https://github.com/envoyproxy/envoy/issues/10646 diff --git a/test/extensions/common/aws/credentials_provider_impl_test.cc b/test/extensions/common/aws/credentials_provider_impl_test.cc index 4db7d769046b..76a8472547b7 100644 --- a/test/extensions/common/aws/credentials_provider_impl_test.cc +++ b/test/extensions/common/aws/credentials_provider_impl_test.cc @@ -377,8 +377,6 @@ class InstanceProfileCredentialsProviderTest : public testing::Test { void setupProvider(MetadataFetcher::MetadataReceiver::RefreshState refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::Ready, std::chrono::seconds initialization_timer = std::chrono::seconds(2)) { - scoped_runtime_.mergeValues( - {{"envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"}}); ON_CALL(context_, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); provider_ = std::make_shared( @@ -1080,6 +1078,10 @@ class InstanceProfileCredentialsProviderUsingLibcurlTest : public testing::Test : api_(Api::createApiForTest(time_system_)) {} void setupProvider() { + + scoped_runtime_.mergeValues( + {{"envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "false"}}); + provider_ = std::make_shared( *api_, absl::nullopt, [this](Http::RequestMessage& message) -> absl::optional { @@ -1134,6 +1136,7 @@ class InstanceProfileCredentialsProviderUsingLibcurlTest : public testing::Test EXPECT_CALL(fetch_metadata_, fetch(messageMatches(headers))).WillOnce(Return(document)); } + TestScopedRuntime scoped_runtime_; Event::SimulatedTimeSystem time_system_; Api::ApiPtr api_; NiceMock fetch_metadata_; @@ -1400,8 +1403,6 @@ class ContainerCredentialsProviderTest : public testing::Test { void setupProvider(MetadataFetcher::MetadataReceiver::RefreshState refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::Ready, std::chrono::seconds initialization_timer = std::chrono::seconds(2)) { - scoped_runtime_.mergeValues( - {{"envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"}}); ON_CALL(context_, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); provider_ = std::make_shared( *api_, context_, @@ -1664,6 +1665,9 @@ class ContainerCredentialsProviderUsingLibcurlTest : public testing::Test { void setupProvider(MetadataFetcher::MetadataReceiver::RefreshState refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::Ready, std::chrono::seconds initialization_timer = std::chrono::seconds(2)) { + scoped_runtime_.mergeValues( + {{"envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "false"}}); + provider_ = std::make_shared( *api_, absl::nullopt, [this](Http::RequestMessage& message) -> absl::optional { @@ -1682,6 +1686,7 @@ class ContainerCredentialsProviderUsingLibcurlTest : public testing::Test { EXPECT_CALL(fetch_metadata_, fetch(messageMatches(headers))).WillOnce(Return(document)); } + TestScopedRuntime scoped_runtime_; Event::SimulatedTimeSystem time_system_; Api::ApiPtr api_; NiceMock fetch_metadata_; @@ -1826,8 +1831,6 @@ class ContainerEKSPodIdentityCredentialsProviderTest : public testing::Test { void setupProvider(MetadataFetcher::MetadataReceiver::RefreshState refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::Ready, std::chrono::seconds initialization_timer = std::chrono::seconds(2)) { - scoped_runtime_.mergeValues( - {{"envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"}}); ON_CALL(context_, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); provider_ = std::make_shared( *api_, context_, @@ -1950,8 +1953,6 @@ class WebIdentityCredentialsProviderTest : public testing::Test { void setupProvider(MetadataFetcher::MetadataReceiver::RefreshState refresh_state = MetadataFetcher::MetadataReceiver::RefreshState::Ready, std::chrono::seconds initialization_timer = std::chrono::seconds(2)) { - scoped_runtime_.mergeValues( - {{"envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"}}); ON_CALL(context_, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); provider_ = std::make_shared( *api_, context_, diff --git a/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc b/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc index ba0da9513745..6ddd2e81ffe1 100644 --- a/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc +++ b/test/extensions/filters/http/aws_request_signing/aws_request_signing_integration_test.cc @@ -74,8 +74,8 @@ class AwsRequestSigningIntegrationTest : public testing::TestWithParamwaitForCounterGe("aws.metadata_credentials_provider.sts_token_" @@ -370,8 +364,6 @@ TEST_F(InitializeFilterTest, TestWithOneClusterRouteLevelAndStandard) { TestEnvironment::setEnvVar("AWS_WEB_IDENTITY_TOKEN_FILE", "/path/to/web_token", 1); TestEnvironment::setEnvVar("AWS_ROLE_ARN", "aws:iam::123456789012:role/arn", 1); TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); addStandardFilter(); addPerRouteFilter(AWS_REQUEST_SIGNING_CONFIG_SIGV4_ROUTE_LEVEL); initialize(); @@ -389,8 +381,6 @@ TEST_F(InitializeFilterTest, TestWithTwoClustersStandard) { TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); TestEnvironment::setEnvVar("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", "/path/to/creds", 1); TestEnvironment::setEnvVar("AWS_CONTAINER_AUTHORIZATION_TOKEN", "auth_token", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); addStandardFilter(); initialize(); std::vector gauges = test_server_->gauges(); @@ -411,8 +401,6 @@ TEST_F(InitializeFilterTest, TestWithTwoClustersRouteLevel) { TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); TestEnvironment::setEnvVar("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", "/path/to/creds", 1); TestEnvironment::setEnvVar("AWS_CONTAINER_AUTHORIZATION_TOKEN", "auth_token", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); addPerRouteFilter(AWS_REQUEST_SIGNING_CONFIG_SIGV4_ROUTE_LEVEL); initialize(); test_server_->waitForCounterGe("aws.metadata_credentials_provider.ecs_task_" @@ -432,8 +420,6 @@ TEST_F(InitializeFilterTest, TestWithTwoClustersRouteLevelAndStandard) { TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); TestEnvironment::setEnvVar("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", "/path/to/creds", 1); TestEnvironment::setEnvVar("AWS_CONTAINER_AUTHORIZATION_TOKEN", "auth_token", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); addStandardFilter(); addPerRouteFilter(AWS_REQUEST_SIGNING_CONFIG_SIGV4_ROUTE_LEVEL); initialize(); @@ -451,8 +437,6 @@ TEST_F(InitializeFilterTest, TestWithTwoClustersStandardInstanceProfile) { TestEnvironment::setEnvVar("AWS_WEB_IDENTITY_TOKEN_FILE", "/path/to/web_token", 1); TestEnvironment::setEnvVar("AWS_ROLE_ARN", "aws:iam::123456789012:role/arn", 1); TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); addStandardFilter(); initialize(); test_server_->waitForCounterGe("aws.metadata_credentials_provider.ec2_instance_" @@ -469,8 +453,6 @@ TEST_F(InitializeFilterTest, TestWithTwoClustersRouteLevelInstanceProfile) { TestEnvironment::setEnvVar("AWS_WEB_IDENTITY_TOKEN_FILE", "/path/to/web_token", 1); TestEnvironment::setEnvVar("AWS_ROLE_ARN", "aws:iam::123456789012:role/arn", 1); TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); addPerRouteFilter(AWS_REQUEST_SIGNING_CONFIG_SIGV4_ROUTE_LEVEL); initialize(); test_server_->waitForCounterGe("aws.metadata_credentials_provider.ec2_instance_" @@ -487,8 +469,6 @@ TEST_F(InitializeFilterTest, TestWithTwoClustersRouteLevelAndStandardInstancePro TestEnvironment::setEnvVar("AWS_WEB_IDENTITY_TOKEN_FILE", "/path/to/web_token", 1); TestEnvironment::setEnvVar("AWS_ROLE_ARN", "aws:iam::123456789012:role/arn", 1); TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); addStandardFilter(); addPerRouteFilter(AWS_REQUEST_SIGNING_CONFIG_SIGV4_ROUTE_LEVEL); initialize(); @@ -560,8 +540,6 @@ TEST_F(CdsInteractionTest, ClusterRemovalRecreatesSTSCluster) { TestEnvironment::setEnvVar("AWS_WEB_IDENTITY_TOKEN_FILE", "/path/to/web_token", 1); TestEnvironment::setEnvVar("AWS_ROLE_ARN", "aws:iam::123456789012:role/arn", 1); TestEnvironment::setEnvVar("AWS_ROLE_SESSION_NAME", "role-session-name", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); CdsHelper cds_helper_; @@ -611,8 +589,6 @@ TEST_F(CdsInteractionTest, ClusterRemovalRecreatesSTSCluster) { TEST_F(CdsInteractionTest, ClusterRemovalRecreatesIMDSCluster) { // Instance Metadata Service only TestEnvironment::setEnvVar("AWS_EC2_METADATA_DISABLED", "false", 1); - config_helper_.addRuntimeOverride( - "envoy.reloadable_features.use_http_client_to_fetch_aws_credentials", "true"); CdsHelper cds_helper_; From e2a273f9be06099cba8e2feec3681d369338f0bf Mon Sep 17 00:00:00 2001 From: code Date: Fri, 23 Aug 2024 06:34:33 +0800 Subject: [PATCH 18/53] deps: update cpp2sky to v0.6.0 (#35768) Commit Message: deps: update cpp2sky to v0.6.0 Additional Description: To close #23032 Fix #35790 Risk Level: low. Testing: n/a. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping --- bazel/repository_locations.bzl | 6 ++-- .../skywalking/skywalking_tracer_impl.cc | 6 ++-- .../skywalking/skywalking_tracer_impl.h | 2 +- .../skywalking/trace_segment_reporter.cc | 2 +- .../skywalking/trace_segment_reporter.h | 6 ++-- .../extensions/tracers/skywalking/tracer.cc | 4 +-- source/extensions/tracers/skywalking/tracer.h | 20 +++++------ .../skywalking/skywalking_test_helper.h | 20 +++++------ .../skywalking/trace_segment_reporter_test.cc | 18 +++++----- .../tracers/skywalking/tracer_test.cc | 35 ++++++++++++------- 10 files changed, 64 insertions(+), 55 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index eb097a94c114..47a9dd2d4073 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -620,13 +620,13 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "cpp2sky", project_desc = "C++ SDK for Apache SkyWalking", project_url = "https://github.com/SkyAPM/cpp2sky", - sha256 = "eda4c32296aefde09cb7d059fc3d06698bf96d7827db51c582e1cd40e266c260", - version = "0.4.0", + sha256 = "d7e52f517de5a1dc7d927dd63a2e5aa5cf8c2dcfd8fcf6b64e179978daf1c3ed", + version = "0.6.0", strip_prefix = "cpp2sky-{version}", urls = ["https://github.com/SkyAPM/cpp2sky/archive/v{version}.tar.gz"], use_category = ["observability_ext"], extensions = ["envoy.tracers.skywalking"], - release_date = "2022-03-28", + release_date = "2024-08-21", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/SkyAPM/cpp2sky/blob/v{version}/LICENSE", diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc index aa8b6d2d0cee..d312b83f707d 100644 --- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc +++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc @@ -23,7 +23,7 @@ constexpr absl::string_view DEFAULT_SERVICE_AND_INSTANCE = "EnvoyProxy"; } // namespace using cpp2sky::createSpanContext; -using cpp2sky::SpanContextPtr; +using cpp2sky::SpanContextSharedPtr; Driver::Driver(const envoy::config::trace::v3::SkyWalkingConfig& proto_config, Server::Configuration::TracerFactoryContext& context) @@ -50,7 +50,7 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config&, Tracing::TraceContext const StreamInfo::StreamInfo&, const std::string&, Tracing::Decision decision) { auto& tracer = tls_slot_ptr_->getTyped().tracer(); - TracingContextPtr tracing_context; + TracingContextSharedPtr tracing_context; // TODO(shikugawa): support extension span header. auto propagation_header = skywalkingPropagationHeaderKey().get(trace_context); if (!propagation_header.has_value()) { @@ -70,7 +70,7 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config&, Tracing::TraceContext // https://github.com/SkyAPM/cpp2sky/issues/117. So, we need to catch all exceptions here to // avoid Envoy crash in the runtime. TRY_NEEDS_AUDIT { - SpanContextPtr span_context = + SpanContextSharedPtr span_context = createSpanContext(toStdStringView(header_value_string)); // NOLINT(std::string_view) tracing_context = tracing_context_factory_->create(span_context); } diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.h b/source/extensions/tracers/skywalking/skywalking_tracer_impl.h index f99cb8aa2345..181e3193b20d 100644 --- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.h +++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.h @@ -17,7 +17,7 @@ namespace SkyWalking { using cpp2sky::TracerConfig; using cpp2sky::TracingContextFactory; -using cpp2sky::TracingContextPtr; +using cpp2sky::TracingContextSharedPtr; class Driver : public Tracing::Driver, public Logger::Loggable { public: diff --git a/source/extensions/tracers/skywalking/trace_segment_reporter.cc b/source/extensions/tracers/skywalking/trace_segment_reporter.cc index 6ee0e9105703..3665ec065823 100644 --- a/source/extensions/tracers/skywalking/trace_segment_reporter.cc +++ b/source/extensions/tracers/skywalking/trace_segment_reporter.cc @@ -42,7 +42,7 @@ void TraceSegmentReporter::onCreateInitialMetadata(Http::RequestHeaderMap& metad } } -void TraceSegmentReporter::report(TracingContextPtr tracing_context) { +void TraceSegmentReporter::report(TracingContextSharedPtr tracing_context) { ASSERT(tracing_context); auto request = tracing_context->createSegmentObject(); ENVOY_LOG(trace, "Try to report segment to SkyWalking Server:\n{}", request.DebugString()); diff --git a/source/extensions/tracers/skywalking/trace_segment_reporter.h b/source/extensions/tracers/skywalking/trace_segment_reporter.h index 2fb5a0718836..d4737505528f 100644 --- a/source/extensions/tracers/skywalking/trace_segment_reporter.h +++ b/source/extensions/tracers/skywalking/trace_segment_reporter.h @@ -16,7 +16,7 @@ namespace Extensions { namespace Tracers { namespace SkyWalking { -using cpp2sky::TracingContextPtr; +using cpp2sky::TracingContextSharedPtr; class TraceSegmentReporter : public Logger::Loggable, public Grpc::AsyncStreamCallbacks { @@ -34,7 +34,7 @@ class TraceSegmentReporter : public Logger::Loggable, void onReceiveTrailingMetadata(Http::ResponseTrailerMapPtr&&) override {} void onRemoteClose(Grpc::Status::GrpcStatus, const std::string&) override; - void report(TracingContextPtr tracing_context); + void report(TracingContextSharedPtr tracing_context); private: /* @@ -48,7 +48,7 @@ class TraceSegmentReporter : public Logger::Loggable, SkyWalkingTracerStatsSharedPtr tracing_stats_; Grpc::AsyncClient client_; - Grpc::AsyncStream stream_{}; + Grpc::AsyncStream stream_; const Protobuf::MethodDescriptor& service_method_; Random::RandomGenerator& random_generator_; // If the connection is unavailable when reporting data, the created SegmentObject will be cached diff --git a/source/extensions/tracers/skywalking/tracer.cc b/source/extensions/tracers/skywalking/tracer.cc index 464b81d0a6c7..eddfa0427635 100644 --- a/source/extensions/tracers/skywalking/tracer.cc +++ b/source/extensions/tracers/skywalking/tracer.cc @@ -71,7 +71,7 @@ Tracing::SpanPtr Span::spawnChild(const Tracing::Config&, const std::string&, Sy Tracer::Tracer(TraceSegmentReporterPtr reporter) : reporter_(std::move(reporter)) {} -void Tracer::sendSegment(TracingContextPtr segment_context) { +void Tracer::sendSegment(TracingContextSharedPtr segment_context) { ASSERT(reporter_); if (segment_context->readyToSend()) { reporter_->report(std::move(segment_context)); @@ -79,7 +79,7 @@ void Tracer::sendSegment(TracingContextPtr segment_context) { } Tracing::SpanPtr Tracer::startSpan(absl::string_view name, absl::string_view protocol, - TracingContextPtr tracing_context) { + TracingContextSharedPtr tracing_context) { return std::make_unique(name, protocol, tracing_context, *this); } } // namespace SkyWalking diff --git a/source/extensions/tracers/skywalking/tracer.h b/source/extensions/tracers/skywalking/tracer.h index 70f03f9e50b5..32b948f4eabe 100644 --- a/source/extensions/tracers/skywalking/tracer.h +++ b/source/extensions/tracers/skywalking/tracer.h @@ -17,8 +17,8 @@ namespace Extensions { namespace Tracers { namespace SkyWalking { -using cpp2sky::TracingContextPtr; -using cpp2sky::TracingSpanPtr; +using cpp2sky::TracingContextSharedPtr; +using cpp2sky::TracingSpanSharedPtr; const Tracing::TraceContextHandler& skywalkingPropagationHeaderKey(); @@ -31,7 +31,7 @@ class Tracer { * * @param segment_context The segment context. */ - void sendSegment(TracingContextPtr tracing_context); + void sendSegment(TracingContextSharedPtr tracing_context); /* * Create a new span based on the segment context and parent span. @@ -43,7 +43,7 @@ class Tracer { * @return The unique ptr to the newly created span. */ Tracing::SpanPtr startSpan(absl::string_view name, absl::string_view protocol, - TracingContextPtr tracing_context); + TracingContextSharedPtr tracing_context); private: TraceSegmentReporterPtr reporter_; @@ -53,7 +53,7 @@ using TracerPtr = std::unique_ptr; class Span : public Tracing::Span { public: - Span(absl::string_view name, absl::string_view protocol, TracingContextPtr tracing_context, + Span(absl::string_view name, absl::string_view protocol, TracingContextSharedPtr tracing_context, Tracer& parent_tracer) : parent_tracer_(parent_tracer), tracing_context_(tracing_context), span_entity_(tracing_context_->createEntrySpan()) { @@ -69,7 +69,7 @@ class Span : public Tracing::Span { span_entity_->setSpanLayer(layer); } Span(absl::string_view name, skywalking::v3::SpanLayer span_layer, Span& parent_span, - TracingContextPtr tracing_context, Tracer& parent_tracer) + TracingContextSharedPtr tracing_context, Tracer& parent_tracer) : parent_tracer_(parent_tracer), tracing_context_(tracing_context), span_entity_(tracing_context_->createExitSpan(parent_span.spanEntity())) { span_entity_->startSpan({name.data(), name.size()}); @@ -91,13 +91,13 @@ class Span : public Tracing::Span { std::string getTraceId() const override { return tracing_context_->traceId(); } std::string getSpanId() const override { return EMPTY_STRING; } - const TracingContextPtr tracingContext() { return tracing_context_; } - const TracingSpanPtr spanEntity() { return span_entity_; } + const TracingContextSharedPtr tracingContext() { return tracing_context_; } + const TracingSpanSharedPtr spanEntity() { return span_entity_; } private: Tracer& parent_tracer_; - TracingContextPtr tracing_context_; - TracingSpanPtr span_entity_; + TracingContextSharedPtr tracing_context_; + TracingSpanSharedPtr span_entity_; }; } // namespace SkyWalking diff --git a/test/extensions/tracers/skywalking/skywalking_test_helper.h b/test/extensions/tracers/skywalking/skywalking_test_helper.h index 7af27e5a0c07..5f69aa590e18 100644 --- a/test/extensions/tracers/skywalking/skywalking_test_helper.h +++ b/test/extensions/tracers/skywalking/skywalking_test_helper.h @@ -16,11 +16,11 @@ namespace Tracers { namespace SkyWalking { using cpp2sky::createSpanContext; -using cpp2sky::SpanContextPtr; +using cpp2sky::SpanContextSharedPtr; using cpp2sky::TracerConfig; using cpp2sky::TracingContextFactory; -using cpp2sky::TracingContextPtr; -using cpp2sky::TracingSpanPtr; +using cpp2sky::TracingContextSharedPtr; +using cpp2sky::TracingSpanSharedPtr; /* * A simple helper class for auxiliary testing. Contains some simple static functions, such as @@ -59,21 +59,21 @@ class SkyWalkingTestHelper { return tracing_context->createSW8HeaderValue(seed + "#ENDPOINT").value(); } - static TracingContextPtr createSegmentContext(bool sampled, std::string seed, - std::string prev_seed) { + static TracingContextSharedPtr createSegmentContext(bool sampled, std::string seed, + std::string prev_seed) { TracerConfig config; config.set_service_name(seed + "#SERVICE"); config.set_instance_name(seed + "#INSTANCE"); auto tracing_context_factory = std::make_unique(config); - SpanContextPtr previous_span_context; + SpanContextSharedPtr previous_span_context; if (!prev_seed.empty()) { std::string header_value = createPropagatedSW8HeaderValue(sampled, prev_seed); previous_span_context = createSpanContext(header_value); ASSERT(previous_span_context); } - TracingContextPtr tracing_context; + TracingContextSharedPtr tracing_context; if (previous_span_context) { tracing_context = tracing_context_factory->create(previous_span_context); } else { @@ -86,9 +86,9 @@ class SkyWalkingTestHelper { return tracing_context; } - static TracingSpanPtr createSpanStore(TracingContextPtr tracing_context, - TracingSpanPtr parent_span_store, std::string seed, - bool sample = true) { + static TracingSpanSharedPtr createSpanStore(TracingContextSharedPtr tracing_context, + TracingSpanSharedPtr parent_span_store, + std::string seed, bool sample = true) { auto span_store = parent_span_store ? tracing_context->createExitSpan(parent_span_store) : tracing_context->createEntrySpan(); diff --git a/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc b/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc index 76fd05b3ba98..e10cabf7b225 100644 --- a/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc +++ b/test/extensions/tracers/skywalking/trace_segment_reporter_test.cc @@ -99,13 +99,13 @@ TEST_F(TraceSegmentReporterTest, TraceSegmentReporterReportTraceSegment) { setupTraceSegmentReporter("{}"); ON_CALL(mock_random_generator_, random()).WillByDefault(Return(23333)); - TracingContextPtr segment_context = + TracingContextSharedPtr segment_context = SkyWalkingTestHelper::createSegmentContext(true, "NEW", "PRE"); - TracingSpanPtr parent_store = + TracingSpanSharedPtr parent_store = SkyWalkingTestHelper::createSpanStore(segment_context, nullptr, "PARENT"); // Skip reporting the first child span. - TracingSpanPtr first_child_sptore = + TracingSpanSharedPtr first_child_sptore = SkyWalkingTestHelper::createSpanStore(segment_context, parent_store, "CHILD", false); // Create second child span. @@ -121,7 +121,7 @@ TEST_F(TraceSegmentReporterTest, TraceSegmentReporterReportTraceSegment) { EXPECT_EQ(0U, mock_scope_.counter("tracing.skywalking.segments_flushed").value()); // Create a segment context with no previous span context. - TracingContextPtr second_segment_context = + TracingContextSharedPtr second_segment_context = SkyWalkingTestHelper::createSegmentContext(true, "SECOND_SEGMENT", ""); SkyWalkingTestHelper::createSpanStore(second_segment_context, nullptr, "PARENT"); @@ -138,9 +138,9 @@ TEST_F(TraceSegmentReporterTest, TraceSegmentReporterReportWithDefaultCache) { setupTraceSegmentReporter("{}"); ON_CALL(mock_random_generator_, random()).WillByDefault(Return(23333)); - TracingContextPtr segment_context = + TracingContextSharedPtr segment_context = SkyWalkingTestHelper::createSegmentContext(true, "NEW", "PRE"); - TracingSpanPtr parent_store = + TracingSpanSharedPtr parent_store = SkyWalkingTestHelper::createSpanStore(segment_context, nullptr, "PARENT"); SkyWalkingTestHelper::createSpanStore(segment_context, parent_store, "CHILD"); @@ -188,9 +188,9 @@ TEST_F(TraceSegmentReporterTest, TraceSegmentReporterReportWithCacheConfig) { ON_CALL(mock_random_generator_, random()).WillByDefault(Return(23333)); - TracingContextPtr segment_context = + TracingContextSharedPtr segment_context = SkyWalkingTestHelper::createSegmentContext(true, "NEW", "PRE"); - TracingSpanPtr parent_store = + TracingSpanSharedPtr parent_store = SkyWalkingTestHelper::createSpanStore(segment_context, nullptr, "PARENT"); SkyWalkingTestHelper::createSpanStore(segment_context, parent_store, "CHILD"); @@ -239,7 +239,7 @@ TEST_F(TraceSegmentReporterTest, CallAsyncCallbackAndNothingTodo) { TEST_F(TraceSegmentReporterTest, NoReportWithHighWatermark) { setupTraceSegmentReporter("{}"); - TracingContextPtr segment_context = + TracingContextSharedPtr segment_context = SkyWalkingTestHelper::createSegmentContext(true, "NEW", "PRE"); SkyWalkingTestHelper::createSpanStore(segment_context, nullptr, "CHILD"); diff --git a/test/extensions/tracers/skywalking/tracer_test.cc b/test/extensions/tracers/skywalking/tracer_test.cc index 60a12a42ed15..1dab0f94550f 100644 --- a/test/extensions/tracers/skywalking/tracer_test.cc +++ b/test/extensions/tracers/skywalking/tracer_test.cc @@ -104,38 +104,47 @@ TEST_F(TracerTest, TracerTestCreateNewSpanWithNoPropagationHeaders) { // Test whether the tag can be set correctly. span->setTag("TestTagKeyA", "TestTagValueA"); span->setTag("TestTagKeyB", "TestTagValueB"); - EXPECT_EQ("TestTagValueA", span->spanEntity()->tags().at(0).second); - EXPECT_EQ("TestTagValueB", span->spanEntity()->tags().at(1).second); // When setting the status code tag, the corresponding tag name will be rewritten as // 'status_code'. span->setTag(Tracing::Tags::get().HttpStatusCode, "200"); - EXPECT_EQ("status_code", span->spanEntity()->tags().at(2).first); - EXPECT_EQ("200", span->spanEntity()->tags().at(2).second); // When setting the error tag, the spanEntity object will also mark itself as an error. span->setTag(Tracing::Tags::get().Error, Tracing::Tags::get().True); - EXPECT_EQ(Tracing::Tags::get().Error, span->spanEntity()->tags().at(3).first); - EXPECT_EQ(Tracing::Tags::get().True, span->spanEntity()->tags().at(3).second); EXPECT_EQ(true, span->spanEntity()->errorStatus()); // When setting http url tag, the corresponding tag name will be rewritten as 'url'. span->setTag(Tracing::Tags::get().HttpUrl, "http://test.com/test/path"); - EXPECT_EQ("url", span->spanEntity()->tags().at(4).first); // When setting peer address tag, the peer will be set. span->setTag(Tracing::Tags::get().PeerAddress, "1.2.3.4:8080"); EXPECT_EQ("1.2.3.4:8080", span->spanEntity()->peer()); - span->log(SystemTime{std::chrono::duration(100)}, "abc"); - EXPECT_EQ(1, span->spanEntity()->logs().size()); - EXPECT_LT(0, span->spanEntity()->logs().at(0).time()); - EXPECT_EQ("abc", span->spanEntity()->logs().at(0).data().at(0).value()); - absl::string_view sample{"GETxx"}; sample.remove_suffix(2); span->setTag(Tracing::Tags::get().HttpMethod, sample); - EXPECT_EQ("GET", span->spanEntity()->tags().at(5).second); + + span->log(SystemTime{std::chrono::duration(100)}, "abc"); + + // Evaluate tag values and log values at last. + auto span_object = span->spanEntity()->createSpanObject(); + EXPECT_EQ("TestTagValueA", span_object.tags().at(0).value()); + EXPECT_EQ("TestTagValueB", span_object.tags().at(1).value()); + + EXPECT_EQ("status_code", span_object.tags().at(2).key()); + EXPECT_EQ("200", span_object.tags().at(2).value()); + + EXPECT_EQ(Tracing::Tags::get().Error, span_object.tags().at(3).key()); + EXPECT_EQ(Tracing::Tags::get().True, span_object.tags().at(3).value()); + + EXPECT_EQ("url", span_object.tags().at(4).key()); + EXPECT_EQ("http://test.com/test/path", span_object.tags().at(4).value()); + + EXPECT_EQ("GET", span_object.tags().at(5).value()); + + EXPECT_EQ(1, span_object.logs().size()); + EXPECT_LT(0, span_object.logs().at(0).time()); + EXPECT_EQ("abc", span_object.logs().at(0).data().at(0).value()); } { From 5d82cb6403917c306286f79941c812c141319242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20JACQUES?= Date: Fri, 23 Aug 2024 00:35:45 +0200 Subject: [PATCH 19/53] Fix the NO_HTTP3_SKIP_TARGETS variable (#35765) Fix the NO_HTTP3_SKIP_TARGETS variable Signed-off-by: JACQUES Francois --- bazel/repositories.bzl | 2 ++ source/exe/BUILD | 1 + test/config_test/BUILD | 1 + 3 files changed, 4 insertions(+) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index b6a698103eed..e29e867457a0 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -39,6 +39,8 @@ NO_HTTP3_SKIP_TARGETS = [ "envoy.quic.deterministic_connection_id_generator", "envoy.quic.proof_source.filter_chain", "envoy.quic.server_preferred_address.fixed", + "envoy.quic.server_preferred_address.datasource", + "envoy.quic.connection_debug_visitor.basic", ] # Make all contents of an external repository accessible under a filegroup. Used for external HTTP diff --git a/source/exe/BUILD b/source/exe/BUILD index 09b7647b1d1b..8885a4923956 100644 --- a/source/exe/BUILD +++ b/source/exe/BUILD @@ -49,6 +49,7 @@ envoy_cc_library( "//bazel:enable_http3_on_linux_ppc": envoy_all_extensions(PPC_SKIP_TARGETS), "//bazel:disable_http3_on_windows_x86_64": envoy_all_extensions(NO_HTTP3_SKIP_TARGETS + WINDOWS_SKIP_TARGETS), "//bazel:disable_http3_on_linux_ppc": envoy_all_extensions(NO_HTTP3_SKIP_TARGETS + PPC_SKIP_TARGETS), + "//bazel:disable_http3": envoy_all_extensions(NO_HTTP3_SKIP_TARGETS), "//conditions:default": envoy_all_extensions(), }), ) diff --git a/test/config_test/BUILD b/test/config_test/BUILD index 43561cd54f84..451b35206258 100644 --- a/test/config_test/BUILD +++ b/test/config_test/BUILD @@ -67,6 +67,7 @@ envoy_cc_test_library( "//bazel:enable_http3_on_linux_ppc": envoy_all_extensions(PPC_SKIP_TARGETS), "//bazel:disable_http3_on_windows_x86_64": envoy_all_extensions(NO_HTTP3_SKIP_TARGETS + WINDOWS_SKIP_TARGETS), "//bazel:disable_http3_on_linux_ppc": envoy_all_extensions(NO_HTTP3_SKIP_TARGETS + PPC_SKIP_TARGETS), + "//bazel:disable_http3": envoy_all_extensions(NO_HTTP3_SKIP_TARGETS), "//conditions:default": envoy_all_extensions(), }), ) From e679e7e6fb3f7c31342775d8401eb017f7682835 Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Thu, 22 Aug 2024 22:25:43 -0400 Subject: [PATCH 20/53] xds-failover: add stat tracking primary/failover connection (#35691) Extends the possible values of the `control_plane.connected_state` gauge. Previously it only stored 0 when Envoy wasn't connecting/connected to the xDS server, and 1 when it was. This PR changes it to have the following values: 0 - Envoy isn't connected/connecting to an xDS server. 1 - Envoy is connecting/connected to the primary source. 2 - Envoy is connecting/connected to the failover source. Risk Level: low. Testing: Added integration tests. Docs Changes: Will be added once the feature is complete Release Notes: N/A. Platform Specific Features: N/A Signed-off-by: Adi Suissa-Peleg --- .../config_subscription/grpc/grpc_mux_impl.cc | 15 ++++++++++--- .../config_subscription/grpc/grpc_stream.h | 21 +++++++++++++++---- .../grpc/new_grpc_mux_impl.cc | 15 ++++++++++--- .../grpc/xds_mux/grpc_mux_impl.cc | 9 +++++--- .../grpc/grpc_stream_test.cc | 11 +++++++--- .../grpc/xds_failover_integration_test.cc | 11 ++++++++++ 6 files changed, 66 insertions(+), 16 deletions(-) diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc index f402fafb8878..5da627572280 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc @@ -94,7 +94,10 @@ GrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_context) { callbacks, std::move(grpc_mux_context.async_client_), grpc_mux_context.service_method_, grpc_mux_context.dispatcher_, grpc_mux_context.scope_, std::move(grpc_mux_context.backoff_strategy_), - grpc_mux_context.rate_limit_settings_); + grpc_mux_context.rate_limit_settings_, + GrpcStream::ConnectedStateValue:: + FIRST_ENTRY); }, /*failover_stream_creator=*/ grpc_mux_context.failover_async_client_ @@ -116,7 +119,10 @@ GrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_context) { GrpcMuxFailover:: DefaultFailoverBackoffMilliseconds), - grpc_mux_context.rate_limit_settings_); + grpc_mux_context.rate_limit_settings_, + GrpcStream:: + ConnectedStateValue::SECOND_ENTRY); }) : absl::nullopt, /*grpc_mux_callbacks=*/*this, @@ -126,7 +132,10 @@ GrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_context) { envoy::service::discovery::v3::DiscoveryResponse>>( this, std::move(grpc_mux_context.async_client_), grpc_mux_context.service_method_, grpc_mux_context.dispatcher_, grpc_mux_context.scope_, - std::move(grpc_mux_context.backoff_strategy_), grpc_mux_context.rate_limit_settings_); + std::move(grpc_mux_context.backoff_strategy_), grpc_mux_context.rate_limit_settings_, + GrpcStream< + envoy::service::discovery::v3::DiscoveryRequest, + envoy::service::discovery::v3::DiscoveryResponse>::ConnectedStateValue::FIRST_ENTRY); } GrpcMuxImpl::~GrpcMuxImpl() { AllMuxes::get().erase(this); } diff --git a/source/extensions/config_subscription/grpc/grpc_stream.h b/source/extensions/config_subscription/grpc/grpc_stream.h index 3ce4ff1b967d..f8429df2605e 100644 --- a/source/extensions/config_subscription/grpc/grpc_stream.h +++ b/source/extensions/config_subscription/grpc/grpc_stream.h @@ -26,15 +26,24 @@ template class GrpcStream : public GrpcStreamInterface, public Logger::Loggable { public: + // The entry value corresponding to the grpc stream's configuration entry index. + enum class ConnectedStateValue { + // The first entry in the config corresponds to the primary xDS source. + FIRST_ENTRY = 1, + // The second entry in the config corresponds to the failover xDS source. + SECOND_ENTRY + }; + GrpcStream(GrpcStreamCallbacks* callbacks, Grpc::RawAsyncClientPtr async_client, const Protobuf::MethodDescriptor& service_method, Event::Dispatcher& dispatcher, Stats::Scope& scope, BackOffStrategyPtr backoff_strategy, - const RateLimitSettings& rate_limit_settings) + const RateLimitSettings& rate_limit_settings, ConnectedStateValue connected_state_val) : callbacks_(callbacks), async_client_(std::move(async_client)), service_method_(service_method), control_plane_stats_(Utility::generateControlPlaneStats(scope)), time_source_(dispatcher.timeSource()), backoff_strategy_(std::move(backoff_strategy)), - rate_limiting_enabled_(rate_limit_settings.enabled_) { + rate_limiting_enabled_(rate_limit_settings.enabled_), + connected_state_val_(connected_state_val) { retry_timer_ = dispatcher.createTimer([this]() -> void { establishNewStream(); }); if (rate_limiting_enabled_) { // Default Bucket contains 100 tokens maximum and refills at 10 tokens/sec. @@ -65,7 +74,7 @@ class GrpcStream : public GrpcStreamInterface, setRetryTimer(); return; } - control_plane_stats_.connected_state_.set(1); + control_plane_stats_.connected_state_.set(static_cast(connected_state_val_)); callbacks_->onStreamEstablished(); } @@ -91,7 +100,7 @@ class GrpcStream : public GrpcStreamInterface, // Sometimes during hot restarts this stat's value becomes inconsistent and will continue to // have 0 until it is reconnected. Setting here ensures that it is consistent with the state of // management server connection. - control_plane_stats_.connected_state_.set(1); + control_plane_stats_.connected_state_.set(static_cast(connected_state_val_)); callbacks_->onDiscoveryResponse(std::move(message), control_plane_stats_); } @@ -259,6 +268,10 @@ class GrpcStream : public GrpcStreamInterface, const bool rate_limiting_enabled_; Event::TimerPtr drain_request_timer_; + // A stream value to be set in the control_plane.connected_state gauge once + // the gRPC-stream is establishing a connection or connected to the server. + ConnectedStateValue connected_state_val_; + // Records the initial message and timestamp of the most recent remote closes with the same // status. absl::optional last_close_status_; diff --git a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc index 44e64c1ca43e..93716197c016 100644 --- a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc @@ -68,7 +68,10 @@ NewGrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_context) { callbacks, std::move(grpc_mux_context.async_client_), grpc_mux_context.service_method_, grpc_mux_context.dispatcher_, grpc_mux_context.scope_, std::move(grpc_mux_context.backoff_strategy_), - grpc_mux_context.rate_limit_settings_); + grpc_mux_context.rate_limit_settings_, + GrpcStream:: + ConnectedStateValue::FIRST_ENTRY); }, /*failover_stream_creator=*/ grpc_mux_context.failover_async_client_ @@ -91,7 +94,10 @@ NewGrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_context) { GrpcMuxFailover:: DefaultFailoverBackoffMilliseconds), - grpc_mux_context.rate_limit_settings_); + grpc_mux_context.rate_limit_settings_, + GrpcStream:: + ConnectedStateValue::SECOND_ENTRY); }) : absl::nullopt, /*grpc_mux_callbacks=*/*this, @@ -101,7 +107,10 @@ NewGrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_context) { envoy::service::discovery::v3::DeltaDiscoveryResponse>>( this, std::move(grpc_mux_context.async_client_), grpc_mux_context.service_method_, grpc_mux_context.dispatcher_, grpc_mux_context.scope_, - std::move(grpc_mux_context.backoff_strategy_), grpc_mux_context.rate_limit_settings_); + std::move(grpc_mux_context.backoff_strategy_), grpc_mux_context.rate_limit_settings_, + GrpcStream< + envoy::service::discovery::v3::DeltaDiscoveryRequest, + envoy::service::discovery::v3::DeltaDiscoveryResponse>::ConnectedStateValue::FIRST_ENTRY); } NewGrpcMuxImpl::~NewGrpcMuxImpl() { AllMuxes::get().erase(this); } diff --git a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc index ef39566a8383..7dedcf910abe 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc @@ -69,7 +69,8 @@ GrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_conte callbacks, std::move(grpc_mux_context.async_client_), grpc_mux_context.service_method_, grpc_mux_context.dispatcher_, grpc_mux_context.scope_, std::move(grpc_mux_context.backoff_strategy_), - grpc_mux_context.rate_limit_settings_); + grpc_mux_context.rate_limit_settings_, + GrpcStream::ConnectedStateValue::FIRST_ENTRY); }, /*failover_stream_creator=*/ grpc_mux_context.failover_async_client_ @@ -83,7 +84,8 @@ GrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_conte // be the same as the primary source. std::make_unique( GrpcMuxFailover::DefaultFailoverBackoffMilliseconds), - grpc_mux_context.rate_limit_settings_); + grpc_mux_context.rate_limit_settings_, + GrpcStream::ConnectedStateValue::SECOND_ENTRY); }) : absl::nullopt, /*grpc_mux_callbacks=*/*this, @@ -92,7 +94,8 @@ GrpcMuxImpl::createGrpcStreamObject(GrpcMuxContext& grpc_mux_conte return std::make_unique>( this, std::move(grpc_mux_context.async_client_), grpc_mux_context.service_method_, grpc_mux_context.dispatcher_, grpc_mux_context.scope_, - std::move(grpc_mux_context.backoff_strategy_), grpc_mux_context.rate_limit_settings_); + std::move(grpc_mux_context.backoff_strategy_), grpc_mux_context.rate_limit_settings_, + GrpcStream::ConnectedStateValue::FIRST_ENTRY); } template GrpcMuxImpl::~GrpcMuxImpl() { AllMuxes::get().erase(this); diff --git a/test/extensions/config_subscription/grpc/grpc_stream_test.cc b/test/extensions/config_subscription/grpc/grpc_stream_test.cc index ba84d17f2bf8..9f7645c3b712 100644 --- a/test/extensions/config_subscription/grpc/grpc_stream_test.cc +++ b/test/extensions/config_subscription/grpc/grpc_stream_test.cc @@ -36,8 +36,10 @@ class GrpcStreamTest : public testing::Test { &callbacks_, std::move(async_client_owner_), *Protobuf::DescriptorPool::generated_pool()->FindMethodByName( "envoy.service.endpoint.v3.EndpointDiscoveryService.StreamEndpoints"), - dispatcher_, *stats_.rootScope(), std::move(backoff_strategy_), rate_limit_settings_)) { - } + dispatcher_, *stats_.rootScope(), std::move(backoff_strategy_), rate_limit_settings_, + GrpcStream::ConnectedStateValue:: + FIRST_ENTRY)) {} void setUpCustomBackoffRetryTimer(uint32_t retry_initial_delay_ms, absl::optional retry_max_delay_ms, @@ -54,7 +56,10 @@ class GrpcStreamTest : public testing::Test { &callbacks_, std::move(async_client_owner_), *Protobuf::DescriptorPool::generated_pool()->FindMethodByName( "envoy.service.endpoint.v3.EndpointDiscoveryService.StreamEndpoints"), - dispatcher_, *stats_.rootScope(), std::move(backoff_strategy_), rate_limit_settings_); + dispatcher_, *stats_.rootScope(), std::move(backoff_strategy_), rate_limit_settings_, + GrpcStream< + envoy::service::discovery::v3::DiscoveryRequest, + envoy::service::discovery::v3::DiscoveryResponse>::ConnectedStateValue::FIRST_ENTRY); } NiceMock dispatcher_; diff --git a/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc b/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc index 93be6621f445..9318d0150bf3 100644 --- a/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc +++ b/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc @@ -309,6 +309,8 @@ TEST_P(XdsFailoverAdsIntegrationTest, NoFailoverBasic) { // Ensure basic flow using the primary (when failover is not defined) works. validateAllXdsResponsesAndDataplaneRequest(xds_stream_.get()); + + EXPECT_EQ(1, test_server_->gauge("control_plane.connected_state")->value()); } // Validate that when there's failover defined and the primary is available, @@ -473,6 +475,8 @@ TEST_P(XdsFailoverAdsIntegrationTest, StartupPrimaryGrpcFailureAfterHeaders) { // Ensure basic flow using the failover source works. validateAllXdsResponsesAndDataplaneRequest(failover_xds_stream_.get()); + + EXPECT_EQ(2, test_server_->gauge("control_plane.connected_state")->value()); } // Validate that once primary answers, failover will not be used, even after disconnecting. @@ -565,6 +569,8 @@ TEST_P(XdsFailoverAdsIntegrationTest, NoFailoverUseAfterPrimaryResponse) { EXPECT_TRUE(compareDiscoveryRequest(EdsTypeUrl, "", {"cluster_0"}, {"cluster_0"}, {}, false, Grpc::Status::WellKnownGrpcStatus::Ok, "", xds_stream_.get())); + + EXPECT_EQ(1, test_server_->gauge("control_plane.connected_state")->value()); } // Validate that once failover responds, and then disconnects, primary will be attempted. @@ -625,6 +631,7 @@ TEST_P(XdsFailoverAdsIntegrationTest, PrimaryUseAfterFailoverResponseAndDisconne test_server_->waitForGaugeEq("cluster_manager.warming_clusters", 0); test_server_->waitForGaugeGe("cluster_manager.active_clusters", 2); test_server_->waitForGaugeEq("cluster.failover_cluster_0.warming_state", 0); + EXPECT_EQ(2, test_server_->gauge("control_plane.connected_state")->value()); EXPECT_TRUE(compareDiscoveryRequest(CdsTypeUrl, "failover1", {}, {}, {}, false, Grpc::Status::WellKnownGrpcStatus::Ok, "", failover_xds_stream_.get())); @@ -677,6 +684,7 @@ TEST_P(XdsFailoverAdsIntegrationTest, PrimaryUseAfterFailoverResponseAndDisconne EXPECT_TRUE(compareDiscoveryRequest(EdsTypeUrl, "", {"primary_cluster_0"}, {"primary_cluster_0"}, {}, false, Grpc::Status::WellKnownGrpcStatus::Ok, "", xds_stream_.get())); + EXPECT_EQ(1, test_server_->gauge("control_plane.connected_state")->value()); } // Validates that if failover is used, and then disconnected, and the primary @@ -739,6 +747,7 @@ TEST_P(XdsFailoverAdsIntegrationTest, FailoverUseAfterFailoverResponseAndDisconn test_server_->waitForGaugeEq("cluster_manager.warming_clusters", 0); test_server_->waitForGaugeGe("cluster_manager.active_clusters", 2); test_server_->waitForGaugeEq("cluster.failover_cluster_0.warming_state", 0); + EXPECT_EQ(2, test_server_->gauge("control_plane.connected_state")->value()); EXPECT_TRUE(compareDiscoveryRequest(CdsTypeUrl, "failover1", {}, {}, {}, false, Grpc::Status::WellKnownGrpcStatus::Ok, "", failover_xds_stream_.get())); @@ -792,6 +801,7 @@ TEST_P(XdsFailoverAdsIntegrationTest, FailoverUseAfterFailoverResponseAndDisconn EXPECT_TRUE(compareDiscoveryRequest( EdsTypeUrl, "", {"failover_cluster_1"}, {"failover_cluster_1"}, {}, false, Grpc::Status::WellKnownGrpcStatus::Ok, "", failover_xds_stream_.get())); + EXPECT_EQ(2, test_server_->gauge("control_plane.connected_state")->value()); } // Validate that once failover responds, and then disconnects, Envoy @@ -855,6 +865,7 @@ TEST_P(XdsFailoverAdsIntegrationTest, test_server_->waitForGaugeEq("cluster_manager.warming_clusters", 0); test_server_->waitForGaugeGe("cluster_manager.active_clusters", 2); test_server_->waitForGaugeEq("cluster.failover_cluster_0.warming_state", 0); + EXPECT_EQ(2, test_server_->gauge("control_plane.connected_state")->value()); EXPECT_TRUE(compareDiscoveryRequest(CdsTypeUrl, "failover1", {}, {}, {}, false, Grpc::Status::WellKnownGrpcStatus::Ok, "", failover_xds_stream_.get())); From 8809f6bfe62e35c5bc42a1c6739167b71c64f637 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Thu, 22 Aug 2024 23:35:33 -0400 Subject: [PATCH 21/53] [cache_filter] Determine end_stream later (#35699) Commit Message: [cache_filter] Determine end_stream later Additional Description: Currently the cache filter is incompatible with streaming a result at the same time as populating it, because the lookup requires foreknowledge of whether the entry will have trailers or not, which isn't known until the end of the request (a `Trailers` header is a hint but not a guarantee). This change makes it so the end_stream value from the cache acts more like the way it does for every other stream, so no foreknowledge is required. Plus similar changes for content-length being potentially unknown under the same circumstances. Risk Level: Some risk to changing behavior of a filter still tagged WIP. Testing: Existing tests provide coverage, and are updated to verify the new value. Additional tests for content-length handling especially around range requests. Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a --------- Signed-off-by: Raven Black --- .../filters/http/cache/cache_filter.cc | 116 +++++++------ .../filters/http/cache/cache_filter.h | 12 +- .../filters/http/cache/http_cache.cc | 21 ++- .../filters/http/cache/http_cache.h | 48 ++++-- .../filters/http/cache/range_utils.h | 4 + .../file_system_http_cache/lookup_context.cc | 24 +-- .../simple_http_cache/simple_http_cache.cc | 9 +- .../filters/http/cache/cache_filter_test.cc | 152 ++++++++++++++++-- .../http_cache_implementation_test_common.cc | 43 ++--- .../http_cache_implementation_test_common.h | 7 +- .../filters/http/cache/http_cache_test.cc | 29 +++- .../file_system_http_cache_test.cc | 76 +++++---- 12 files changed, 372 insertions(+), 169 deletions(-) diff --git a/source/extensions/filters/http/cache/cache_filter.cc b/source/extensions/filters/http/cache/cache_filter.cc index 03f5557a8538..2e9c073a6680 100644 --- a/source/extensions/filters/http/cache/cache_filter.cc +++ b/source/extensions/filters/http/cache/cache_filter.cc @@ -219,7 +219,6 @@ Http::FilterTrailersStatus CacheFilter::encodeTrailers(Http::ResponseTrailerMap& // Stop the encoding stream until the cached response is fetched & added to the encoding stream. return Http::FilterTrailersStatus::StopIteration; } - response_has_trailers_ = !trailers.empty(); if (insert_queue_ != nullptr) { ENVOY_STREAM_LOG(debug, "CacheFilter::encodeTrailers inserting trailers", *encoder_callbacks_); insert_queue_->insertTrailers(trailers); @@ -316,19 +315,14 @@ void CacheFilter::getHeaders(Http::RequestHeaderMap& request_headers) { // The dispatcher needs to be captured because there's no guarantee that // decoder_callbacks_->dispatcher() is thread-safe. - lookup_->getHeaders([self, &request_headers, - &dispatcher = decoder_callbacks_->dispatcher()](LookupResult&& result) { + lookup_->getHeaders([self, &request_headers, &dispatcher = decoder_callbacks_->dispatcher()]( + LookupResult&& result, bool end_stream) { // The callback is posted to the dispatcher to make sure it is called on the worker thread. - dispatcher.post( - [self, &request_headers, status = result.cache_entry_status_, - headers = std::move(result.headers_), range_details = std::move(result.range_details_), - content_length = result.content_length_, has_trailers = result.has_trailers_]() mutable { - if (CacheFilterSharedPtr cache_filter = self.lock()) { - cache_filter->onHeaders(LookupResult{status, std::move(headers), content_length, - range_details, has_trailers}, - request_headers); - } - }); + dispatcher.post([self, &request_headers, result = std::move(result), end_stream]() mutable { + if (CacheFilterSharedPtr cache_filter = self.lock()) { + cache_filter->onHeaders(std::move(result), request_headers, end_stream); + } + }); }); } @@ -356,11 +350,11 @@ void CacheFilter::getBody() { // The dispatcher needs to be captured because there's no guarantee that // decoder_callbacks_->dispatcher() is thread-safe. lookup_->getBody(fetch_range, [self, &dispatcher = decoder_callbacks_->dispatcher()]( - Buffer::InstancePtr&& body) { + Buffer::InstancePtr&& body, bool end_stream) { // The callback is posted to the dispatcher to make sure it is called on the worker thread. - dispatcher.post([self, body = std::move(body)]() mutable { + dispatcher.post([self, body = std::move(body), end_stream]() mutable { if (CacheFilterSharedPtr cache_filter = self.lock()) { - cache_filter->onBody(std::move(body)); + cache_filter->onBody(std::move(body), end_stream); } }); }); @@ -368,7 +362,6 @@ void CacheFilter::getBody() { void CacheFilter::getTrailers() { ASSERT(lookup_, "CacheFilter is trying to call getTrailers with no LookupContext"); - ASSERT(response_has_trailers_, "No reason to call getTrailers when there's no trailers to get."); // If the cache posts a callback to the dispatcher then the CacheFilter is destroyed for any // reason (e.g client disconnected and HTTP stream terminated), then there is no guarantee that @@ -391,7 +384,8 @@ void CacheFilter::getTrailers() { }); } -void CacheFilter::onHeaders(LookupResult&& result, Http::RequestHeaderMap& request_headers) { +void CacheFilter::onHeaders(LookupResult&& result, Http::RequestHeaderMap& request_headers, + bool end_stream) { if (filter_state_ == FilterState::Destroyed) { // The filter is being destroyed, any callbacks should be ignored. return; @@ -419,7 +413,7 @@ void CacheFilter::onHeaders(LookupResult&& result, Http::RequestHeaderMap& reque handleCacheHitWithRangeRequest(); return; } - handleCacheHit(); + handleCacheHit(/* end_stream_after_headers = */ end_stream); return; case CacheEntryStatus::Unusable: decoder_callbacks_->continueDecoding(); @@ -437,7 +431,7 @@ void CacheFilter::onHeaders(LookupResult&& result, Http::RequestHeaderMap& reque } // TODO(toddmgreer): Handle downstream backpressure. -void CacheFilter::onBody(Buffer::InstancePtr&& body) { +void CacheFilter::onBody(Buffer::InstancePtr&& body, bool end_stream) { // Can be called during decoding if a valid cache hit is found, // or during encoding if a cache entry was being validated. if (filter_state_ == FilterState::Destroyed) { @@ -447,6 +441,11 @@ void CacheFilter::onBody(Buffer::InstancePtr&& body) { ASSERT(!remaining_ranges_.empty(), "CacheFilter doesn't call getBody unless there's more body to get, so this is a " "bogus callback."); + if (remaining_ranges_[0].end() == std::numeric_limits::max() && body == nullptr) { + ASSERT(!end_stream); + getTrailers(); + return; + } ASSERT(body, "Cache said it had a body, but isn't giving it to us."); const uint64_t bytes_from_cache = body->length(); @@ -461,18 +460,23 @@ void CacheFilter::onBody(Buffer::InstancePtr&& body) { return; } - const bool end_stream = remaining_ranges_.empty() && !response_has_trailers_; - filter_state_ == FilterState::DecodeServingFromCache ? decoder_callbacks_->encodeData(*body, end_stream) : encoder_callbacks_->addEncodedData(*body, true); - if (!remaining_ranges_.empty()) { + if (end_stream) { + finalizeEncodingCachedResponse(); + } else if (!remaining_ranges_.empty()) { getBody(); - } else if (response_has_trailers_) { - getTrailers(); - } else { + } else if (lookup_result_->range_details_.has_value()) { + // If a range was requested we don't send trailers. + // (It is unclear from the spec whether we should, but pragmatically we + // don't have any indication of whether trailers are present or not, and + // range requests in general are for filling in missing chunks so including + // trailers with every chunk would be wasteful.) finalizeEncodingCachedResponse(); + } else { + getTrailers(); } } @@ -500,16 +504,16 @@ void CacheFilter::onTrailers(Http::ResponseTrailerMapPtr&& trailers) { finalizeEncodingCachedResponse(); } -void CacheFilter::handleCacheHit() { +void CacheFilter::handleCacheHit(bool end_stream_after_headers) { filter_state_ = FilterState::DecodeServingFromCache; insert_status_ = InsertStatus::NoInsertCacheHit; - encodeCachedResponse(); + encodeCachedResponse(end_stream_after_headers); } void CacheFilter::handleCacheHitWithRangeRequest() { if (!lookup_result_->range_details_.has_value()) { ENVOY_LOG(error, "handleCacheHitWithRangeRequest() should not be called without " - "range_details being populated in lookup_result_"); + "range_details_ being populated in lookup_result_"); return; } if (!lookup_result_->range_details_->satisfiable_) { @@ -517,12 +521,21 @@ void CacheFilter::handleCacheHitWithRangeRequest() { insert_status_ = InsertStatus::NoInsertCacheHit; lookup_result_->headers_->setStatus( static_cast(Envoy::Http::Code::RangeNotSatisfiable)); - lookup_result_->headers_->addCopy(Envoy::Http::Headers::get().ContentRange, - absl::StrCat("bytes */", lookup_result_->content_length_)); + if (lookup_result_->content_length_.has_value()) { + lookup_result_->headers_->addCopy( + Envoy::Http::Headers::get().ContentRange, + absl::StrCat("bytes */", lookup_result_->content_length_.value())); + } else { + IS_ENVOY_BUG( + "handleCacheHitWithRangeRequest() should not be called with satisfiable_=false " + "without content_length_ being populated in lookup_result_. Cache implementation " + "should wait to respond to getHeaders in this case until content_length_ is known, " + "declaring a miss, or should strip range_details_ from the lookup result."); + } // We shouldn't serve any of the body, so the response content length // is 0. lookup_result_->setContentLength(0); - encodeCachedResponse(); + encodeCachedResponse(/* end_stream_after_headers = */ true); decoder_callbacks_->continueDecoding(); return; } @@ -536,7 +549,7 @@ void CacheFilter::handleCacheHitWithRangeRequest() { // each part. Would need to keep track if the current range is over or // not to know when to insert the separator, and calculate the length // based on length of ranges + extra headers and separators. - handleCacheHit(); + handleCacheHit(/* end_stream_after_headers = */ false); return; } @@ -544,15 +557,17 @@ void CacheFilter::handleCacheHitWithRangeRequest() { insert_status_ = InsertStatus::NoInsertCacheHit; lookup_result_->headers_->setStatus(static_cast(Envoy::Http::Code::PartialContent)); - lookup_result_->headers_->addCopy(Envoy::Http::Headers::get().ContentRange, - absl::StrCat("bytes ", ranges[0].begin(), "-", - ranges[0].end() - 1, "/", - lookup_result_->content_length_)); + lookup_result_->headers_->addCopy( + Envoy::Http::Headers::get().ContentRange, + absl::StrCat("bytes ", ranges[0].begin(), "-", ranges[0].end() - 1, "/", + lookup_result_->content_length_.has_value() + ? absl::StrCat(lookup_result_->content_length_.value()) + : "*")); // We serve only the desired range, so adjust the length // accordingly. lookup_result_->setContentLength(ranges[0].length()); remaining_ranges_ = std::move(ranges); - encodeCachedResponse(); + encodeCachedResponse(/* end_stream_after_headers = */ false); decoder_callbacks_->continueDecoding(); } @@ -609,7 +624,7 @@ void CacheFilter::processSuccessfulValidation(Http::ResponseHeaderMap& response_ } // A cache entry was successfully validated -> encode cached body and trailers. - encodeCachedResponse(); + encodeCachedResponse(/* end_stream_after_headers = */ false); } // TODO(yosrym93): Write a test that exercises this when SimpleHttpCache implements updateHeaders @@ -662,14 +677,10 @@ void CacheFilter::injectValidationHeaders(Http::RequestHeaderMap& request_header } } -void CacheFilter::encodeCachedResponse() { +void CacheFilter::encodeCachedResponse(bool end_stream_after_headers) { ASSERT(lookup_result_, "encodeCachedResponse precondition unsatisfied: lookup_result_ " "does not point to a cache lookup result"); - response_has_trailers_ = lookup_result_->has_trailers_; - const bool end_stream = - (lookup_result_->content_length_ == 0 && !response_has_trailers_) || is_head_request_; - // Set appropriate response flags and codes. Http::StreamFilterCallbacks* callbacks = filter_state_ == FilterState::DecodeServingFromCache @@ -683,7 +694,8 @@ void CacheFilter::encodeCachedResponse() { // If the filter is encoding, 304 response headers and cached headers are merged in encodeHeaders. // If the filter is decoding, we need to serve response headers from cache directly. if (filter_state_ == FilterState::DecodeServingFromCache) { - decoder_callbacks_->encodeHeaders(std::move(lookup_result_->headers_), end_stream, + decoder_callbacks_->encodeHeaders(std::move(lookup_result_->headers_), + is_head_request_ || end_stream_after_headers, CacheResponseCodeDetails::get().ResponseFromCacheFilter); // Filter can potentially be destroyed during encodeHeaders. if (filter_state_ == FilterState::Destroyed) { @@ -694,13 +706,17 @@ void CacheFilter::encodeCachedResponse() { filter_state_ = FilterState::ResponseServedFromCache; return; } - if (lookup_result_->content_length_ > 0 && !is_head_request_) { + if (end_stream_after_headers || is_head_request_) { + return; + } + if (remaining_ranges_.empty() && lookup_result_->content_length_.value_or(1) > 0) { // No range has been added, so we add entire body to the response. - if (remaining_ranges_.empty()) { - remaining_ranges_.emplace_back(0, lookup_result_->content_length_); - } + remaining_ranges_.emplace_back( + 0, lookup_result_->content_length_.value_or(std::numeric_limits::max())); + } + if (!remaining_ranges_.empty()) { getBody(); - } else if (response_has_trailers_) { + } else { getTrailers(); } } diff --git a/source/extensions/filters/http/cache/cache_filter.h b/source/extensions/filters/http/cache/cache_filter.h index a5fd855aa35f..3641797b5c7a 100644 --- a/source/extensions/filters/http/cache/cache_filter.h +++ b/source/extensions/filters/http/cache/cache_filter.h @@ -93,12 +93,12 @@ class CacheFilter : public Http::PassThroughFilter, void getTrailers(); // Callbacks for HttpCache to call when headers/body/trailers are ready. - void onHeaders(LookupResult&& result, Http::RequestHeaderMap& request_headers); - void onBody(Buffer::InstancePtr&& body); + void onHeaders(LookupResult&& result, Http::RequestHeaderMap& request_headers, bool end_stream); + void onBody(Buffer::InstancePtr&& bod, bool end_stream); void onTrailers(Http::ResponseTrailerMapPtr&& trailers); // Set required state in the CacheFilter for handling a cache hit. - void handleCacheHit(); + void handleCacheHit(bool end_stream_after_headers); // Set up the required state in the CacheFilter for handling a range // request. @@ -128,7 +128,7 @@ class CacheFilter : public Http::PassThroughFilter, // Adds a cache lookup result to the response encoding stream. // Can be called during decoding if a valid cache hit is found, // or during encoding if a cache entry was validated successfully. - void encodeCachedResponse(); + void encodeCachedResponse(bool end_stream_after_headers); // Precondition: finished adding a response from cache to the response encoding stream. // Updates filter_state_ and continues the encoding stream if necessary. @@ -157,10 +157,6 @@ class CacheFilter : public Http::PassThroughFilter, const std::shared_ptr config_; - // True if the response has trailers. - // TODO(toddmgreer): cache trailers. - bool response_has_trailers_ = false; - // True if a request allows cache inserts according to: // https://httpwg.org/specs/rfc7234.html#response.cacheability bool request_allows_inserts_ = false; diff --git a/source/extensions/filters/http/cache/http_cache.cc b/source/extensions/filters/http/cache/http_cache.cc index 377ef2742562..6796b9778590 100644 --- a/source/extensions/filters/http/cache/http_cache.cc +++ b/source/extensions/filters/http/cache/http_cache.cc @@ -130,8 +130,8 @@ bool LookupRequest::requiresValidation(const Http::ResponseHeaderMap& response_h } LookupResult LookupRequest::makeLookupResult(Http::ResponseHeaderMapPtr&& response_headers, - ResponseMetadata&& metadata, uint64_t content_length, - bool has_trailers) const { + ResponseMetadata&& metadata, + absl::optional content_length) const { // TODO(toddmgreer): Implement all HTTP caching semantics. ASSERT(response_headers); LookupResult result; @@ -145,9 +145,20 @@ LookupResult LookupRequest::makeLookupResult(Http::ResponseHeaderMapPtr&& respon ? CacheEntryStatus::RequiresValidation : CacheEntryStatus::Ok; result.headers_ = std::move(response_headers); - result.content_length_ = content_length; - result.range_details_ = RangeUtils::createRangeDetails(requestHeaders(), content_length); - result.has_trailers_ = has_trailers; + if (content_length.has_value()) { + result.content_length_ = content_length; + } else { + absl::string_view content_length_header = result.headers_->getContentLengthValue(); + int64_t length_from_header; + if (!content_length_header.empty() && + absl::SimpleAtoi(content_length_header, &length_from_header)) { + result.content_length_ = length_from_header; + } + } + if (result.content_length_.has_value()) { + result.range_details_ = + RangeUtils::createRangeDetails(requestHeaders(), result.content_length_.value()); + } return result; } diff --git a/source/extensions/filters/http/cache/http_cache.h b/source/extensions/filters/http/cache/http_cache.h index 24533ca19467..59face7598bb 100644 --- a/source/extensions/filters/http/cache/http_cache.h +++ b/source/extensions/filters/http/cache/http_cache.h @@ -39,17 +39,16 @@ struct LookupResult { // header with this value, replacing any preexisting content-length header. // (This lets us dechunk responses as we insert them, then later serve them // with a content-length header.) - uint64_t content_length_; + // If the cache entry is still populating, and the cache supports streaming, + // and the response had no content-length header, the content length may be + // unknown at lookup-time. + absl::optional content_length_; // If the request is a range request, this struct indicates if the ranges can // be satisfied and which ranges are requested. nullopt indicates that this is // not a range request or the range header has been ignored. absl::optional range_details_; - // TODO(toddmgreer): Implement trailer support. - // True if the cached response has trailers. - bool has_trailers_ = false; - // Update the content length of the object and its response headers. void setContentLength(uint64_t new_length) { content_length_ = new_length; @@ -97,8 +96,8 @@ class LookupRequest { // - LookupResult::response_ranges_ entries are satisfiable (as documented // there). LookupResult makeLookupResult(Http::ResponseHeaderMapPtr&& response_headers, - ResponseMetadata&& metadata, uint64_t content_length, - bool has_trailers) const; + ResponseMetadata&& metadata, + absl::optional content_length) const; const Http::RequestHeaderMap& requestHeaders() const { return *request_headers_; } const VaryAllowList& varyAllowList() const { return vary_allow_list_; } @@ -123,8 +122,8 @@ struct CacheInfo { bool supports_range_requests_ = false; }; -using LookupBodyCallback = std::function; -using LookupHeadersCallback = std::function; +using LookupBodyCallback = std::function; +using LookupHeadersCallback = std::function; using LookupTrailersCallback = std::function; using InsertCallback = std::function; @@ -192,6 +191,14 @@ class LookupContext { public: // Get the headers from the cache. It is a programming error to call this // twice. + // In the case that a cache supports shared streaming (serving content from + // the cache entry while it is still being populated), and a range request is made + // for a streaming entry that didn't have a content-length header from upstream, range + // requests may be unable to receive a response until the content-length is + // known to exceed the end of the requested range. In this case a cache + // implementation should wait until that is known before calling the callback, + // and must pass a LookupResult with range_details_->satisfiable_ = false + // if the request is invalid. virtual void getHeaders(LookupHeadersCallback&& cb) PURE; // Reads the next fragment from the cache, calling cb when the fragment is ready. @@ -199,9 +206,19 @@ class LookupContext { // // The cache must call cb with a range of bytes starting at range.start() and // ending at or before range.end(). Caller is responsible for tracking what - // ranges have been received, what to request next, and when to stop. A cache - // can report an error, and cause the response to be aborted, by calling cb - // with nullptr. + // ranges have been received, what to request next, and when to stop. + // + // A request may have a range that exceeds the size of the content, in support + // of a "shared stream" cache entry, where the request may not know the size of + // the content in advance. In this case the cache should call cb with + // end_stream=true when the end of the body is reached, if there are no trailers. + // + // If there are trailers *and* the size of the content was not known when the + // LookupContext was created, the cache should pass a null buffer pointer to the + // LookupBodyCallback (when getBody is called with a range starting beyond the + // end of the actual content-length) to indicate that no more body is available + // and the filter should request trailers. It is invalid to pass a null buffer + // pointer other than in this case. // // If a cache happens to load data in fragments of a set size, it may be // efficient to respond with fewer than the requested number of bytes. For @@ -213,7 +230,8 @@ class LookupContext { // getBody requests bytes 20-23 .......... callback with bytes 20-23 virtual void getBody(const AdjustedByteRange& range, LookupBodyCallback&& cb) PURE; - // Get the trailers from the cache. Only called if LookupResult::has_trailers == true. The + // Get the trailers from the cache. Only called if the request reached the end of + // the body and LookupBodyCallback did not pass true for end_stream. The // Http::ResponseTrailerMapPtr passed to cb must not be null. virtual void getTrailers(LookupTrailersCallback&& cb) PURE; @@ -244,6 +262,10 @@ class HttpCache { public: // Returns a LookupContextPtr to manage the state of a cache lookup. On a cache // miss, the returned LookupContext will be given to the insert call (if any). + // + // It is possible for a cache to make a "shared stream" of responses allowing + // read access to a cache entry before its write is complete. In this case the + // content-length value may be unset. virtual LookupContextPtr makeLookupContext(LookupRequest&& request, Http::StreamDecoderFilterCallbacks& callbacks) PURE; diff --git a/source/extensions/filters/http/cache/range_utils.h b/source/extensions/filters/http/cache/range_utils.h index 4d7aa4728d2a..23178dbea67a 100644 --- a/source/extensions/filters/http/cache/range_utils.h +++ b/source/extensions/filters/http/cache/range_utils.h @@ -71,7 +71,11 @@ class AdjustedByteRange { ASSERT(first < last, "Illegal byte range."); } uint64_t begin() const { return first_; } + // Unlike RawByteRange, end() is one past the index of the last offset. + // + // If end() == std::numeric_limits::max(), the cache doesn't yet + // know the response body's length. uint64_t end() const { return last_; } uint64_t length() const { return last_ - first_; } void trimFront(uint64_t n) { diff --git a/source/extensions/http/cache/file_system_http_cache/lookup_context.cc b/source/extensions/http/cache/file_system_http_cache/lookup_context.cc index d0b006365c54..d436dd86d534 100644 --- a/source/extensions/http/cache/file_system_http_cache/lookup_context.cc +++ b/source/extensions/http/cache/file_system_http_cache/lookup_context.cc @@ -34,7 +34,7 @@ void FileLookupContext::getHeadersWithLock(LookupHeadersCallback cb) { cancel_action_in_flight_ = nullptr; if (!open_result.ok()) { cache_.stats().cache_miss_.inc(); - cb(LookupResult{}); + cb(LookupResult{}, /* end_stream (ignored) = */ false); return; } ASSERT(!file_handle_); @@ -48,14 +48,14 @@ void FileLookupContext::getHeadersWithLock(LookupHeadersCallback cb) { read_result.value()->length() != CacheFileFixedBlock::size()) { invalidateCacheEntry(); cache_.stats().cache_miss_.inc(); - cb(LookupResult{}); + cb(LookupResult{}, /* end_stream (ignored) = */ false); return; } header_block_.populateFromStringView(read_result.value()->toString()); if (!header_block_.isValid()) { invalidateCacheEntry(); cache_.stats().cache_miss_.inc(); - cb(LookupResult{}); + cb(LookupResult{}, /* end_stream (ignored) = */ false); return; } auto queued = file_handle_->read( @@ -67,7 +67,7 @@ void FileLookupContext::getHeadersWithLock(LookupHeadersCallback cb) { read_result.value()->length() != header_block_.headerSize()) { invalidateCacheEntry(); cache_.stats().cache_miss_.inc(); - cb(LookupResult{}); + cb(LookupResult{}, /* end_stream (ignored) = */ false); return; } auto header_proto = makeCacheFileHeaderProto(*read_result.value()); @@ -79,7 +79,7 @@ void FileLookupContext::getHeadersWithLock(LookupHeadersCallback cb) { lookup().requestHeaders()); if (!maybe_vary_key.has_value()) { cache_.stats().cache_miss_.inc(); - cb(LookupResult{}); + cb(LookupResult{}, /* end_stream (ignored) = */ false); return; } key_ = maybe_vary_key.value(); @@ -96,9 +96,11 @@ void FileLookupContext::getHeadersWithLock(LookupHeadersCallback cb) { return; } cache_.stats().cache_hit_.inc(); - cb(lookup().makeLookupResult( - headersFromHeaderProto(header_proto), metadataFromHeaderProto(header_proto), - header_block_.bodySize(), header_block_.trailerSize() > 0)); + cb(lookup().makeLookupResult(headersFromHeaderProto(header_proto), + metadataFromHeaderProto(header_proto), + header_block_.bodySize()), + /* end_stream = */ header_block_.trailerSize() == 0 && + header_block_.bodySize() == 0); }); ASSERT(queued.ok(), queued.status().ToString()); cancel_action_in_flight_ = queued.value(); @@ -135,10 +137,12 @@ void FileLookupContext::getBody(const AdjustedByteRange& range, LookupBodyCallba if (!read_result.ok() || read_result.value()->length() != range.length()) { invalidateCacheEntry(); // Calling callback with nullptr fails the request. - cb(nullptr); + cb(nullptr, /* end_stream (ignored) = */ false); return; } - cb(std::move(read_result.value())); + cb(std::move(read_result.value()), + /* end_stream = */ range.end() == header_block_.bodySize() && + header_block_.trailerSize() == 0); }); ASSERT(queued.ok(), queued.status().ToString()); cancel_action_in_flight_ = queued.value(); diff --git a/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc b/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc index 59f15b8af3cc..a2be23281c86 100644 --- a/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc +++ b/source/extensions/http/cache/simple_http_cache/simple_http_cache.cc @@ -41,14 +41,15 @@ class SimpleLookupContext : public LookupContext { body_ = std::move(entry.body_); trailers_ = std::move(entry.trailers_); cb(entry.response_headers_ ? request_.makeLookupResult(std::move(entry.response_headers_), - std::move(entry.metadata_), body_.size(), - trailers_ != nullptr) - : LookupResult{}); + std::move(entry.metadata_), body_.size()) + : LookupResult{}, + body_.empty() && trailers_ == nullptr); } void getBody(const AdjustedByteRange& range, LookupBodyCallback&& cb) override { ASSERT(range.end() <= body_.length(), "Attempt to read past end of body."); - cb(std::make_unique(&body_[range.begin()], range.length())); + cb(std::make_unique(&body_[range.begin()], range.length()), + trailers_ == nullptr && range.end() == body_.length()); } // The cache must call cb with the cached trailers. diff --git a/test/extensions/filters/http/cache/cache_filter_test.cc b/test/extensions/filters/http/cache/cache_filter_test.cc index a0b0cd38457b..27bd88716b80 100644 --- a/test/extensions/filters/http/cache/cache_filter_test.cc +++ b/test/extensions/filters/http/cache/cache_filter_test.cc @@ -22,6 +22,7 @@ namespace Cache { namespace { using ::Envoy::StatusHelpers::IsOkAndHolds; +using ::testing::Gt; using ::testing::IsNull; using ::testing::NotNull; @@ -371,7 +372,7 @@ TEST_F(CacheFilterTest, WatermarkEventsAreSentIfCacheBlocksStreamAndLimitExceede return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}); + cb(LookupResult{}, false); }); EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, @@ -443,7 +444,7 @@ TEST_F(CacheFilterTest, FilterDestroyedWhileWatermarkedSendsLowWatermarkEvent) { return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}); + cb(LookupResult{}, false); }); EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, @@ -494,6 +495,57 @@ MATCHER_P2(RangeMatcher, begin, end, "") { testing::ExplainMatchResult(end, arg.end(), result_listener); } +TEST_F(CacheFilterTest, CacheEntryStreamedWithTrailersAndNoContentLengthCanDeliverTrailers) { + request_headers_.setHost("CacheEntryStreamedWithTrailers"); + const std::string body = "abcde"; + auto mock_http_cache = std::make_shared(); + auto mock_lookup_context = std::make_unique(); + EXPECT_CALL(*mock_http_cache, makeLookupContext(_, _)) + .WillOnce([&](LookupRequest&&, + Http::StreamDecoderFilterCallbacks&) -> std::unique_ptr { + return std::move(mock_lookup_context); + }); + // response_headers_ intentionally has no content length, LookupResult also has no content length. + EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { + cb(LookupResult{CacheEntryStatus::Ok, + std::make_unique(response_headers_), + absl::nullopt, absl::nullopt}, + /* end_stream = */ false); + }); + EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, Gt(5)), _)) + .WillOnce([&](AdjustedByteRange, LookupBodyCallback&& cb) { + cb(std::make_unique(body), false); + }); + EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(5, Gt(5)), _)) + .WillOnce([&](AdjustedByteRange, LookupBodyCallback&& cb) { cb(nullptr, false); }); + EXPECT_CALL(*mock_lookup_context, getTrailers(_)).WillOnce([&](LookupTrailersCallback&& cb) { + cb(std::make_unique()); + }); + EXPECT_CALL(*mock_lookup_context, onDestroy()); + { + CacheFilterSharedPtr filter = makeFilter(mock_http_cache); + EXPECT_CALL(decoder_callbacks_, encodeHeaders_(IsSupersetOfHeaders(response_headers_), false)); + EXPECT_EQ(filter->decodeHeaders(request_headers_, true), + Http::FilterHeadersStatus::StopAllIterationAndWatermark); + EXPECT_CALL( + decoder_callbacks_, + encodeData(testing::Property(&Buffer::Instance::toString, testing::Eq("abcde")), false)); + EXPECT_CALL(decoder_callbacks_, encodeTrailers_(_)); + + // The cache lookup callback should be posted to the dispatcher. + // Run events on the dispatcher so that the callback is invoked. + // The posted lookup callback will cause another callback to be posted (when getBody() is + // called) which should also be invoked. + dispatcher_->run(Event::Dispatcher::RunType::Block); + + ::testing::Mock::VerifyAndClearExpectations(&decoder_callbacks_); + + filter->onStreamComplete(); + EXPECT_THAT(lookupStatus(), IsOkAndHolds(LookupStatus::CacheHit)); + EXPECT_THAT(insertStatus(), IsOkAndHolds(InsertStatus::NoInsertCacheHit)); + } +} + TEST_F(CacheFilterTest, OnDestroyBeforeOnHeadersAbortsAction) { request_headers_.setHost("CacheHitWithBody"); auto mock_http_cache = std::make_shared(); @@ -506,7 +558,7 @@ TEST_F(CacheFilterTest, OnDestroyBeforeOnHeadersAbortsAction) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}); + cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}, false); }); auto filter = makeFilter(mock_http_cache, false); EXPECT_EQ(filter->decodeHeaders(request_headers_, true), @@ -529,7 +581,7 @@ TEST_F(CacheFilterTest, OnDestroyBeforeOnBodyAbortsAction) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt}); + cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt}, false); }); LookupBodyCallback body_callback; EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) @@ -540,7 +592,7 @@ TEST_F(CacheFilterTest, OnDestroyBeforeOnBodyAbortsAction) { dispatcher_->run(Event::Dispatcher::RunType::NonBlock); filter->onDestroy(); // onBody should do nothing because the filter was destroyed. - body_callback(std::make_unique("abcde")); + body_callback(std::make_unique("abcde"), true); dispatcher_->run(Event::Dispatcher::RunType::NonBlock); } @@ -556,11 +608,11 @@ TEST_F(CacheFilterTest, OnDestroyBeforeOnTrailersAbortsAction) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt, true}); + cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 5, absl::nullopt}, false); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { - cb(std::make_unique("abcde")); + cb(std::make_unique("abcde"), false); }); LookupTrailersCallback trailers_callback; EXPECT_CALL(*mock_lookup_context, getTrailers(_)).WillOnce([&](LookupTrailersCallback&& cb) { @@ -591,15 +643,15 @@ TEST_F(CacheFilterTest, BodyReadFromCacheLimitedToBufferSizeChunks) { EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { std::unique_ptr response_headers = std::make_unique(response_headers_); - cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}); + cb(LookupResult{CacheEntryStatus::Ok, std::move(response_headers), 8, absl::nullopt}, false); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { - cb(std::make_unique("abcde")); + cb(std::make_unique("abcde"), false); }); EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(5, 8), _)) .WillOnce([&](const AdjustedByteRange&, LookupBodyCallback&& cb) { - cb(std::make_unique("fgh")); + cb(std::make_unique("fgh"), true); }); EXPECT_CALL(*mock_lookup_context, onDestroy()); @@ -651,7 +703,7 @@ TEST_F(CacheFilterTest, CacheInsertAbortedByCache) { return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}); + cb(LookupResult{}, false); }); EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) .WillOnce([&](const Http::ResponseHeaderMap&, const ResponseMetadata&, @@ -701,7 +753,7 @@ TEST_F(CacheFilterTest, FilterDeletedWhileIncompleteCacheWriteInQueueShouldAband return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}); + cb(LookupResult{}, false); }); InsertCallback captured_insert_header_callback; EXPECT_CALL(*mock_insert_context, insertHeaders(_, _, _, false)) @@ -749,7 +801,7 @@ TEST_F(CacheFilterTest, FilterDeletedWhileCompleteCacheWriteInQueueShouldContinu return std::move(mock_insert_context); }); EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { - cb(LookupResult{}); + cb(LookupResult{}, false); }); InsertCallback captured_insert_header_callback; InsertCallback captured_insert_body_callback; @@ -1329,6 +1381,80 @@ TEST_F(CacheFilterTest, LocalReplyDuringLookup) { // https://google.github.io/googletest/advanced.html#death-test-naming using CacheFilterDeathTest = CacheFilterTest; +TEST_F(CacheFilterDeathTest, BadRangeRequestLookup) { + request_headers_.setHost("BadRangeRequestLookup"); + auto mock_http_cache = std::make_shared(); + auto mock_lookup_context = std::make_unique(); + EXPECT_CALL(*mock_http_cache, makeLookupContext(_, _)) + .WillOnce([&](LookupRequest&&, + Http::StreamDecoderFilterCallbacks&) -> std::unique_ptr { + return std::move(mock_lookup_context); + }); + EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { + // LookupResult with unknown length and an unsatisfiable RangeDetails is invalid. + cb(LookupResult{CacheEntryStatus::Ok, + std::make_unique(response_headers_), + absl::nullopt, + RangeDetails{/*satisfiable_ = */ false, {AdjustedByteRange{0, 5}}}}, + false); + }); + EXPECT_CALL(*mock_lookup_context, onDestroy()); + { + CacheFilterSharedPtr filter = makeFilter(mock_http_cache); + // encodeHeaders can be called when ENVOY_BUG doesn't exit. + response_headers_ = {{":status", "416"}}; + EXPECT_CALL(decoder_callbacks_, encodeHeaders_(IsSupersetOfHeaders(response_headers_), true)) + .Times(testing::AnyNumber()); + request_headers_.addReference(Http::Headers::get().Range, "bytes=-5"); + EXPECT_EQ(filter->decodeHeaders(request_headers_, true), + Http::FilterHeadersStatus::StopAllIterationAndWatermark); + + // The cache lookup callback should be posted to the dispatcher. + // Run events on the dispatcher so that the callback is invoked. + EXPECT_ENVOY_BUG( + dispatcher_->run(Event::Dispatcher::RunType::Block), + "handleCacheHitWithRangeRequest() should not be called with satisfiable_=false"); + } +} + +TEST_F(CacheFilterTest, RangeRequestSatisfiedBeforeLengthKnown) { + request_headers_.setHost("RangeRequestSatisfiedBeforeLengthKnown"); + std::string body = "abcde"; + auto mock_http_cache = std::make_shared(); + auto mock_lookup_context = std::make_unique(); + EXPECT_CALL(*mock_http_cache, makeLookupContext(_, _)) + .WillOnce([&](LookupRequest&&, + Http::StreamDecoderFilterCallbacks&) -> std::unique_ptr { + return std::move(mock_lookup_context); + }); + EXPECT_CALL(*mock_lookup_context, getHeaders(_)).WillOnce([&](LookupHeadersCallback&& cb) { + // LookupResult with unknown length and an unsatisfiable RangeDetails is invalid. + cb(LookupResult{CacheEntryStatus::Ok, + std::make_unique(response_headers_), + absl::nullopt, + RangeDetails{/*satisfiable_ = */ true, {AdjustedByteRange{0, 5}}}}, + false); + }); + EXPECT_CALL(*mock_lookup_context, getBody(RangeMatcher(0, 5), _)) + .WillOnce([&](AdjustedByteRange, LookupBodyCallback&& cb) { + cb(std::make_unique(body), false); + }); + EXPECT_CALL(*mock_lookup_context, onDestroy()); + { + CacheFilterSharedPtr filter = makeFilter(mock_http_cache); + response_headers_ = {{":status", "206"}, {"content-range", "bytes 0-4/*"}}; + EXPECT_CALL(decoder_callbacks_, encodeHeaders_(IsSupersetOfHeaders(response_headers_), false)) + .Times(testing::AnyNumber()); + request_headers_.addReference(Http::Headers::get().Range, "bytes=-5"); + EXPECT_EQ(filter->decodeHeaders(request_headers_, true), + Http::FilterHeadersStatus::StopAllIterationAndWatermark); + + // The cache lookup callback should be posted to the dispatcher. + // Run events on the dispatcher so that the callback is invoked. + dispatcher_->run(Event::Dispatcher::RunType::Block); + } +} + TEST_F(CacheFilterDeathTest, StreamTimeoutDuringLookup) { request_headers_.setHost("StreamTimeoutDuringLookup"); { diff --git a/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc b/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc index fdb4c3f240cf..e1db6c9d4490 100644 --- a/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc +++ b/test/extensions/filters/http/cache/http_cache_implementation_test_common.cc @@ -78,12 +78,15 @@ bool HttpCacheImplementationTest::updateHeaders( LookupContextPtr HttpCacheImplementationTest::lookup(absl::string_view request_path) { LookupRequest request = makeLookupRequest(request_path); LookupContextPtr context = cache()->makeLookupContext(std::move(request), decoder_callbacks_); - auto headers_promise = std::make_shared>(); - context->getHeaders( - [headers_promise](LookupResult&& result) { headers_promise->set_value(std::move(result)); }); + auto headers_promise = std::make_shared>>(); + context->getHeaders([headers_promise](LookupResult&& result, bool end_stream) { + headers_promise->set_value(std::make_pair(std::move(result), end_stream)); + }); auto headers_future = headers_promise->get_future(); if (std::future_status::ready == headers_future.wait_for(std::chrono::seconds(5))) { - lookup_result_ = headers_future.get(); + auto result_pair = headers_future.get(); + lookup_result_ = std::move(result_pair.first); + lookup_end_stream_after_headers_ = result_pair.second; } else { EXPECT_TRUE(false) << "timed out in lookup " << request_path; } @@ -166,26 +169,29 @@ absl::Status HttpCacheImplementationTest::insert(absl::string_view request_path, return insert(lookup(request_path), headers, body, timeout); } -Http::ResponseHeaderMapPtr HttpCacheImplementationTest::getHeaders(LookupContext& context) { +std::pair +HttpCacheImplementationTest::getHeaders(LookupContext& context) { Http::ResponseHeaderMapPtr response_headers_ptr; - auto headers_promise = std::make_shared>(); - context.getHeaders([headers_promise](LookupResult&& lookup_result) { + auto headers_promise = + std::make_shared>>(); + context.getHeaders([headers_promise](LookupResult&& lookup_result, bool end_stream) { EXPECT_NE(lookup_result.cache_entry_status_, CacheEntryStatus::Unusable); EXPECT_NE(lookup_result.headers_, nullptr); - headers_promise->set_value(std::move(lookup_result.headers_)); + headers_promise->set_value(std::make_pair(std::move(lookup_result.headers_), end_stream)); }); auto future = headers_promise->get_future(); EXPECT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(5))); return future.get(); } -std::string HttpCacheImplementationTest::getBody(LookupContext& context, uint64_t start, - uint64_t end) { +std::pair HttpCacheImplementationTest::getBody(LookupContext& context, + uint64_t start, uint64_t end) { AdjustedByteRange range(start, end); - auto body_promise = std::make_shared>(); - context.getBody(range, [body_promise](Buffer::InstancePtr&& data) { + auto body_promise = std::make_shared>>(); + context.getBody(range, [body_promise](Buffer::InstancePtr&& data, bool end_stream) { EXPECT_NE(data, nullptr); - body_promise->set_value(data ? data->toString() : ""); + body_promise->set_value(data ? std::make_pair(data->toString(), end_stream) + : std::make_pair("", end_stream)); }); auto future = body_promise->get_future(); EXPECT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(5))); @@ -248,16 +254,19 @@ testing::AssertionResult HttpCacheImplementationTest::expectLookupSuccessWithBod if (!lookup_context) { return AssertionFailure() << "Expected nonnull lookup_context"; } - const std::string actual_body = getBody(*lookup_context, 0, body.size()); + const auto [actual_body, end_stream] = getBody(*lookup_context, 0, body.size()); if (body != actual_body) { return AssertionFailure() << "Expected body == " << body << "\n Actual: " << actual_body; } - if (lookup_result_.has_trailers_) { + if (!end_stream) { const Http::TestResponseTrailerMapImpl actual_trailers = getTrailers(*lookup_context); if (trailers != actual_trailers) { return AssertionFailure() << "Expected trailers == " << trailers << "\n Actual: " << actual_trailers; } + } else if (!trailers.empty()) { + return AssertionFailure() << "Expected trailers == " << trailers + << "\n Actual: end_stream after body"; } return AssertionSuccess(); } @@ -443,7 +452,7 @@ TEST_P(HttpCacheImplementationTest, StreamingPut) { ASSERT_EQ(CacheEntryStatus::Ok, lookup_result_.cache_entry_status_); ASSERT_NE(nullptr, lookup_result_.headers_); ASSERT_EQ(13, lookup_result_.content_length_); - ASSERT_EQ("Hello, World!", getBody(*name_lookup, 0, 13)); + ASSERT_THAT(getBody(*name_lookup, 0, 13), testing::Pair("Hello, World!", true)); name_lookup->onDestroy(); } @@ -770,7 +779,6 @@ TEST_P(HttpCacheImplementationTest, PutGetWithTrailers) { IsOk()); EXPECT_TRUE(expectLookupSuccessWithBodyAndTrailers(lookup(request_path1).get(), new_body1, response_trailers)); - EXPECT_TRUE(lookup_result_.has_trailers_); } TEST_P(HttpCacheImplementationTest, EmptyTrailers) { @@ -786,7 +794,6 @@ TEST_P(HttpCacheImplementationTest, EmptyTrailers) { ASSERT_THAT(insert(std::move(name_lookup_context), response_headers, body1), IsOk()); name_lookup_context = lookup(request_path1); EXPECT_TRUE(expectLookupSuccessWithBodyAndTrailers(name_lookup_context.get(), body1)); - EXPECT_FALSE(lookup_result_.has_trailers_); } } // namespace Cache diff --git a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h index 53553010fbaf..d172f95fab32 100644 --- a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h +++ b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h @@ -71,9 +71,11 @@ class HttpCacheImplementationTest const Http::TestResponseHeaderMapImpl& headers, const absl::string_view body, std::chrono::milliseconds timeout = std::chrono::seconds(1)); - Http::ResponseHeaderMapPtr getHeaders(LookupContext& context); + // Returns the headers and a bool for end_stream. + std::pair getHeaders(LookupContext& context); - std::string getBody(LookupContext& context, uint64_t start, uint64_t end); + // Returns a body chunk and a bool for end_stream. + std::pair getBody(LookupContext& context, uint64_t start, uint64_t end); Http::TestResponseTrailerMapImpl getTrailers(LookupContext& context); @@ -94,6 +96,7 @@ class HttpCacheImplementationTest std::unique_ptr delegate_; VaryAllowList vary_allow_list_; LookupResult lookup_result_; + bool lookup_end_stream_after_headers_; Http::TestRequestHeaderMapImpl request_headers_; Event::SimulatedTimeSystem time_system_; Event::MockDispatcher dispatcher_; diff --git a/test/extensions/filters/http/cache/http_cache_test.cc b/test/extensions/filters/http/cache/http_cache_test.cc index 3d330dc158ca..3d63e2087ba4 100644 --- a/test/extensions/filters/http/cache/http_cache_test.cc +++ b/test/extensions/filters/http/cache/http_cache_test.cc @@ -174,12 +174,12 @@ class LookupRequestTest : public testing::TestWithParam { LookupResult makeLookupResult(const LookupRequest& lookup_request, const Http::TestResponseHeaderMapImpl& response_headers, - uint64_t content_length = 0, bool has_trailers = false) { + absl::optional content_length = absl::nullopt) { // For the purpose of the test, set the response_time to the date header value. ResponseMetadata metadata = {CacheHeadersUtils::httpTime(response_headers.Date())}; return lookup_request.makeLookupResult( std::make_unique(response_headers), std::move(metadata), - content_length, has_trailers); + content_length); } INSTANTIATE_TEST_SUITE_P(ResultMatchesExpectation, LookupRequestTest, @@ -194,7 +194,7 @@ TEST_P(LookupRequestTest, ResultWithoutBodyMatchesExpectation) { const Http::TestResponseHeaderMapImpl response_headers( {{"cache-control", GetParam().response_cache_control}, {"date", formatter_.fromTime(response_date)}}); - const LookupResult lookup_response = makeLookupResult(lookup_request, response_headers); + const LookupResult lookup_response = makeLookupResult(lookup_request, response_headers, 0); EXPECT_EQ(GetParam().expected_cache_entry_status, lookup_response.cache_entry_status_); ASSERT_TRUE(lookup_response.headers_); @@ -202,7 +202,24 @@ TEST_P(LookupRequestTest, ResultWithoutBodyMatchesExpectation) { EXPECT_THAT(*lookup_response.headers_, HeaderHasValueRef(Http::CustomHeaders::get().Age, GetParam().expected_age)); EXPECT_EQ(lookup_response.content_length_, 0); - EXPECT_FALSE(lookup_response.has_trailers_); +} + +TEST_P(LookupRequestTest, ResultWithUnknownContentLengthMatchesExpectation) { + request_headers_.setReferenceKey(Http::CustomHeaders::get().CacheControl, + GetParam().request_cache_control); + const SystemTime request_time = GetParam().request_time, response_date = GetParam().response_date; + const LookupRequest lookup_request(request_headers_, request_time, vary_allow_list_); + const Http::TestResponseHeaderMapImpl response_headers( + {{"cache-control", GetParam().response_cache_control}, + {"date", formatter_.fromTime(response_date)}}); + const LookupResult lookup_response = makeLookupResult(lookup_request, response_headers); + + EXPECT_EQ(GetParam().expected_cache_entry_status, lookup_response.cache_entry_status_); + ASSERT_TRUE(lookup_response.headers_); + EXPECT_THAT(*lookup_response.headers_, Http::IsSupersetOfHeaders(response_headers)); + EXPECT_THAT(*lookup_response.headers_, + HeaderHasValueRef(Http::CustomHeaders::get().Age, GetParam().expected_age)); + EXPECT_FALSE(lookup_response.content_length_.has_value()); } TEST_P(LookupRequestTest, ResultWithBodyMatchesExpectation) { @@ -223,7 +240,6 @@ TEST_P(LookupRequestTest, ResultWithBodyMatchesExpectation) { EXPECT_THAT(*lookup_response.headers_, HeaderHasValueRef(Http::CustomHeaders::get().Age, GetParam().expected_age)); EXPECT_EQ(lookup_response.content_length_, content_length); - EXPECT_FALSE(lookup_response.has_trailers_); } TEST_F(LookupRequestTest, ExpiredViaFallbackheader) { @@ -346,7 +362,7 @@ TEST_P(LookupRequestTest, ResultWithBodyAndTrailersMatchesExpectation) { {"date", formatter_.fromTime(response_date)}}); const uint64_t content_length = 5; const LookupResult lookup_response = - makeLookupResult(lookup_request, response_headers, content_length, /*has_trailers=*/true); + makeLookupResult(lookup_request, response_headers, content_length); EXPECT_EQ(GetParam().expected_cache_entry_status, lookup_response.cache_entry_status_); ASSERT_TRUE(lookup_response.headers_ != nullptr); @@ -355,7 +371,6 @@ TEST_P(LookupRequestTest, ResultWithBodyAndTrailersMatchesExpectation) { EXPECT_THAT(*lookup_response.headers_, HeaderHasValueRef(Http::CustomHeaders::get().Age, GetParam().expected_age)); EXPECT_EQ(lookup_response.content_length_, content_length); - EXPECT_TRUE(lookup_response.has_trailers_); } TEST_F(LookupRequestTest, HttpScheme) { diff --git a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc index 52aeddd352a2..208163fb9145 100644 --- a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc +++ b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc @@ -335,29 +335,6 @@ class FileSystemHttpCacheTestWithMockFiles : public FileSystemHttpCacheTest { return ret; } - LookupResult testLookupResult() { - // Use a different mock file handle while in this function, then restore the original. - absl::Cleanup restore_file_handle([this, original_file_handle = mock_async_file_handle_]() { - mock_async_file_handle_ = original_file_handle; - }); - mock_async_file_handle_ = std::make_shared(mock_async_file_manager_); - LookupResult result; - { - auto lookup = testLookupContext(); - absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); - EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - EXPECT_CALL(*mock_async_file_handle_, read(_, _, _)).Times(2); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); - mock_async_file_manager_->nextActionCompletes( - absl::StatusOr(testHeaderBlock(0))); - mock_async_file_manager_->nextActionCompletes( - absl::StatusOr(testHeaderBuffer())); - } - // Consume the close from the queue that occurs when lookup context is destroyed. - mock_async_file_manager_->nextActionCompletes(absl::OkStatus()); - return result; - } - protected: ::testing::NiceMock mock_singleton_manager_; std::shared_ptr mock_async_file_manager_factory_ = @@ -484,7 +461,7 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedOpenForReadReturnsMiss) { absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(absl::UnknownError("Intentionally failed to open file"))); // File handle didn't get used but is expected to be closed. @@ -505,7 +482,7 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfHeaderBlockInvalidatesT LookupResult result; EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); @@ -544,7 +521,7 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, ReadWithInvalidHeaderBlockInvalidat LookupResult result; EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); @@ -565,7 +542,7 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfHeaderProtoInvalidatesT EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); mock_async_file_manager_->nextActionCompletes( @@ -585,10 +562,14 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfBodyInvalidatesTheCache auto lookup = testLookupContext(); absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; + bool end_stream_after_headers = true; // initialized wrong to ensure it's set. EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool es) { + result = std::move(r); + end_stream_after_headers = es; + }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); mock_async_file_manager_->nextActionCompletes( @@ -597,9 +578,11 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfBodyInvalidatesTheCache absl::StatusOr(testHeaderBuffer())); // result should be populated. EXPECT_NE(result.cache_entry_status_, CacheEntryStatus::Unusable); + EXPECT_FALSE(end_stream_after_headers); EXPECT_CALL(*mock_async_file_handle_, read(_, _, _)); - lookup->getBody(AdjustedByteRange(0, 8), - [&](Buffer::InstancePtr body) { EXPECT_EQ(body.get(), nullptr); }); + lookup->getBody(AdjustedByteRange(0, 8), [&](Buffer::InstancePtr body, bool /*end_stream*/) { + EXPECT_EQ(body.get(), nullptr); + }); EXPECT_CALL(*mock_async_file_manager_, stat(_, _)); EXPECT_CALL(*mock_async_file_manager_, unlink(_, _)); mock_async_file_manager_->nextActionCompletes( @@ -614,10 +597,14 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfTrailersInvalidatesTheC auto lookup = testLookupContext(); absl::Cleanup destroy_lookup([&lookup]() { lookup->onDestroy(); }); LookupResult result; + bool end_stream_after_headers = true; EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::size(), headers_size_, _)); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool es) { + result = std::move(r); + end_stream_after_headers = es; + }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); mock_async_file_manager_->nextActionCompletes( @@ -626,9 +613,12 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfTrailersInvalidatesTheC absl::StatusOr(testHeaderBuffer())); // result should be populated. EXPECT_NE(result.cache_entry_status_, CacheEntryStatus::Unusable); + EXPECT_FALSE(end_stream_after_headers); EXPECT_CALL(*mock_async_file_handle_, read(_, 8, _)); - lookup->getBody(AdjustedByteRange(0, 8), - [&](Buffer::InstancePtr body) { EXPECT_EQ(body->toString(), "beepbeep"); }); + lookup->getBody(AdjustedByteRange(0, 8), [&](Buffer::InstancePtr body, bool end_stream) { + EXPECT_EQ(body->toString(), "beepbeep"); + EXPECT_FALSE(end_stream); + }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique("beepbeep"))); EXPECT_CALL(*mock_async_file_handle_, read(_, _, _)); @@ -646,13 +636,17 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfTrailersInvalidatesTheC } TEST_F(FileSystemHttpCacheTestWithMockFiles, ReadWithMultipleBlocksWorksCorrectly) { + trailers_size_ = 0; auto lookup = testLookupContext(); LookupResult result; EXPECT_CALL(*mock_async_file_manager_, openExistingFile(_, _, _)); EXPECT_CALL(*mock_async_file_handle_, read(0, CacheFileFixedBlock::size(), _)); EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::offsetToHeaders(), headers_size_, _)); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool end_stream) { + result = std::move(r); + EXPECT_FALSE(end_stream) << "in headers"; + }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(mock_async_file_handle_)); mock_async_file_manager_->nextActionCompletes( @@ -663,12 +657,16 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, ReadWithMultipleBlocksWorksCorrectl read(CacheFileFixedBlock::offsetToHeaders() + headers_size_, 4, _)); EXPECT_CALL(*mock_async_file_handle_, read(CacheFileFixedBlock::offsetToHeaders() + headers_size_ + 4, 4, _)); - lookup->getBody(AdjustedByteRange(0, 4), - [&](Buffer::InstancePtr body) { EXPECT_EQ(body->toString(), "beep"); }); + lookup->getBody(AdjustedByteRange(0, 4), [&](Buffer::InstancePtr body, bool end_stream) { + EXPECT_EQ(body->toString(), "beep"); + EXPECT_FALSE(end_stream) << "in body part 1"; + }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique("beep"))); - lookup->getBody(AdjustedByteRange(4, 8), - [&](Buffer::InstancePtr body) { EXPECT_EQ(body->toString(), "boop"); }); + lookup->getBody(AdjustedByteRange(4, 8), [&](Buffer::InstancePtr body, bool end_stream) { + EXPECT_EQ(body->toString(), "boop"); + EXPECT_TRUE(end_stream) << "in body part 2"; + }); mock_async_file_manager_->nextActionCompletes( absl::StatusOr(std::make_unique("boop"))); // While we're here, incidentally test the behavior of aborting a lookup in progress @@ -687,7 +685,7 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, DestroyingALookupWithFileActionInFl EXPECT_CALL(*mock_async_file_manager_, mockCancel()).WillOnce([this]() { mock_async_file_manager_->queue_.pop_front(); }); - lookup->getHeaders([&](LookupResult&& r) { result = std::move(r); }); + lookup->getHeaders([&](LookupResult&& r, bool /*end_stream*/) { result = std::move(r); }); // File wasn't used in this test but is expected to be closed. EXPECT_OK(mock_async_file_handle_->close([](absl::Status) {})); } From 114021561e44d529d660d95c7cad3f5c734dfa89 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 23 Aug 2024 09:53:17 +0100 Subject: [PATCH 22/53] bazel: Remove `envoy_package` from tools BUILD files (#35771) Currently you have to install most of envoys deps to use tooling or access repo metadata - this exposes (some of) the tools/targets without that being necessary Signed-off-by: Ryan Northey --- BUILD | 5 ++-- changelogs/BUILD | 5 +--- test/integration/BUILD | 2 +- test/integration/hotrestart_test.sh | 6 ++-- tools/BUILD | 31 -------------------- tools/base/BUILD | 3 -- tools/bootstrap2pb/BUILD | 24 +++++++++++++++ tools/code_format/config.yaml | 2 ++ tools/socket_passing/BUILD | 16 ++++++++++ tools/{ => socket_passing}/socket_passing.py | 0 10 files changed, 49 insertions(+), 45 deletions(-) create mode 100644 tools/bootstrap2pb/BUILD create mode 100644 tools/socket_passing/BUILD rename tools/{ => socket_passing}/socket_passing.py (100%) diff --git a/BUILD b/BUILD index c7b88cdece13..d3d06671ae7b 100644 --- a/BUILD +++ b/BUILD @@ -1,10 +1,7 @@ -load("//bazel:envoy_build_system.bzl", "envoy_package") load("//tools/python:namespace.bzl", "envoy_py_namespace") licenses(["notice"]) # Apache 2 -envoy_package() - envoy_py_namespace() exports_files([ @@ -22,11 +19,13 @@ exports_files([ alias( name = "envoy", actual = "//source/exe:envoy", + visibility = ["//visibility:public"], ) alias( name = "envoy.stripped", actual = "//source/exe:envoy-static.stripped", + visibility = ["//visibility:public"], ) filegroup( diff --git a/changelogs/BUILD b/changelogs/BUILD index e36d6bfbb93a..26d4cd5f88fe 100644 --- a/changelogs/BUILD +++ b/changelogs/BUILD @@ -1,9 +1,5 @@ -load("//bazel:envoy_build_system.bzl", "envoy_package") - licenses(["notice"]) # Apache 2 -envoy_package() - exports_files([ "sections.yaml", ]) @@ -11,6 +7,7 @@ exports_files([ filegroup( name = "changelogs", srcs = glob(["*.*.*.yaml"]) + ["current.yaml"], + visibility = ["//visibility:public"], ) genrule( diff --git a/test/integration/BUILD b/test/integration/BUILD index 1e2e7c57c4f8..7e6150068b9d 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -392,7 +392,7 @@ envoy_sh_test( data = [ "test_utility.sh", "//test/config/integration:server_config_files", - "//tools:socket_passing", + "//tools/socket_passing", ], # Hot restart does not apply on Windows, skipping tags = ["skip_on_windows"], diff --git a/test/integration/hotrestart_test.sh b/test/integration/hotrestart_test.sh index 035382a15b44..a1a7f6e81cf5 100755 --- a/test/integration/hotrestart_test.sh +++ b/test/integration/hotrestart_test.sh @@ -137,7 +137,7 @@ function run_testsuite() { sleep 3 UPDATED_HOT_RESTART_JSON="${TEST_TMPDIR}"/hot_restart_updated."${TEST_INDEX}".yaml - "${TEST_SRCDIR}/envoy"/tools/socket_passing "-o" "${HOT_RESTART_JSON}" "-a" "${ADMIN_ADDRESS_PATH_0}" \ + "${TEST_SRCDIR}/envoy"/tools/socket_passing/socket_passing "-o" "${HOT_RESTART_JSON}" "-a" "${ADMIN_ADDRESS_PATH_0}" \ "-u" "${UPDATED_HOT_RESTART_JSON}" # Send SIGUSR1 signal to the first server, this should not kill it. Also send SIGHUP which should @@ -205,7 +205,7 @@ function run_testsuite() { start_test "Checking that listener addresses have not changed" HOT_RESTART_JSON_1="${TEST_TMPDIR}"/hot_restart.1."${TEST_INDEX}".yaml - "${TEST_SRCDIR}/envoy"/tools/socket_passing "-o" "${UPDATED_HOT_RESTART_JSON}" "-a" "${ADMIN_ADDRESS_PATH_1}" \ + "${TEST_SRCDIR}/envoy"/tools/socket_passing/socket_passing "-o" "${UPDATED_HOT_RESTART_JSON}" "-a" "${ADMIN_ADDRESS_PATH_1}" \ "-u" "${HOT_RESTART_JSON_1}" CONFIG_DIFF=$(diff "${UPDATED_HOT_RESTART_JSON}" "${HOT_RESTART_JSON_1}") [[ -z "${CONFIG_DIFF}" ]] @@ -264,7 +264,7 @@ function run_testsuite() { start_test "Checking that listener addresses have not changed" HOT_RESTART_JSON_2="${TEST_TMPDIR}"/hot_restart.2."${TEST_INDEX}".yaml - "${TEST_SRCDIR}/envoy"/tools/socket_passing "-o" "${UPDATED_HOT_RESTART_JSON}" "-a" "${ADMIN_ADDRESS_PATH_2}" \ + "${TEST_SRCDIR}/envoy"/tools/socket_passing/socket_passing "-o" "${UPDATED_HOT_RESTART_JSON}" "-a" "${ADMIN_ADDRESS_PATH_2}" \ "-u" "${HOT_RESTART_JSON_2}" CONFIG_DIFF=$(diff "${UPDATED_HOT_RESTART_JSON}" "${HOT_RESTART_JSON_2}") [[ -z "${CONFIG_DIFF}" ]] diff --git a/tools/BUILD b/tools/BUILD index 8dbb978d51ef..fbf51940f051 100644 --- a/tools/BUILD +++ b/tools/BUILD @@ -1,16 +1,8 @@ load("@rules_python//python:defs.bzl", "py_library") -load( - "//bazel:envoy_build_system.bzl", - "envoy_cc_binary", - "envoy_package", - "envoy_py_test_binary", -) load("//tools/python:namespace.bzl", "envoy_py_namespace") licenses(["notice"]) # Apache 2 -envoy_package() - envoy_py_namespace() exports_files([ @@ -23,13 +15,6 @@ py_binary( srcs = ["stack_decode.py"], ) -envoy_py_test_binary( - name = "socket_passing", - srcs = [ - "socket_passing.py", - ], -) - py_library( name = "run_command", srcs = [ @@ -37,19 +22,3 @@ py_library( ], visibility = ["//visibility:public"], ) - -envoy_cc_binary( - name = "bootstrap2pb", - srcs = ["bootstrap2pb.cc"], - deps = [ - "//source/common/api:api_lib", - "//source/common/common:assert_lib", - "//source/common/common:random_generator_lib", - "//source/common/protobuf:message_validator_lib", - "//source/common/protobuf:utility_lib", - "//source/common/stats:isolated_store_lib", - "//source/exe:platform_impl_lib", - "//test/test_common:test_version_linkstamp", - "@envoy_api//envoy/config/bootstrap/v2:pkg_cc_proto", - ], -) diff --git a/tools/base/BUILD b/tools/base/BUILD index 494b97fc6ec9..a9495572db96 100644 --- a/tools/base/BUILD +++ b/tools/base/BUILD @@ -1,10 +1,7 @@ load("@rules_python//python:pip.bzl", "compile_pip_requirements") -load("//bazel:envoy_build_system.bzl", "envoy_package") licenses(["notice"]) # Apache 2 -envoy_package() - exports_files([ "entry_point.py", ]) diff --git a/tools/bootstrap2pb/BUILD b/tools/bootstrap2pb/BUILD new file mode 100644 index 000000000000..295a305e7ac5 --- /dev/null +++ b/tools/bootstrap2pb/BUILD @@ -0,0 +1,24 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_binary", + "envoy_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_cc_binary( + name = "bootstrap2pb", + srcs = ["bootstrap2pb.cc"], + deps = [ + "//source/common/api:api_lib", + "//source/common/common:assert_lib", + "//source/common/common:random_generator_lib", + "//source/common/protobuf:message_validator_lib", + "//source/common/protobuf:utility_lib", + "//source/common/stats:isolated_store_lib", + "//source/exe:platform_impl_lib", + "//test/test_common:test_version_linkstamp", + ], +) diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index d1e90409b8fb..99c4774846c1 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -61,6 +61,8 @@ paths: build_fixer: exclude: + - BUILD + - tools/BUILD - bazel/BUILD - bazel/external/ - bazel/toolchains/ diff --git a/tools/socket_passing/BUILD b/tools/socket_passing/BUILD new file mode 100644 index 000000000000..5d139f68ff05 --- /dev/null +++ b/tools/socket_passing/BUILD @@ -0,0 +1,16 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", + "envoy_py_test_binary", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_py_test_binary( + name = "socket_passing", + srcs = [ + "socket_passing.py", + ], +) diff --git a/tools/socket_passing.py b/tools/socket_passing/socket_passing.py similarity index 100% rename from tools/socket_passing.py rename to tools/socket_passing/socket_passing.py From 7344490c8240d341ba78c1f1205adac86a033a32 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:44:59 +0100 Subject: [PATCH 23/53] deps: Bump `envoy_examples` -> 0.0.4 (#35799) Created by Envoy dependency bot for @phlax Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 47a9dd2d4073..28fe370ea400 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -96,12 +96,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "envoy_examples", project_desc = "Envoy proxy examples", project_url = "https://github.com/envoyproxy/examples", - version = "0.0.2", - sha256 = "c19d5542eb1b105c60a13170c7cdc8f15b489ae06d49374962ea131a50c13c49", + version = "0.0.4", + sha256 = "a90a00ebea98a06e521d1c80c137085b542ff5c5ed6fec23afcb1fc165cc4b62", strip_prefix = "examples-{version}", urls = ["https://github.com/envoyproxy/examples/archive/v{version}.tar.gz"], use_category = ["test_only"], - release_date = "2024-08-07", + release_date = "2024-08-22", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/envoyproxy/examples/blob/v{version}/LICENSE", From 2196f59222d63fc2ff443b957c8f19ee624eaa18 Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Fri, 23 Aug 2024 09:54:20 -0400 Subject: [PATCH 24/53] happy-eyeballs: code-comments for sorting algorithm (#35772) Signed-off-by: Adi Suissa-Peleg --- .../network/happy_eyeballs_connection_impl.cc | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/source/common/network/happy_eyeballs_connection_impl.cc b/source/common/network/happy_eyeballs_connection_impl.cc index a68392b05c3b..63695464edeb 100644 --- a/source/common/network/happy_eyeballs_connection_impl.cc +++ b/source/common/network/happy_eyeballs_connection_impl.cc @@ -102,15 +102,25 @@ HappyEyeballsConnectionProvider::sortAddressesWithConfig( if (!happy_eyeballs_config.has_value()) { return sortAddresses(in); } - ENVOY_LOG_EVENT(debug, "happy_eyeballs_sort_address", "sort address with happy_eyeballs config."); + // Sort the addresses according to https://datatracker.ietf.org/doc/html/rfc8305#section-4. + // Currently the first_address_family version and count options are supported. This allows + // specifying the address family version to prefer over the other, and the number (count) + // of addresses in that family to attempt before moving to the other family. + // If no family version is specified, the version is taken from the first + // address in the list. The default count is 1. As an example, assume the + // family version is v6, and the count is 3, then the output list will be: + // [3*v6, 1*v4, 3*v6, 1*v4, ...] (assuming sufficient addresses exist in the input). + ENVOY_LOG_EVENT(trace, "happy_eyeballs_sort_address", "sort address with happy_eyeballs config."); std::vector address_list; address_list.reserve(in.size()); // First_family_ip_version defaults to the first valid ip version - // unless overwritten by happy_eyeballs_config. + // unless overwritten by happy_eyeballs_config. There must be at least one + // entry in the vector that is passed to the function. + ASSERT(in.size() > 0); Address::IpVersion first_family_ip_version = in[0].get()->ip()->version(); - auto first_address_family_count = + const auto first_address_family_count = PROTOBUF_GET_WRAPPED_OR_DEFAULT(happy_eyeballs_config.value(), first_address_family_count, 1); switch (happy_eyeballs_config.value().first_address_family_version()) { case envoy::config::cluster::v3::UpstreamConnectionOptions::DEFAULT: @@ -132,7 +142,6 @@ HappyEyeballsConnectionProvider::sortAddressesWithConfig( return !hasMatchingIpVersion(first_family_ip_version, val); }); - // Address::IpVersion first_family_ip_version(Address::IpVersion::v4); while (first != in.end() || other != in.end()) { uint32_t count = 0; while (first != in.end() && ++count <= first_address_family_count) { From 36f2fee4bc5e82ace7443886698c148442b74c8a Mon Sep 17 00:00:00 2001 From: David Schinazi Date: Fri, 23 Aug 2024 07:43:36 -0700 Subject: [PATCH 25/53] Add /nostalebot repokitteh option (#35784) Commit Message: Add /nostalebot repokitteh option Additional Description: This will reduce user toil and maintainer load. Risk Level: Low Testing: NA Docs Changes: None Release Notes: None Platform Specific Features: None Signed-off-by: David Schinazi --- repokitteh.star | 5 +++++ source/docs/repokitteh.md | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/repokitteh.star b/repokitteh.star index 9ee51d6afe40..1e67dbe810c6 100644 --- a/repokitteh.star +++ b/repokitteh.star @@ -61,3 +61,8 @@ def _milestone(): github.issue_label('milestone/review') handlers.command(name='milestone', func=_milestone) + +def _nostalebot(): + github.issue_label('no stalebot') + +handlers.command(name='nostalebot', func=_nostalebot) diff --git a/source/docs/repokitteh.md b/source/docs/repokitteh.md index d1d8bd20ad31..a9aa2cf9906d 100644 --- a/source/docs/repokitteh.md +++ b/source/docs/repokitteh.md @@ -114,3 +114,11 @@ Two types of approvals: ``` will labels the PR commented on with `backport/review`. + +### No stalebot labeling + +``` +/nostalebot +``` + +will label the issue or PR commented on with `no stalebot`. From 84c8da7540e4e5064f6a6dffc66825668f6220e4 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 23 Aug 2024 16:02:50 +0100 Subject: [PATCH 26/53] test/coverage: Reduce quic to fix fail (#35826) Commit Message: Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] Signed-off-by: Ryan Northey --- test/per_file_coverage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index 6cca2bbba585..c889f231791e 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -16,7 +16,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/memory:74.5" # tcmalloc code path is not enabled in coverage build, only gperf tcmalloc, see PR#32589 "source/common/network:94.4" # Flaky, `activateFileEvents`, `startSecureTransport` and `ioctl`, listener_socket do not always report LCOV "source/common/network/dns_resolver:91.4" # A few lines of MacOS code not tested in linux scripts. Tested in MacOS scripts -"source/common/quic:93.8" +"source/common/quic:93.7" "source/common/secret:95.4" "source/common/signal:87.2" # Death tests don't report LCOV "source/common/thread:0.0" # Death tests don't report LCOV From 3d7486abb40cf7102483e2de7d0138e1de8784d3 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Fri, 23 Aug 2024 11:22:45 -0500 Subject: [PATCH 27/53] mobile: Remove toBridge from Envoy::Http::Client (#35830) `Envoy::Http::Client` no longer uses C wrapper types, so the `toBridge` name no longer makes sense. Risk Level: low (rename only) Testing: CI Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a Signed-off-by: Fredy Wijaya --- mobile/library/common/http/client.cc | 16 ++++++++-------- mobile/library/common/http/client.h | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mobile/library/common/http/client.cc b/mobile/library/common/http/client.cc index d0338595c6ff..3a3a8f039e20 100644 --- a/mobile/library/common/http/client.cc +++ b/mobile/library/common/http/client.cc @@ -134,7 +134,7 @@ void Client::DirectStreamCallbacks::encodeData(Buffer::Instance& data, bool end_ if (bytes_to_send_ > 0 || !explicit_flow_control_) { // We shouldn't be calling sendDataToBridge with newly arrived data if there's buffered data. ASSERT(!response_data_.get() || response_data_->length() == 0); - sendDataToBridge(data, end_stream); + sendData(data, end_stream); } // If not all the bytes have been sent up, buffer any remaining data in response_data. @@ -147,7 +147,7 @@ void Client::DirectStreamCallbacks::encodeData(Buffer::Instance& data, bool end_ } } -void Client::DirectStreamCallbacks::sendDataToBridge(Buffer::Instance& data, bool end_stream) { +void Client::DirectStreamCallbacks::sendData(Buffer::Instance& data, bool end_stream) { ASSERT(!explicit_flow_control_ || bytes_to_send_ > 0); // Cap by bytes_to_send_ if and only if applying explicit flow control. @@ -202,10 +202,10 @@ void Client::DirectStreamCallbacks::encodeTrailers(const ResponseTrailerMap& tra return; } - sendTrailersToBridge(trailers); + sendTrailers(trailers); } -void Client::DirectStreamCallbacks::sendTrailersToBridge(const ResponseTrailerMap& trailers) { +void Client::DirectStreamCallbacks::sendTrailers(const ResponseTrailerMap& trailers) { ENVOY_LOG(debug, "[S{}] dispatching to platform response trailers for stream:\n{}", direct_stream_.stream_handle_, trailers); @@ -237,13 +237,13 @@ void Client::DirectStreamCallbacks::resumeData(size_t bytes_to_send) { // 1) it has been received from the peer and // 2) there are no trailers if (hasDataToSend()) { - sendDataToBridge(*response_data_, remote_end_stream_received_ && !response_trailers_.get()); + sendData(*response_data_, remote_end_stream_received_ && !response_trailers_.get()); bytes_to_send_ = 0; } // If all buffered data has been sent, send and free up trailers. if (!hasDataToSend() && response_trailers_.get() && bytes_to_send_ > 0) { - sendTrailersToBridge(*response_trailers_); + sendTrailers(*response_trailers_); response_trailers_.reset(); bytes_to_send_ = 0; } @@ -317,10 +317,10 @@ void Client::DirectStreamCallbacks::onError() { http_client_.removeStream(direct_stream_.stream_handle_); direct_stream_.request_decoder_ = nullptr; - sendErrorToBridge(); + sendError(); } -void Client::DirectStreamCallbacks::sendErrorToBridge() { +void Client::DirectStreamCallbacks::sendError() { if (remote_end_stream_forwarded_) { // If the request was not fully sent, but the response was complete, Envoy // will reset the stream after sending the fin bit. Don't pass this class of diff --git a/mobile/library/common/http/client.h b/mobile/library/common/http/client.h index 140e73e3205e..046588e53fea 100644 --- a/mobile/library/common/http/client.h +++ b/mobile/library/common/http/client.h @@ -199,9 +199,9 @@ class Client : public Logger::Loggable { (remote_end_stream_received_ && !remote_end_stream_forwarded_ && !response_trailers_)); } - void sendDataToBridge(Buffer::Instance& data, bool end_stream); - void sendTrailersToBridge(const ResponseTrailerMap& trailers); - void sendErrorToBridge(); + void sendData(Buffer::Instance& data, bool end_stream); + void sendTrailers(const ResponseTrailerMap& trailers); + void sendError(); envoy_stream_intel streamIntel(); envoy_final_stream_intel& finalStreamIntel(); From 09501db4f475ea8e2f0bec719ff7dc4d591bb8c4 Mon Sep 17 00:00:00 2001 From: yanavlasov Date: Fri, 23 Aug 2024 12:32:55 -0400 Subject: [PATCH 28/53] Separate state for tracking downstream end_stream in filter manager and HCM (#35815) Commit Message: Fix two bugs in processing of deferred requests. 1. Filter manager (FM) uses presence of the timestamp of receipt of the downstream end_stream to set the end_stream during filter chain resumption. If a complete request (with end_stream= true) was deferred, its filter chain iteration would start with the downstream end_stream flag set. If there is a decoder filter that pauses and resumes filer chain iteration, all filters after resumption will see end_stream as true. For example if a filter pauses in decodeHeaders() and then resumes in decodeData() all filters after that will have decodeHeaders() called with end_stream == true. This can cause request to be proxied by the router without the body. 2. The request trailers were also immediately available to filter manager when processing of a deferred request begins. If there is a filter that pauses and resumes iteration it makes filter manager incorrectly process trailers as though they were added by the filter that paused iteration. This causes trailers to be processed by filter chain twice triggering asserts. The same problem is also present when HCM recreates the stream with body (i.e. for internal redirect). This change makes filter manager use its own, already existing, flag `observed_decode_end_stream_` for tracking state of downstream end_stream flag when resuming the filter chain, instead of the timestamp of the end_stream receipt from downstream client. HCM continues to use the presence of the end_stream timestamp as the indicator of completed client's stream. This change can be reverted by setting the envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream runtime flag to false. Risk Level: Medium, affects deferred request processing Testing: Unit tests Docs Changes: N/A Release Notes: Yes Platform Specific Features: N/A Runtime guard: envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream Fixes #35814 Signed-off-by: Yan Avlasov --- changelogs/current.yaml | 6 ++ source/common/http/conn_manager_impl.cc | 76 +++++++++++-------- source/common/http/conn_manager_impl.h | 7 +- source/common/http/filter_manager.h | 26 ++++++- source/common/runtime/runtime_features.cc | 1 + test/integration/BUILD | 1 + test/integration/filters/BUILD | 14 ++++ ...stop_in_headers_continue_in_data_filter.cc | 34 +++++++++ .../multiplexed_integration_test.cc | 67 ++++++++++++---- 9 files changed, 179 insertions(+), 53 deletions(-) create mode 100644 test/integration/filters/stop_in_headers_continue_in_data_filter.cc diff --git a/changelogs/current.yaml b/changelogs/current.yaml index cb4c0defc775..571570861bdc 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -93,6 +93,12 @@ bug_fixes: change: | RBAC will now allow stat prefixes configured in per-route config to override the base config's stat prefix. +- area: http + change: | + Fixed a bug where an incomplete request (missing body or trailers) may be proxied to the upstream when the limit on + the number of requests per I/O cycle is configured and an HTTP decoder filter that pauses filter chain is present. This behavior + can be reverted by setting the runtime guard ``envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream`` + to false. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc index 65a2b032ec4e..f3ba58afdfb6 100644 --- a/source/common/http/conn_manager_impl.cc +++ b/source/common/http/conn_manager_impl.cc @@ -247,8 +247,9 @@ void ConnectionManagerImpl::doEndStream(ActiveStream& stream, bool check_for_def // here is when Envoy "ends" the stream by calling recreateStream at which point recreateStream // explicitly nulls out response_encoder to avoid the downstream being notified of the // Envoy-internal stream instance being ended. - if (stream.response_encoder_ != nullptr && (!stream.filter_manager_.decoderObservedEndStream() || - !stream.state_.codec_saw_local_complete_)) { + if (stream.response_encoder_ != nullptr && + (!stream.filter_manager_.hasLastDownstreamByteReceived() || + !stream.state_.codec_saw_local_complete_)) { // Indicate local is complete at this point so that if we reset during a continuation, we don't // raise further data or trailers. ENVOY_STREAM_LOG(debug, "doEndStream() resetting stream", stream); @@ -294,7 +295,7 @@ void ConnectionManagerImpl::doEndStream(ActiveStream& stream, bool check_for_def // fully read, as there's no race condition to avoid. const bool connection_close = stream.filter_manager_.streamInfo().shouldDrainConnectionUponCompletion(); - const bool request_complete = stream.filter_manager_.decoderObservedEndStream(); + const bool request_complete = stream.filter_manager_.hasLastDownstreamByteReceived(); // Don't do delay close for HTTP/1.0 or if the request is complete. checkForDeferredClose(connection_close && (request_complete || http_10_sans_cl)); @@ -943,32 +944,35 @@ void ConnectionManagerImpl::ActiveStream::onIdleTimeout() { connection_manager_.stats_.named_.downstream_rq_idle_timeout_.inc(); filter_manager_.streamInfo().setResponseFlag(StreamInfo::CoreResponseFlag::StreamIdleTimeout); - sendLocalReply(Http::Utility::maybeRequestTimeoutCode(filter_manager_.decoderObservedEndStream()), - "stream timeout", nullptr, absl::nullopt, - StreamInfo::ResponseCodeDetails::get().StreamIdleTimeout); + sendLocalReply( + Http::Utility::maybeRequestTimeoutCode(filter_manager_.hasLastDownstreamByteReceived()), + "stream timeout", nullptr, absl::nullopt, + StreamInfo::ResponseCodeDetails::get().StreamIdleTimeout); } void ConnectionManagerImpl::ActiveStream::onRequestTimeout() { connection_manager_.stats_.named_.downstream_rq_timeout_.inc(); - sendLocalReply(Http::Utility::maybeRequestTimeoutCode(filter_manager_.decoderObservedEndStream()), - "request timeout", nullptr, absl::nullopt, - StreamInfo::ResponseCodeDetails::get().RequestOverallTimeout); + sendLocalReply( + Http::Utility::maybeRequestTimeoutCode(filter_manager_.hasLastDownstreamByteReceived()), + "request timeout", nullptr, absl::nullopt, + StreamInfo::ResponseCodeDetails::get().RequestOverallTimeout); } void ConnectionManagerImpl::ActiveStream::onRequestHeaderTimeout() { connection_manager_.stats_.named_.downstream_rq_header_timeout_.inc(); - sendLocalReply(Http::Utility::maybeRequestTimeoutCode(filter_manager_.decoderObservedEndStream()), - "request header timeout", nullptr, absl::nullopt, - StreamInfo::ResponseCodeDetails::get().RequestHeaderTimeout); + sendLocalReply( + Http::Utility::maybeRequestTimeoutCode(filter_manager_.hasLastDownstreamByteReceived()), + "request header timeout", nullptr, absl::nullopt, + StreamInfo::ResponseCodeDetails::get().RequestHeaderTimeout); } void ConnectionManagerImpl::ActiveStream::onStreamMaxDurationReached() { ENVOY_STREAM_LOG(debug, "Stream max duration time reached", *this); connection_manager_.stats_.named_.downstream_rq_max_duration_reached_.inc(); - sendLocalReply(Http::Utility::maybeRequestTimeoutCode(filter_manager_.decoderObservedEndStream()), - "downstream duration timeout", nullptr, - Grpc::Status::WellKnownGrpcStatus::DeadlineExceeded, - StreamInfo::ResponseCodeDetails::get().MaxDurationTimeout); + sendLocalReply( + Http::Utility::maybeRequestTimeoutCode(filter_manager_.hasLastDownstreamByteReceived()), + "downstream duration timeout", nullptr, Grpc::Status::WellKnownGrpcStatus::DeadlineExceeded, + StreamInfo::ResponseCodeDetails::get().MaxDurationTimeout); } void ConnectionManagerImpl::ActiveStream::chargeStats(const ResponseHeaderMap& headers) { @@ -1086,15 +1090,15 @@ bool ConnectionManagerImpl::ActiveStream::validateHeaders() { return true; } -bool ConnectionManagerImpl::ActiveStream::validateTrailers() { +bool ConnectionManagerImpl::ActiveStream::validateTrailers(RequestTrailerMap& trailers) { if (!header_validator_) { return true; } - auto validation_result = header_validator_->validateRequestTrailers(*request_trailers_); + auto validation_result = header_validator_->validateRequestTrailers(trailers); std::string failure_details(validation_result.details()); if (validation_result.ok()) { - auto transformation_result = header_validator_->transformRequestTrailers(*request_trailers_); + auto transformation_result = header_validator_->transformRequestTrailers(trailers); if (transformation_result.ok()) { return true; } @@ -1129,12 +1133,12 @@ bool ConnectionManagerImpl::ActiveStream::validateTrailers() { return false; } -void ConnectionManagerImpl::ActiveStream::maybeEndDecode(bool end_stream) { +void ConnectionManagerImpl::ActiveStream::maybeRecordLastByteReceived(bool end_stream) { // If recreateStream is called, the HCM rewinds state and may send more encodeData calls. - if (end_stream && !filter_manager_.decoderObservedEndStream()) { + if (end_stream && !filter_manager_.hasLastDownstreamByteReceived()) { filter_manager_.streamInfo().downstreamTiming().onLastDownstreamRxByteReceived( connection_manager_.dispatcher_->timeSource()); - ENVOY_STREAM_LOG(debug, "request end stream", *this); + ENVOY_STREAM_LOG(debug, "request end stream timestamp recorded", *this); } } @@ -1154,7 +1158,7 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(RequestHeaderMapSharedPt *headers); // We only want to record this when reading the headers the first time, not when recreating // a stream. - if (!filter_manager_.decoderObservedEndStream()) { + if (!filter_manager_.hasLastDownstreamByteReceived()) { filter_manager_.streamInfo().downstreamTiming().onLastDownstreamHeaderRxByteReceived( connection_manager_.dispatcher_->timeSource()); } @@ -1180,7 +1184,7 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(RequestHeaderMapSharedPt filter_manager_.streamInfo().protocol(protocol); // We end the decode here to mark that the downstream stream is complete. - maybeEndDecode(end_stream); + maybeRecordLastByteReceived(end_stream); if (!validateHeaders()) { ENVOY_STREAM_LOG(debug, "request headers validation failed\n{}", *this, *request_headers_); @@ -1458,7 +1462,7 @@ void ConnectionManagerImpl::ActiveStream::traceRequest() { void ConnectionManagerImpl::ActiveStream::decodeData(Buffer::Instance& data, bool end_stream) { ScopeTrackerScopeState scope(this, connection_manager_.read_callbacks_->connection().dispatcher()); - maybeEndDecode(end_stream); + maybeRecordLastByteReceived(end_stream); filter_manager_.streamInfo().addBytesReceived(data.length()); if (!state_.deferred_to_next_io_iteration_) { filter_manager_.decodeData(data, end_stream); @@ -1478,14 +1482,19 @@ void ConnectionManagerImpl::ActiveStream::decodeTrailers(RequestTrailerMapPtr&& resetIdleTimer(); ASSERT(!request_trailers_); - request_trailers_ = std::move(trailers); - if (!validateTrailers()) { - ENVOY_STREAM_LOG(debug, "request trailers validation failed:\n{}", *this, *request_trailers_); + if (!validateTrailers(*trailers)) { + ENVOY_STREAM_LOG(debug, "request trailers validation failed:\n{}", *this, *trailers); return; } - maybeEndDecode(true); + maybeRecordLastByteReceived(true); if (!state_.deferred_to_next_io_iteration_) { + request_trailers_ = std::move(trailers); filter_manager_.decodeTrailers(*request_trailers_); + } else { + // Save trailers in a different variable since `request_trailers_` is available to the filter + // manager via `requestTrailers()` callback and makes filter manager see trailers prematurely + // when deferred request is processed. + deferred_request_trailers_ = std::move(trailers); } } @@ -1776,7 +1785,7 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ResponseHeaderMap& heade // If we are destroying a stream before remote is complete and the connection does not support // multiplexing, we should disconnect since we don't want to wait around for the request to // finish. - if (!filter_manager_.decoderObservedEndStream()) { + if (!filter_manager_.hasLastDownstreamByteReceived()) { if (connection_manager_.codec_->protocol() < Protocol::Http2) { connection_manager_.drain_state_ = DrainState::Closing; } @@ -2221,7 +2230,7 @@ bool ConnectionManagerImpl::ActiveStream::onDeferredRequestProcessing() { } state_.deferred_to_next_io_iteration_ = false; bool end_stream = state_.deferred_end_stream_ && deferred_data_ == nullptr && - request_trailers_ == nullptr && deferred_metadata_.empty(); + deferred_request_trailers_ == nullptr && deferred_metadata_.empty(); filter_manager_.decodeHeaders(*request_headers_, end_stream); if (end_stream) { return true; @@ -2235,10 +2244,11 @@ bool ConnectionManagerImpl::ActiveStream::onDeferredRequestProcessing() { // Filter manager will return early from decodeData and decodeTrailers if // request has completed. if (deferred_data_ != nullptr) { - end_stream = state_.deferred_end_stream_ && request_trailers_ == nullptr; + end_stream = state_.deferred_end_stream_ && deferred_request_trailers_ == nullptr; filter_manager_.decodeData(*deferred_data_, end_stream); } - if (request_trailers_ != nullptr) { + if (deferred_request_trailers_ != nullptr) { + request_trailers_ = std::move(deferred_request_trailers_); filter_manager_.decodeTrailers(*request_trailers_); } return true; diff --git a/source/common/http/conn_manager_impl.h b/source/common/http/conn_manager_impl.h index 34c96fab02f1..b9b7e13a2092 100644 --- a/source/common/http/conn_manager_impl.h +++ b/source/common/http/conn_manager_impl.h @@ -176,8 +176,8 @@ class ConnectionManagerImpl : Logger::Loggable, void decodeData(Buffer::Instance& data, bool end_stream) override; void decodeMetadata(MetadataMapPtr&&) override; - // Mark that the last downstream byte is received, and the downstream stream is complete. - void maybeEndDecode(bool end_stream); + // Record the timestamp of last downstream byte is received. + void maybeRecordLastByteReceived(bool end_stream); // Http::RequestDecoder void decodeHeaders(RequestHeaderMapSharedPtr&& headers, bool end_stream) override; @@ -410,7 +410,7 @@ class ConnectionManagerImpl : Logger::Loggable, // harmonize this behavior with H/1. // 3. If the `stream_error_on_invalid_http_message` is set to `false` (it is by default) in the // HTTP connection manager configuration, then the entire connection is closed. - bool validateTrailers(); + bool validateTrailers(RequestTrailerMap& trailers); std::weak_ptr stillAlive() { return {still_alive_}; } @@ -508,6 +508,7 @@ class ConnectionManagerImpl : Logger::Loggable, std::shared_ptr still_alive_ = std::make_shared(true); std::unique_ptr deferred_data_; std::queue deferred_metadata_; + RequestTrailerMapPtr deferred_request_trailers_; }; using ActiveStreamPtr = std::unique_ptr; diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index 392f0bdcd239..c2d5bb189841 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -1121,7 +1121,9 @@ class DownstreamFilterManager : public FilterManager { std::move(parent_filter_state)), local_reply_(local_reply), downstream_filter_load_shed_point_(overload_manager.getLoadShedPoint( - Server::LoadShedPointName::get().HttpDownstreamFilterCheck)) { + Server::LoadShedPointName::get().HttpDownstreamFilterCheck)), + use_filter_manager_state_for_downstream_end_stream_(Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream")) { ENVOY_LOG_ONCE_IF( trace, downstream_filter_load_shed_point_ == nullptr, "LoadShedPoint envoy.load_shed_points.http_downstream_filter_check is not found. " @@ -1153,11 +1155,24 @@ class DownstreamFilterManager : public FilterManager { absl::string_view details) override; /** - * Whether remote processing has been marked as complete. - * For the DownstreamFilterManager rely on external state, to handle the case - * of internal redirects. + * Whether downstream has observed end_stream. */ bool decoderObservedEndStream() const override { + // Set by the envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream + // runtime flag. + if (use_filter_manager_state_for_downstream_end_stream_) { + return state_.observed_decode_end_stream_; + } + + return hasLastDownstreamByteReceived(); + } + + /** + * Return true if the timestamp of the downstream end_stream was recorded. + * For the HCM to handle the case of internal redirects, timeout error replies + * and stream resets on premature upstream response. + */ + bool hasLastDownstreamByteReceived() const { return streamInfo().downstreamTiming() && streamInfo().downstreamTiming()->lastDownstreamRxByteReceived().has_value(); } @@ -1206,6 +1221,9 @@ class DownstreamFilterManager : public FilterManager { const LocalReply::LocalReply& local_reply_; Utility::PreparedLocalReplyPtr prepared_local_reply_{nullptr}; Server::LoadShedPoint* downstream_filter_load_shed_point_{nullptr}; + // Set by the envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream runtime + // flag. + const bool use_filter_manager_state_for_downstream_end_stream_{}; }; } // namespace Http diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 1acdd3d55a31..ce42fe31e4c4 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -92,6 +92,7 @@ RUNTIME_GUARD(envoy_reloadable_features_udp_socket_apply_aggregated_read_limit); RUNTIME_GUARD(envoy_reloadable_features_uhv_allow_malformed_url_encoding); RUNTIME_GUARD(envoy_reloadable_features_upstream_remote_address_use_connection); RUNTIME_GUARD(envoy_reloadable_features_use_config_in_happy_eyeballs); +RUNTIME_GUARD(envoy_reloadable_features_use_filter_manager_state_for_downstream_end_stream); RUNTIME_GUARD(envoy_reloadable_features_use_http3_header_normalisation); RUNTIME_GUARD(envoy_reloadable_features_use_http_client_to_fetch_aws_credentials); RUNTIME_GUARD(envoy_reloadable_features_use_route_host_mutation_for_auto_sni_san); diff --git a/test/integration/BUILD b/test/integration/BUILD index 7e6150068b9d..b4230ea98025 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -540,6 +540,7 @@ envoy_cc_test( "//test/integration/filters:response_metadata_filter_config_lib", "//test/integration/filters:set_response_code_filter_config_proto_cc_proto", "//test/integration/filters:set_response_code_filter_lib", + "//test/integration/filters:stop_in_headers_continue_in_data_filter_lib", "//test/integration/filters:stop_iteration_and_continue", "//test/mocks/http:http_mocks", "//test/mocks/upstream:retry_priority_factory_mocks", diff --git a/test/integration/filters/BUILD b/test/integration/filters/BUILD index 4c99af8610ba..d5b852d3c23a 100644 --- a/test/integration/filters/BUILD +++ b/test/integration/filters/BUILD @@ -962,3 +962,17 @@ envoy_cc_test_library( "//source/extensions/filters/network/common:factory_base_lib", ], ) + +envoy_cc_test_library( + name = "stop_in_headers_continue_in_data_filter_lib", + srcs = ["stop_in_headers_continue_in_data_filter.cc"], + deps = [ + ":common_lib", + "//envoy/http:filter_interface", + "//envoy/registry", + "//envoy/server:filter_config_interface", + "//source/common/protobuf", + "//source/extensions/filters/http/common:pass_through_filter_lib", + "//test/extensions/filters/http/common:empty_http_filter_config_lib", + ], +) diff --git a/test/integration/filters/stop_in_headers_continue_in_data_filter.cc b/test/integration/filters/stop_in_headers_continue_in_data_filter.cc new file mode 100644 index 000000000000..c968208e2e50 --- /dev/null +++ b/test/integration/filters/stop_in_headers_continue_in_data_filter.cc @@ -0,0 +1,34 @@ +#include + +#include "envoy/http/filter.h" +#include "envoy/registry/registry.h" +#include "envoy/server/filter_config.h" + +#include "source/extensions/filters/http/common/pass_through_filter.h" + +#include "test/extensions/filters/http/common/empty_http_filter_config.h" +#include "test/integration/filters/common.h" + +namespace Envoy { + +// A test filter that stops iteration in decodeHeaders then continues in decodeBody. +class StopInHeadersContinueInBodyFilter : public Http::PassThroughFilter { +public: + constexpr static char name[] = "stop-in-headers-continue-in-body-filter"; + + Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap&, bool /* end_stream */) override { + return Http::FilterHeadersStatus::StopIteration; + } + + Http::FilterDataStatus decodeData(Buffer::Instance&, bool) override { + return Http::FilterDataStatus::Continue; + } +}; + +static Registry::RegisterFactory, + Server::Configuration::NamedHttpFilterConfigFactory> + register_; +static Registry::RegisterFactory, + Server::Configuration::UpstreamHttpFilterConfigFactory> + register_upstream_; +} // namespace Envoy diff --git a/test/integration/multiplexed_integration_test.cc b/test/integration/multiplexed_integration_test.cc index 8ba0d7738750..1581b17ad6f1 100644 --- a/test/integration/multiplexed_integration_test.cc +++ b/test/integration/multiplexed_integration_test.cc @@ -2002,6 +2002,8 @@ class Http2FrameIntegrationTest : public testing::TestWithParamwrite(buffer, false, false)); + waitForNextUpstreamConnection({0}, std::chrono::milliseconds(500), fake_upstream_connection_); + std::vector upstream_requests(kRequestsSentPerIOCycle); + for (int i = 0; i < kRequestsSentPerIOCycle; ++i) { + FakeStreamPtr upstream_request; + ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request)); + ASSERT_TRUE(upstream_request->waitForEndStream(*dispatcher_)); + ASSERT_TRUE(upstream_request->receivedData()); + upstream_request->encodeHeaders(default_response_headers_, true); + upstream_requests.push_back(std::move(upstream_request)); + } + for (int i = 0; i < kRequestsSentPerIOCycle; ++i) { auto frame = readFrame(); EXPECT_EQ(Http2Frame::Type::Headers, frame.type()); @@ -2513,38 +2525,50 @@ TEST_P(Http2FrameIntegrationTest, MultipleRequestsDecodeHeadersEndsRequest) { tcp_client_->close(); } -TEST_P(Http2FrameIntegrationTest, MultipleRequestsWithTrailers) { - const int kRequestsSentPerIOCycle = 20; - autonomous_upstream_ = true; - config_helper_.addRuntimeOverride("http.max_requests_per_io_cycle", "1"); +void Http2FrameIntegrationTest::sendRequestsAndResponses(uint32_t num_requests) { beginSession(); std::string buffer; - for (int i = 0; i < kRequestsSentPerIOCycle; ++i) { - auto request = - Http2Frame::makePostRequest(Http2Frame::makeClientStreamId(i), "a", "/", - {{"response_data_blocks", "0"}, {"no_trailers", "1"}}); + for (uint32_t i = 0; i < num_requests; ++i) { + auto request = Http2Frame::makePostRequest(Http2Frame::makeClientStreamId(i), "a", "/", + {{"request_no", absl::StrCat(i)}}); absl::StrAppend(&buffer, std::string(request)); } - for (int i = 0; i < kRequestsSentPerIOCycle; ++i) { + for (uint32_t i = 0; i < num_requests; ++i) { auto data = Http2Frame::makeDataFrame(Http2Frame::makeClientStreamId(i), "a"); absl::StrAppend(&buffer, std::string(data)); } - for (int i = 0; i < kRequestsSentPerIOCycle; ++i) { + for (uint32_t i = 0; i < num_requests; ++i) { auto trailers = Http2Frame::makeEmptyHeadersFrame( Http2Frame::makeClientStreamId(i), static_cast(Http::Http2::orFlags( Http2Frame::HeadersFlags::EndStream, Http2Frame::HeadersFlags::EndHeaders))); - trailers.appendHeaderWithoutIndexing({"k", "v"}); + trailers.appendHeaderWithoutIndexing({"k", absl::StrCat("v", i)}); trailers.adjustPayloadSize(); absl::StrAppend(&buffer, std::string(trailers)); } ASSERT_TRUE(tcp_client_->write(buffer, false, false)); - for (int i = 0; i < kRequestsSentPerIOCycle; ++i) { + waitForNextUpstreamConnection({0}, std::chrono::milliseconds(500), fake_upstream_connection_); + std::vector upstream_requests(num_requests); + for (uint32_t i = 0; i < num_requests; ++i) { + FakeStreamPtr upstream_request; + ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request)); + ASSERT_TRUE(upstream_request->waitForEndStream(*dispatcher_)); + ASSERT_TRUE(upstream_request->receivedData()); + ASSERT_FALSE(upstream_request->trailers() + ->get(Http::LowerCaseString("k"))[0] + ->value() + .getStringView() + .empty()); + upstream_request->encodeHeaders(default_response_headers_, true); + upstream_requests.push_back(std::move(upstream_request)); + } + + for (uint32_t i = 0; i < num_requests; ++i) { auto frame = readFrame(); EXPECT_EQ(Http2Frame::Type::Headers, frame.type()); EXPECT_EQ(Http2Frame::ResponseStatus::Ok, frame.responseStatus()); @@ -2552,6 +2576,23 @@ TEST_P(Http2FrameIntegrationTest, MultipleRequestsWithTrailers) { tcp_client_->close(); } +// Validate that processing of deferred requests with body and trailers is handled correctly +// when there is a filter that pauses and resumes iteration. +TEST_P(Http2FrameIntegrationTest, MultipleRequestsWithTrailersWithFilterChainPause) { + const int kRequestsSentPerIOCycle = 20; + // Add filter that stops iteration in the decodeHeaders and resumes in + // decodeData to verify that downstream end_stream is handled correctly by the filter manager. + config_helper_.addFilter("name: stop-in-headers-continue-in-body-filter"); + config_helper_.addRuntimeOverride("http.max_requests_per_io_cycle", "1"); + sendRequestsAndResponses(kRequestsSentPerIOCycle); +} + +TEST_P(Http2FrameIntegrationTest, MultipleRequestsWithTrailersNoPauseInFilterChain) { + const int kRequestsSentPerIOCycle = 20; + config_helper_.addRuntimeOverride("http.max_requests_per_io_cycle", "1"); + sendRequestsAndResponses(kRequestsSentPerIOCycle); +} + // Validate the request completion during processing of headers in the deferred requests, // is ok, when deferred data and trailers are also present. TEST_P(Http2FrameIntegrationTest, MultipleRequestsWithTrailersDecodeHeadersEndsRequest) { From 3f36f1466de11624958614a3fd46d9ce208ed5b5 Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Fri, 23 Aug 2024 12:53:40 -0400 Subject: [PATCH 29/53] ext_proc: filter config API to support sending body before receiving header response (#35612) Signed-off-by: Yanjun Xiang --- .../filters/http/ext_proc/v3/ext_proc.proto | 16 +++++++++++++++- .../service/ext_proc/v3/external_processor.proto | 3 +++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 1d79d39d99b8..eec230317943 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -99,7 +99,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // ` object in a namespace matching the filter // name. // -// [#next-free-field: 21] +// [#next-free-field: 22] message ExternalProcessor { // Describes the route cache action to be taken when an external processor response // is received in response to request headers. @@ -275,6 +275,20 @@ message ExternalProcessor { // backend stream lifetime. In this case, Envoy will eventually timeout the external processor stream according to this time limit. // The default value is 5000 milliseconds (5 seconds) if not specified. google.protobuf.Duration deferred_close_timeout = 19; + + // [#not-implemented-hide:] + // Send body to the side stream server once it arrives without waiting for the header response from that server. + // It only works for STREAMED body processing mode. For any other body processing modes, it is ignored. + // + // The server has two options upon receiving a header request: + // 1. Instant Response: Send the header response as soon as the header request is received. + // 2. Delayed Response: Wait for the body before sending any response. + // If the server chooses the second option, it has two further choices: + // 2.1 Separate Responses: Send the header response first, followed by separate body responses. + // 2.2 Combined Response: Include both the header response and the first chunk of the body response + // in a single body response message, followed by the remaining body responses. + // In all scenarios, the header-body ordering must always be maintained. + bool send_body_without_waiting_for_header_response = 21; } // ExtProcHttpService is used for HTTP communication between the filter and the external processing service. diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index 585d0aa7bf41..5f0d66e65735 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -285,6 +285,9 @@ message CommonResponse { // Instructions on how to manipulate the headers. When responding to an // HttpBody request, header mutations will only take effect if // the current processing mode for the body is BUFFERED. + // [#comment:TODO(yanjunxiang-google) rephrase last sentence once send_body_without_waiting_for_header_response is not hidden: + // the current processing mode for the body is: 1) BUFFERED; 2) or STREAMED and + // the :ref:`send_body_without_waiting_for_header_response ` is enabled.] HeaderMutation header_mutation = 2; // Replace the body of the last message sent to the remote server on this From d7e0d6083cc95357cc7a110a9a05e46d1fca0f08 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Fri, 23 Aug 2024 14:28:13 -0500 Subject: [PATCH 30/53] mobile: Add an overloaded EngineBuilder::addNativeFilter that takes Any proto (#35831) This PR adds an overloaded `EngineBuilder::addNativeFilter` that takes `Any` proto. The existing `EngineBuilder::addNative` that takes `std::string` is confusing because the `std::string` passed in can be different depending whether full protos or lite protos support is enabled. Having an overloaded `EngineBuilder::addNativeFilter` that takes `Any` should eliminate that confusion. Some tests have also been updated to no longer need `#ifdef ENVOY_ENABLE_FULL_PROTOS`. Risk Level: low Testing: unit tests Docs Changes: n/a Release Notes: n/a Platform Specific Features: mobile Signed-off-by: Fredy Wijaya --- mobile/library/cc/engine_builder.cc | 25 +++++++++---- mobile/library/cc/engine_builder.h | 9 +++-- mobile/test/cc/integration/BUILD | 3 ++ mobile/test/cc/integration/send_data_test.cc | 28 +++++++-------- .../test/cc/integration/send_headers_test.cc | 36 +++++++++++-------- .../test/cc/integration/send_trailers_test.cc | 29 ++++++++------- mobile/test/cc/unit/BUILD | 1 + mobile/test/cc/unit/envoy_config_test.cc | 30 +++++++++++++++- mobile/test/common/BUILD | 1 + mobile/test/common/internal_engine_test.cc | 17 ++++++--- 10 files changed, 121 insertions(+), 58 deletions(-) diff --git a/mobile/library/cc/engine_builder.cc b/mobile/library/cc/engine_builder.cc index 15ec80552f6e..1bff4d7dc7e7 100644 --- a/mobile/library/cc/engine_builder.cc +++ b/mobile/library/cc/engine_builder.cc @@ -276,7 +276,13 @@ EngineBuilder& EngineBuilder::addStringAccessor(std::string name, } EngineBuilder& EngineBuilder::addNativeFilter(std::string name, std::string typed_config) { - native_filter_chain_.emplace_back(std::move(name), std::move(typed_config)); + native_filter_chain_.emplace_back(NativeFilterConfig(std::move(name), std::move(typed_config))); + return *this; +} + +EngineBuilder& EngineBuilder::addNativeFilter(const std::string& name, + const ProtobufWkt::Any& typed_config) { + native_filter_chain_.push_back(NativeFilterConfig(name, typed_config)); return *this; } @@ -361,15 +367,20 @@ std::unique_ptr EngineBuilder::generate ++filter) { auto* native_filter = hcm->add_http_filters(); native_filter->set_name(filter->name_); + if (!filter->textproto_typed_config_.empty()) { #ifdef ENVOY_ENABLE_FULL_PROTOS - Protobuf::TextFormat::ParseFromString((*filter).typed_config_, - native_filter->mutable_typed_config()); - RELEASE_ASSERT(!native_filter->typed_config().DebugString().empty(), - "Failed to parse: " + (*filter).typed_config_); + Protobuf::TextFormat::ParseFromString((*filter).textproto_typed_config_, + native_filter->mutable_typed_config()); + RELEASE_ASSERT(!native_filter->typed_config().DebugString().empty(), + "Failed to parse: " + (*filter).textproto_typed_config_); #else - RELEASE_ASSERT(native_filter->mutable_typed_config()->ParseFromString((*filter).typed_config_), - "Failed to parse binary proto: " + (*filter).typed_config_); + RELEASE_ASSERT( + native_filter->mutable_typed_config()->ParseFromString((*filter).textproto_typed_config_), + "Failed to parse binary proto: " + (*filter).textproto_typed_config_); #endif // !ENVOY_ENABLE_FULL_PROTOS + } else { + *native_filter->mutable_typed_config() = filter->typed_config_; + } } // Set up the optional filters diff --git a/mobile/library/cc/engine_builder.h b/mobile/library/cc/engine_builder.h index 748c9cb1fc66..6fb4b2a94b5c 100644 --- a/mobile/library/cc/engine_builder.h +++ b/mobile/library/cc/engine_builder.h @@ -81,6 +81,7 @@ class EngineBuilder { // E.g. addDnsPreresolveHost(std::string host, uint32_t port); EngineBuilder& addDnsPreresolveHostnames(const std::vector& hostnames); EngineBuilder& addNativeFilter(std::string name, std::string typed_config); + EngineBuilder& addNativeFilter(const std::string& name, const ProtobufWkt::Any& typed_config); EngineBuilder& addPlatformFilter(const std::string& name); // Adds a runtime guard for the `envoy.reloadable_features.`. @@ -117,10 +118,14 @@ class EngineBuilder { private: struct NativeFilterConfig { NativeFilterConfig(std::string name, std::string typed_config) - : name_(std::move(name)), typed_config_(std::move(typed_config)) {} + : name_(std::move(name)), textproto_typed_config_(std::move(typed_config)) {} + + NativeFilterConfig(const std::string& name, const ProtobufWkt::Any& typed_config) + : name_(name), typed_config_(typed_config) {} std::string name_; - std::string typed_config_; + std::string textproto_typed_config_{}; + ProtobufWkt::Any typed_config_{}; }; Logger::Logger::Levels log_level_ = Logger::Logger::Levels::info; diff --git a/mobile/test/cc/integration/BUILD b/mobile/test/cc/integration/BUILD index 9ddbb45a0d50..26924f1466bc 100644 --- a/mobile/test/cc/integration/BUILD +++ b/mobile/test/cc/integration/BUILD @@ -12,6 +12,7 @@ envoy_cc_test( "//library/cc:engine_builder_lib", "//library/common:engine_types_lib", "//library/common/http:header_utility_lib", + "//test/common/http/filters/assertion:filter_cc_proto", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", "@envoy_build_config//:test_extensions", @@ -26,6 +27,7 @@ envoy_cc_test( "//library/cc:engine_builder_lib", "//library/common:engine_types_lib", "//library/common/http:header_utility_lib", + "//test/common/http/filters/assertion:filter_cc_proto", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", "@envoy_build_config//:test_extensions", @@ -40,6 +42,7 @@ envoy_cc_test( "//library/cc:engine_builder_lib", "//library/common:engine_types_lib", "//library/common/http:header_utility_lib", + "//test/common/http/filters/assertion:filter_cc_proto", "//test/common/integration:engine_with_test_server", "//test/common/integration:test_server_lib", "@envoy_build_config//:test_extensions", diff --git a/mobile/test/cc/integration/send_data_test.cc b/mobile/test/cc/integration/send_data_test.cc index 5f4ba1ab2887..97a519bf2b09 100644 --- a/mobile/test/cc/integration/send_data_test.cc +++ b/mobile/test/cc/integration/send_data_test.cc @@ -1,3 +1,4 @@ +#include "test/common/http/filters/assertion/filter.pb.h" #include "test/common/integration/engine_with_test_server.h" #include "test/common/integration/test_server.h" @@ -9,26 +10,23 @@ namespace Envoy { -inline constexpr absl::string_view ASSERTION_FILTER_TEXT_PROTO = R"( - [type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion] { - match_config { - http_request_generic_body_match: { - patterns: { - string_match: 'request body' - } - } - } - } -)"; - TEST(SendDataTest, Success) { + envoymobile::extensions::filters::http::assertion::Assertion assertion; + auto* request_generic_body_match = + assertion.mutable_match_config()->mutable_http_request_generic_body_match(); + request_generic_body_match->add_patterns()->set_string_match("request body"); + ProtobufWkt::Any typed_config; + typed_config.set_type_url( + "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion"); + std::string serialized_assertion; + assertion.SerializeToString(&serialized_assertion); + typed_config.set_value(serialized_assertion); + absl::Notification engine_running; Platform::EngineBuilder engine_builder; engine_builder.enforceTrustChainVerification(false) .setLogLevel(Logger::Logger::debug) -#ifdef ENVOY_ENABLE_FULL_PROTOS - .addNativeFilter("envoy.filters.http.assertion", std::string(ASSERTION_FILTER_TEXT_PROTO)) -#endif + .addNativeFilter("envoy.filters.http.assertion", typed_config) .setOnEngineRunning([&]() { engine_running.Notify(); }); EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS); engine_running.WaitForNotification(); diff --git a/mobile/test/cc/integration/send_headers_test.cc b/mobile/test/cc/integration/send_headers_test.cc index a7bafda0dd44..2f29fc42ea35 100644 --- a/mobile/test/cc/integration/send_headers_test.cc +++ b/mobile/test/cc/integration/send_headers_test.cc @@ -1,3 +1,4 @@ +#include "test/common/http/filters/assertion/filter.pb.h" #include "test/common/integration/engine_with_test_server.h" #include "test/common/integration/test_server.h" @@ -9,26 +10,31 @@ namespace Envoy { -inline constexpr absl::string_view ASSERTION_FILTER_TEXT_PROTO = R"( - [type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion] { - match_config: { - http_request_headers_match: { - headers: { name: ':method', exact_match: 'GET' } - headers: { name: ':scheme', exact_match: 'https' } - headers: { name: ':path', exact_match: '/' } - } - } - } -)"; - TEST(SendHeadersTest, Success) { + envoymobile::extensions::filters::http::assertion::Assertion assertion; + auto* http_request_headers_match = + assertion.mutable_match_config()->mutable_http_request_headers_match(); + auto* headers1 = http_request_headers_match->add_headers(); + headers1->set_name(":method"); + headers1->set_exact_match("GET"); + auto* headers2 = http_request_headers_match->add_headers(); + headers2->set_name(":scheme"); + headers2->set_exact_match("https"); + auto* headers3 = http_request_headers_match->add_headers(); + headers3->set_name(":path"); + headers3->set_exact_match("/"); + ProtobufWkt::Any typed_config; + typed_config.set_type_url( + "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion"); + std::string serialized_assertion; + assertion.SerializeToString(&serialized_assertion); + typed_config.set_value(serialized_assertion); + absl::Notification engine_running; Platform::EngineBuilder engine_builder; engine_builder.enforceTrustChainVerification(false) .setLogLevel(Logger::Logger::debug) -#ifdef ENVOY_ENABLE_FULL_PROTOS - .addNativeFilter("envoy.filters.http.assertion", std::string(ASSERTION_FILTER_TEXT_PROTO)) -#endif + .addNativeFilter("envoy.filters.http.assertion", typed_config) .setOnEngineRunning([&]() { engine_running.Notify(); }); EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS); engine_running.WaitForNotification(); diff --git a/mobile/test/cc/integration/send_trailers_test.cc b/mobile/test/cc/integration/send_trailers_test.cc index a773d316e1ce..c3c79e45ca17 100644 --- a/mobile/test/cc/integration/send_trailers_test.cc +++ b/mobile/test/cc/integration/send_trailers_test.cc @@ -1,3 +1,4 @@ +#include "test/common/http/filters/assertion/filter.pb.h" #include "test/common/integration/engine_with_test_server.h" #include "test/common/integration/test_server.h" @@ -9,24 +10,26 @@ namespace Envoy { -inline constexpr absl::string_view ASSERTION_FILTER_TEXT_PROTO = R"( - [type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion] { - match_config: { - http_request_trailers_match: { - headers: { name: 'trailer-key', exact_match: 'trailer-value' } - } - } - } -)"; - TEST(SendTrailersTest, Success) { + envoymobile::extensions::filters::http::assertion::Assertion assertion; + auto* http_request_trailers_match = + assertion.mutable_match_config()->mutable_http_request_trailers_match(); + auto trailer = http_request_trailers_match->add_headers(); + trailer->set_name("trailer-key"); + trailer->set_exact_match("trailer-value"); + ProtobufWkt::Any typed_config; + typed_config.set_type_url( + "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion"); + std::string serialized_assertion; + assertion.SerializeToString(&serialized_assertion); + typed_config.set_value(serialized_assertion); + absl::Notification engine_running; Platform::EngineBuilder engine_builder; engine_builder.enforceTrustChainVerification(false) .setLogLevel(Logger::Logger::debug) -#ifdef ENVOY_ENABLE_FULL_PROTOS - .addNativeFilter("envoy.filters.http.assertion", std::string(ASSERTION_FILTER_TEXT_PROTO)) -#endif + .addNativeFilter("envoy.filters.http.assertion", typed_config) + .setOnEngineRunning([&]() { engine_running.Notify(); }); EngineWithTestServer engine_with_test_server(engine_builder, TestServerType::HTTP2_WITH_TLS, /* headers= */ {}, /* body= */ "body", diff --git a/mobile/test/cc/unit/BUILD b/mobile/test/cc/unit/BUILD index 80cfdd16c6f1..b6046df3313f 100644 --- a/mobile/test/cc/unit/BUILD +++ b/mobile/test/cc/unit/BUILD @@ -22,6 +22,7 @@ envoy_cc_test( "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/clusters/dynamic_forward_proxy/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/filters/http/buffer/v3:pkg_cc_proto", "@envoy_build_config//:extension_registry", "@envoy_build_config//:test_extensions", ], diff --git a/mobile/test/cc/unit/envoy_config_test.cc b/mobile/test/cc/unit/envoy_config_test.cc index 97958a679883..df94f22ffde4 100644 --- a/mobile/test/cc/unit/envoy_config_test.cc +++ b/mobile/test/cc/unit/envoy_config_test.cc @@ -6,6 +6,7 @@ #include "envoy/config/cluster/v3/cluster.pb.h" #include "envoy/config/core/v3/socket_option.pb.h" #include "envoy/extensions/clusters/dynamic_forward_proxy/v3/cluster.pb.h" +#include "envoy/extensions/filters/http/buffer/v3/buffer.pb.h" #include "test/test_common/utility.h" @@ -409,10 +410,37 @@ class TestStringAccessor : public StringAccessor { mutable int count_ = 0; }; -#ifdef ENVOY_ENABLE_FULL_PROTOS TEST(TestConfig, AddNativeFilters) { EngineBuilder engine_builder; + std::string filter_name1 = "envoy.filters.http.buffer1"; + std::string filter_name2 = "envoy.filters.http.buffer2"; + + envoy::extensions::filters::http::buffer::v3::Buffer buffer; + buffer.mutable_max_request_bytes()->set_value(5242880); + ProtobufWkt::Any typed_config; + typed_config.set_type_url("type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer"); + std::string serialized_buffer; + buffer.SerializeToString(&serialized_buffer); + typed_config.set_value(serialized_buffer); + + engine_builder.addNativeFilter(filter_name1, typed_config); + engine_builder.addNativeFilter(filter_name2, typed_config); + + std::unique_ptr bootstrap = engine_builder.generateBootstrap(); + const std::string hcm_config = + bootstrap->static_resources().listeners(0).api_listener().DebugString(); + EXPECT_THAT(hcm_config, HasSubstr(filter_name1)); + EXPECT_THAT(hcm_config, HasSubstr(filter_name2)); + EXPECT_THAT(hcm_config, + HasSubstr("type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer")); + EXPECT_THAT(hcm_config, HasSubstr(std::to_string(5242880))); +} + +#ifdef ENVOY_ENABLE_FULL_PROTOS +TEST(TestConfig, AddTextProtoNativeFilters) { + EngineBuilder engine_builder; + std::string filter_name1 = "envoy.filters.http.buffer1"; std::string filter_name2 = "envoy.filters.http.buffer2"; std::string filter_config = diff --git a/mobile/test/common/BUILD b/mobile/test/common/BUILD index 5c2155630506..5e4214154320 100644 --- a/mobile/test/common/BUILD +++ b/mobile/test/common/BUILD @@ -30,6 +30,7 @@ envoy_cc_test( "//test/common/mocks/event:event_mocks", "@envoy//test/common/http:common_lib", "@envoy//test/mocks/thread:thread_mocks", + "@envoy_api//envoy/extensions/filters/http/buffer/v3:pkg_cc_proto", "@envoy_build_config//:test_extensions", ], ) diff --git a/mobile/test/common/internal_engine_test.cc b/mobile/test/common/internal_engine_test.cc index 8b0eb0751147..c9b909bad027 100644 --- a/mobile/test/common/internal_engine_test.cc +++ b/mobile/test/common/internal_engine_test.cc @@ -2,6 +2,8 @@ #include +#include "envoy/extensions/filters/http/buffer/v3/buffer.pb.h" + #include "source/common/common/assert.h" #include "test/common/http/common.h" @@ -323,7 +325,6 @@ TEST_F(InternalEngineTest, EventTrackerRegistersEnvoyBugRecordAction) { test_context.on_exit.WaitForNotificationWithTimeout(absl::Seconds(kDefaultTimeoutSec))); } -#ifdef ENVOY_ENABLE_FULL_PROTOS TEST_F(InternalEngineTest, BasicStream) { TestServer test_server; test_server.start(TestServerType::HTTP1_WITHOUT_TLS); @@ -331,10 +332,17 @@ TEST_F(InternalEngineTest, BasicStream) { EngineTestContext test_context{}; std::unique_ptr engine = std::make_unique( createDefaultEngineCallbacks(test_context), /*logger=*/nullptr, /*event_tracker=*/nullptr); + + envoy::extensions::filters::http::buffer::v3::Buffer buffer; + buffer.mutable_max_request_bytes()->set_value(65000); + ProtobufWkt::Any typed_config; + typed_config.set_type_url("type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer"); + std::string serialized_buffer; + buffer.SerializeToString(&serialized_buffer); + typed_config.set_value(serialized_buffer); + Platform::EngineBuilder builder; - builder.addNativeFilter("buffer", - "[type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer] { " - "max_request_bytes: { value: 65000 } }"); + builder.addNativeFilter("buffer", typed_config); runEngine(engine, builder, LOG_LEVEL); ASSERT_TRUE(test_context.on_engine_running.WaitForNotificationWithTimeout(absl::Seconds(10))); @@ -364,7 +372,6 @@ TEST_F(InternalEngineTest, BasicStream) { ASSERT_TRUE(test_context.on_exit.WaitForNotificationWithTimeout(absl::Seconds(10))); } -#endif TEST_F(InternalEngineTest, ResetStream) { EngineTestContext test_context{}; From 93099c6e9ea24eeb22a41d477d821beab164777f Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Fri, 23 Aug 2024 17:24:14 -0400 Subject: [PATCH 31/53] xds-failover: prevent sending initial_resource_versions when moving from fallback to primary (#35692) Signed-off-by: Adi Suissa-Peleg --- envoy/config/grpc_mux.h | 5 +- source/common/config/null_grpc_mux_impl.h | 2 +- .../grpc/delta_subscription_state.cc | 29 +++-- .../grpc/delta_subscription_state.h | 7 +- .../grpc/grpc_mux_failover.h | 37 ++++--- .../config_subscription/grpc/grpc_mux_impl.cc | 2 +- .../config_subscription/grpc/grpc_mux_impl.h | 2 +- .../config_subscription/grpc/grpc_stream.h | 7 +- .../grpc/new_grpc_mux_impl.cc | 5 +- .../grpc/new_grpc_mux_impl.h | 5 +- .../grpc/xds_mux/delta_subscription_state.cc | 29 +++-- .../grpc/xds_mux/delta_subscription_state.h | 3 +- .../grpc/xds_mux/grpc_mux_impl.cc | 6 +- .../grpc/xds_mux/grpc_mux_impl.h | 10 +- .../grpc/xds_mux/sotw_subscription_state.cc | 2 +- .../grpc/xds_mux/sotw_subscription_state.h | 2 +- .../grpc/xds_mux/subscription_state.h | 2 +- .../grpc/delta_subscription_state_test.cc | 101 +++++++++++------- .../grpc/grpc_mux_failover_test.cc | 54 +++++----- .../grpc/grpc_mux_impl_test.cc | 2 +- .../grpc/grpc_stream_test.cc | 30 +++--- .../grpc/new_grpc_mux_impl_test.cc | 38 +++++-- .../grpc/sotw_subscription_state_test.cc | 4 +- .../grpc/xds_failover_integration_test.cc | 41 +++---- test/integration/base_integration_test.cc | 41 +++++-- test/integration/base_integration_test.h | 8 +- test/mocks/config/mocks.h | 2 +- 27 files changed, 306 insertions(+), 170 deletions(-) diff --git a/envoy/config/grpc_mux.h b/envoy/config/grpc_mux.h index a08724fcdf6c..a18c87bc193e 100644 --- a/envoy/config/grpc_mux.h +++ b/envoy/config/grpc_mux.h @@ -134,8 +134,11 @@ template class GrpcStreamCallbacks { /** * For the GrpcStream to prompt the context to take appropriate action in response to * failure to establish the gRPC stream. + * @param next_attempt_may_send_initial_resource_version a flag indicating whether the + * next reconnection attempt will be to the same source that was previously successful + * or not (used to pass primary/failover reconnection information to the GrpcMux). */ - virtual void onEstablishmentFailure() PURE; + virtual void onEstablishmentFailure(bool next_attempt_may_send_initial_resource_version) PURE; /** * For the GrpcStream to pass received protos to the context. diff --git a/source/common/config/null_grpc_mux_impl.h b/source/common/config/null_grpc_mux_impl.h index 5e82f42e5447..453d723eb32d 100644 --- a/source/common/config/null_grpc_mux_impl.h +++ b/source/common/config/null_grpc_mux_impl.h @@ -31,7 +31,7 @@ class NullGrpcMuxImpl : public GrpcMux, void onWriteable() override {} void onStreamEstablished() override {} - void onEstablishmentFailure() override {} + void onEstablishmentFailure(bool) override {} void onDiscoveryResponse(std::unique_ptr&&, ControlPlaneStats&) override {} }; diff --git a/source/extensions/config_subscription/grpc/delta_subscription_state.cc b/source/extensions/config_subscription/grpc/delta_subscription_state.cc index 65ec1fc99b5c..7a1f2fd35445 100644 --- a/source/extensions/config_subscription/grpc/delta_subscription_state.cc +++ b/source/extensions/config_subscription/grpc/delta_subscription_state.cc @@ -139,6 +139,11 @@ bool DeltaSubscriptionState::subscriptionUpdatePending() const { return must_send_discovery_request_; } +void DeltaSubscriptionState::markStreamFresh(bool should_send_initial_resource_versions) { + any_request_sent_yet_in_current_stream_ = false; + should_send_initial_resource_versions_ = should_send_initial_resource_versions; +} + UpdateAck DeltaSubscriptionState::handleResponse( const envoy::service::discovery::v3::DeltaDiscoveryResponse& message) { // We *always* copy the response's nonce into the next request, even if we're going to make that @@ -286,21 +291,25 @@ DeltaSubscriptionState::getNextRequestAckless() { // Also, since this might be a new server, we must explicitly state *all* of our subscription // interest. for (auto const& [resource_name, resource_state] : requested_resource_state_) { - // Populate initial_resource_versions with the resource versions we currently have. - // Resources we are interested in, but are still waiting to get any version of from the - // server, do not belong in initial_resource_versions. (But do belong in new subscriptions!) - if (!resource_state.isWaitingForServer()) { - (*request.mutable_initial_resource_versions())[resource_name] = resource_state.version(); + if (should_send_initial_resource_versions_) { + // Populate initial_resource_versions with the resource versions we currently have. + // Resources we are interested in, but are still waiting to get any version of from the + // server, do not belong in initial_resource_versions. (But do belong in new subscriptions!) + if (!resource_state.isWaitingForServer()) { + (*request.mutable_initial_resource_versions())[resource_name] = resource_state.version(); + } } // We are going over a list of resources that we are interested in, so add them to // resource_names_subscribe. names_added_.insert(resource_name); } - for (auto const& [resource_name, resource_version] : wildcard_resource_state_) { - (*request.mutable_initial_resource_versions())[resource_name] = resource_version; - } - for (auto const& [resource_name, resource_version] : ambiguous_resource_state_) { - (*request.mutable_initial_resource_versions())[resource_name] = resource_version; + if (should_send_initial_resource_versions_) { + for (auto const& [resource_name, resource_version] : wildcard_resource_state_) { + (*request.mutable_initial_resource_versions())[resource_name] = resource_version; + } + for (auto const& [resource_name, resource_version] : ambiguous_resource_state_) { + (*request.mutable_initial_resource_versions())[resource_name] = resource_version; + } } // If this is a legacy wildcard request, then make sure that the resource_names_subscribe is // empty. diff --git a/source/extensions/config_subscription/grpc/delta_subscription_state.h b/source/extensions/config_subscription/grpc/delta_subscription_state.h index 656285a47935..261ae3282e5d 100644 --- a/source/extensions/config_subscription/grpc/delta_subscription_state.h +++ b/source/extensions/config_subscription/grpc/delta_subscription_state.h @@ -89,7 +89,11 @@ class DeltaSubscriptionState : public Logger::Loggable { // Whether there was a change in our subscription interest we have yet to inform the server of. bool subscriptionUpdatePending() const; - void markStreamFresh() { any_request_sent_yet_in_current_stream_ = false; } + // Marks the stream as fresh for the next reconnection attempt. If + // should_send_initial_resource_versions is true, then the next request will + // also populate the initial_resource_versions field in the first request (if + // there are relevant resources). + void markStreamFresh(bool should_send_initial_resource_versions); UpdateAck handleResponse(const envoy::service::discovery::v3::DeltaDiscoveryResponse& message); @@ -169,6 +173,7 @@ class DeltaSubscriptionState : public Logger::Loggable { bool in_initial_legacy_wildcard_{true}; bool any_request_sent_yet_in_current_stream_{}; + bool should_send_initial_resource_versions_{true}; bool must_send_discovery_request_{}; // Tracks changes in our subscription interest since the previous DeltaDiscoveryRequest we sent. diff --git a/source/extensions/config_subscription/grpc/grpc_mux_failover.h b/source/extensions/config_subscription/grpc/grpc_mux_failover.h index 745e1be9409f..19765df61fc7 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_failover.h +++ b/source/extensions/config_subscription/grpc/grpc_mux_failover.h @@ -70,7 +70,8 @@ class GrpcMuxFailover : public GrpcStreamInterface, Event::Dispatcher& dispatcher) : grpc_mux_callbacks_(grpc_mux_callbacks), primary_callbacks_(*this), primary_grpc_stream_(std::move(primary_stream_creator(&primary_callbacks_))), - connection_state_(ConnectionState::None), ever_connected_to_primary_(false) { + connection_state_(ConnectionState::None), ever_connected_to_primary_(false), + previously_connected_to_(ConnectedTo::None) { ASSERT(primary_grpc_stream_ != nullptr); if (failover_stream_creator.has_value()) { ENVOY_LOG(warn, "Using xDS-Failover. Note that the implementation is currently considered " @@ -202,7 +203,7 @@ class GrpcMuxFailover : public GrpcStreamInterface, parent_.grpc_mux_callbacks_.onStreamEstablished(); } - void onEstablishmentFailure() override { + void onEstablishmentFailure(bool) override { // This will be called when the primary stream fails to establish a connection, or after the // connection was closed. ASSERT(parent_.connectingToOrConnectedToPrimary()); @@ -221,11 +222,11 @@ class GrpcMuxFailover : public GrpcStreamInterface, "in a row. Attempting to connect to the failover stream."); // This will close the stream and prevent the retry timer from // reconnecting to the primary source. - // TODO(adisuissa): need to ensure that when moving between primary and failover, - // the initial_resource_versions that are sent are empty. This will be - // done in a followup PR. parent_.primary_grpc_stream_->closeStream(); - parent_.grpc_mux_callbacks_.onEstablishmentFailure(); + // Next attempt will be to the failover, set the value that + // determines whether to set initial_resource_versions or not. + parent_.grpc_mux_callbacks_.onEstablishmentFailure(parent_.previously_connected_to_ == + ConnectedTo::Failover); parent_.connection_state_ = ConnectionState::ConnectingToFailover; parent_.failover_grpc_stream_->establishNewStream(); return; @@ -237,7 +238,10 @@ class GrpcMuxFailover : public GrpcStreamInterface, ENVOY_LOG_MISC(trace, "Not trying to connect to failover. Will try again to reconnect to the " "primary (upon retry)."); parent_.connection_state_ = ConnectionState::ConnectingToPrimary; - parent_.grpc_mux_callbacks_.onEstablishmentFailure(); + // Next attempt will be to the primary, set the value that + // determines whether to set initial_resource_versions or not. + parent_.grpc_mux_callbacks_.onEstablishmentFailure(parent_.previously_connected_to_ == + ConnectedTo::Primary); } void onDiscoveryResponse(ResponseProtoPtr&& message, @@ -249,6 +253,7 @@ class GrpcMuxFailover : public GrpcStreamInterface, parent_.ever_connected_to_primary_ = true; primary_consecutive_failures_ = 0; parent_.connection_state_ = ConnectionState::ConnectedToPrimary; + parent_.previously_connected_to_ = ConnectedTo::Primary; parent_.grpc_mux_callbacks_.onDiscoveryResponse(std::move(message), control_plane_stats); } @@ -278,7 +283,7 @@ class GrpcMuxFailover : public GrpcStreamInterface, parent_.grpc_mux_callbacks_.onStreamEstablished(); } - void onEstablishmentFailure() override { + void onEstablishmentFailure(bool) override { // This will be called when the failover stream fails to establish a connection, or after the // connection was closed. ASSERT(parent_.connectingToOrConnectedToFailover()); @@ -288,12 +293,13 @@ class GrpcMuxFailover : public GrpcStreamInterface, "before). Attempting to connect to the primary stream."); // This will close the stream and prevent the retry timer from - // reconnecting to the failover source. - // TODO(adisuissa): need to ensure that when moving between primary and failover, - // the initial_resource_versions that are sent are empty. This will be - // done in a followup PR. + // reconnecting to the failover source. The next attempt will be to the + // primary source. parent_.failover_grpc_stream_->closeStream(); - parent_.grpc_mux_callbacks_.onEstablishmentFailure(); + // Next attempt will be to the primary, set the value that + // determines whether to set initial_resource_versions or not. + parent_.grpc_mux_callbacks_.onEstablishmentFailure(parent_.previously_connected_to_ == + ConnectedTo::Primary); // Setting the connection state to None, and when the retry timer will // expire, Envoy will try to connect to the primary source. parent_.connection_state_ = ConnectionState::None; @@ -312,6 +318,7 @@ class GrpcMuxFailover : public GrpcStreamInterface, // Received a response from the failover. The failover is now considered available (no going // back to the primary will be attempted). parent_.connection_state_ = ConnectionState::ConnectedToFailover; + parent_.previously_connected_to_ = ConnectedTo::Failover; parent_.grpc_mux_callbacks_.onDiscoveryResponse(std::move(message), control_plane_stats); } @@ -395,6 +402,10 @@ class GrpcMuxFailover : public GrpcStreamInterface, // primary or failover source. Envoy is considered successfully connected to a source // once it receives a response from it. bool ever_connected_to_primary_{false}; + + enum class ConnectedTo { None, Primary, Failover }; + // Used to track the most recent source that Envoy was connected to. + ConnectedTo previously_connected_to_; }; } // namespace Config diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc index 5da627572280..ba038b140955 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc @@ -535,7 +535,7 @@ void GrpcMuxImpl::onStreamEstablished() { } } -void GrpcMuxImpl::onEstablishmentFailure() { +void GrpcMuxImpl::onEstablishmentFailure(bool) { for (const auto& api_state : api_state_) { for (auto watch : api_state.second->watches_) { watch->callbacks_.onConfigUpdateFailed( diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.h b/source/extensions/config_subscription/grpc/grpc_mux_impl.h index 8766ce96935a..c6d6df79dc6d 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.h @@ -78,7 +78,7 @@ class GrpcMuxImpl : public GrpcMux, // Config::GrpcStreamCallbacks void onStreamEstablished() override; - void onEstablishmentFailure() override; + void onEstablishmentFailure(bool) override; void onDiscoveryResponse(std::unique_ptr&& message, ControlPlaneStats& control_plane_stats) override; diff --git a/source/extensions/config_subscription/grpc/grpc_stream.h b/source/extensions/config_subscription/grpc/grpc_stream.h index f8429df2605e..cd04a03c182d 100644 --- a/source/extensions/config_subscription/grpc/grpc_stream.h +++ b/source/extensions/config_subscription/grpc/grpc_stream.h @@ -70,7 +70,7 @@ class GrpcStream : public GrpcStreamInterface, if (stream_ == nullptr) { ENVOY_LOG(debug, "Unable to establish new stream to configuration server {}", async_client_.destination()); - callbacks_->onEstablishmentFailure(); + callbacks_->onEstablishmentFailure(true); setRetryTimer(); return; } @@ -112,7 +112,10 @@ class GrpcStream : public GrpcStreamInterface, logClose(status, message); stream_ = nullptr; control_plane_stats_.connected_state_.set(0); - callbacks_->onEstablishmentFailure(); + // By default Envoy will reconnect to the same server, so pass true here. + // This will be overridden by the mux-failover if Envoy will reconnect to a + // different server. + callbacks_->onEstablishmentFailure(true); // Only retry the timer if not intentionally closed by Envoy. if (!stream_intentionally_closed_) { setRetryTimer(); diff --git a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc index 93716197c016..15efac2b82d5 100644 --- a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc @@ -184,13 +184,13 @@ void NewGrpcMuxImpl::onDiscoveryResponse( void NewGrpcMuxImpl::onStreamEstablished() { for (auto& [type_url, subscription] : subscriptions_) { UNREFERENCED_PARAMETER(type_url); - subscription->sub_state_.markStreamFresh(); + subscription->sub_state_.markStreamFresh(should_send_initial_resource_versions_); } pausable_ack_queue_.clear(); trySendDiscoveryRequests(); } -void NewGrpcMuxImpl::onEstablishmentFailure() { +void NewGrpcMuxImpl::onEstablishmentFailure(bool next_attempt_may_send_initial_resource_version) { // If this happens while Envoy is still initializing, the onConfigUpdateFailed() we ultimately // call on CDS will cause LDS to start up, which adds to subscriptions_ here. So, to avoid a // crash, the iteration needs to dance around a little: collect pointers to all @@ -208,6 +208,7 @@ void NewGrpcMuxImpl::onEstablishmentFailure() { } } } while (all_subscribed.size() != subscriptions_.size()); + should_send_initial_resource_versions_ = next_attempt_may_send_initial_resource_version; } void NewGrpcMuxImpl::onWriteable() { trySendDiscoveryRequests(); } diff --git a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h index 26a949ae4dbb..741ea6856e45 100644 --- a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h @@ -69,7 +69,7 @@ class NewGrpcMuxImpl void onStreamEstablished() override; - void onEstablishmentFailure() override; + void onEstablishmentFailure(bool next_attempt_may_send_initial_resource_version) override; void onWriteable() override; @@ -210,6 +210,9 @@ class NewGrpcMuxImpl XdsConfigTrackerOptRef xds_config_tracker_; EdsResourcesCachePtr eds_resources_cache_; + // Used to track whether initial_resource_versions should be populated on the + // next reconnection. + bool should_send_initial_resource_versions_{true}; bool started_{false}; // True iff Envoy is shutting down; no messages should be sent on the `grpc_stream_` when this is // true because it may contain dangling pointers. diff --git a/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.cc b/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.cc index 31a640801a14..46f1fb04a6f0 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.cc +++ b/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.cc @@ -120,6 +120,11 @@ bool DeltaSubscriptionState::subscriptionUpdatePending() const { return dynamicContextChanged(); } +void DeltaSubscriptionState::markStreamFresh(bool should_send_initial_resource_versions) { + any_request_sent_yet_in_current_stream_ = false; + should_send_initial_resource_versions_ = should_send_initial_resource_versions; +} + bool DeltaSubscriptionState::isHeartbeatResource( const envoy::service::discovery::v3::Resource& resource) const { if (!supports_heartbeats_) { @@ -244,21 +249,25 @@ DeltaSubscriptionState::getNextRequestInternal() { // Also, since this might be a new server, we must explicitly state *all* of our subscription // interest. for (auto const& [resource_name, resource_state] : requested_resource_state_) { - // Populate initial_resource_versions with the resource versions we currently have. - // Resources we are interested in, but are still waiting to get any version of from the - // server, do not belong in initial_resource_versions. (But do belong in new subscriptions!) - if (!resource_state.isWaitingForServer()) { - (*request->mutable_initial_resource_versions())[resource_name] = resource_state.version(); + if (should_send_initial_resource_versions_) { + // Populate initial_resource_versions with the resource versions we currently have. + // Resources we are interested in, but are still waiting to get any version of from the + // server, do not belong in initial_resource_versions. (But do belong in new subscriptions!) + if (!resource_state.isWaitingForServer()) { + (*request->mutable_initial_resource_versions())[resource_name] = resource_state.version(); + } } // We are going over a list of resources that we are interested in, so add them to // resource_names_subscribe. names_added_.insert(resource_name); } - for (auto const& [resource_name, resource_version] : wildcard_resource_state_) { - (*request->mutable_initial_resource_versions())[resource_name] = resource_version; - } - for (auto const& [resource_name, resource_version] : ambiguous_resource_state_) { - (*request->mutable_initial_resource_versions())[resource_name] = resource_version; + if (should_send_initial_resource_versions_) { + for (auto const& [resource_name, resource_version] : wildcard_resource_state_) { + (*request->mutable_initial_resource_versions())[resource_name] = resource_version; + } + for (auto const& [resource_name, resource_version] : ambiguous_resource_state_) { + (*request->mutable_initial_resource_versions())[resource_name] = resource_version; + } } // If this is a legacy wildcard request, then make sure that the resource_names_subscribe is // empty. diff --git a/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.h b/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.h index 70b9801d5920..c6c62218c148 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.h +++ b/source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.h @@ -31,7 +31,7 @@ class DeltaSubscriptionState // Whether there was a change in our subscription interest we have yet to inform the server of. bool subscriptionUpdatePending() const override; - void markStreamFresh() override { any_request_sent_yet_in_current_stream_ = false; } + void markStreamFresh(bool should_send_initial_resource_versions) override; void ttlExpiryCallback(const std::vector& expired) override; @@ -100,6 +100,7 @@ class DeltaSubscriptionState bool in_initial_legacy_wildcard_{true}; bool any_request_sent_yet_in_current_stream_{}; + bool should_send_initial_resource_versions_{true}; // Tracks changes in our subscription interest since the previous DeltaDiscoveryRequest we sent. // TODO: Can't use absl::flat_hash_set due to ordering issues in gTest expectation matching. diff --git a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc index 7dedcf910abe..9269df1d37df 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc @@ -274,7 +274,7 @@ template void GrpcMuxImpl::handleEstablishedStream() { ENVOY_LOG(debug, "GrpcMuxImpl stream successfully established"); for (auto& [type_url, subscription_state] : subscriptions_) { - subscription_state->markStreamFresh(); + subscription_state->markStreamFresh(should_send_initial_resource_versions_); } setAnyRequestSentYetInCurrentStream(false); maybeUpdateQueueSizeStat(0); @@ -283,7 +283,8 @@ void GrpcMuxImpl::handleEstablishedStream() { } template -void GrpcMuxImpl::handleStreamEstablishmentFailure() { +void GrpcMuxImpl::handleStreamEstablishmentFailure( + bool next_attempt_may_send_initial_resource_version) { ENVOY_LOG(debug, "GrpcMuxImpl stream failed to establish"); // If this happens while Envoy is still initializing, the onConfigUpdateFailed() we ultimately // call on CDS will cause LDS to start up, which adds to subscriptions_ here. So, to avoid a @@ -302,6 +303,7 @@ void GrpcMuxImpl::handleStreamEstablishmentFailure() { } } } while (all_subscribed.size() != subscriptions_.size()); + should_send_initial_resource_versions_ = next_attempt_may_send_initial_resource_version; } template diff --git a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h index 2e0ce7407862..37f0c31f1729 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h @@ -96,7 +96,9 @@ class GrpcMuxImpl : public GrpcStreamCallbacks, // GrpcStreamCallbacks void onStreamEstablished() override { handleEstablishedStream(); } - void onEstablishmentFailure() override { handleStreamEstablishmentFailure(); } + void onEstablishmentFailure(bool next_attempt_may_send_initial_resource_version) override { + handleStreamEstablishmentFailure(next_attempt_may_send_initial_resource_version); + } void onWriteable() override { trySendDiscoveryRequests(); } void onDiscoveryResponse(std::unique_ptr&& message, ControlPlaneStats& control_plane_stats) override { @@ -152,7 +154,7 @@ class GrpcMuxImpl : public GrpcStreamCallbacks, S& subscriptionStateFor(const std::string& type_url); WatchMap& watchMapFor(const std::string& type_url); void handleEstablishedStream(); - void handleStreamEstablishmentFailure(); + void handleStreamEstablishmentFailure(bool next_attempt_may_send_initial_resource_version); void genericHandleResponse(const std::string& type_url, const RS& response_proto, ControlPlaneStats& control_plane_stats); void trySendDiscoveryRequests(); @@ -227,6 +229,10 @@ class GrpcMuxImpl : public GrpcStreamCallbacks, EdsResourcesCachePtr eds_resources_cache_; const std::string target_xds_authority_; + // Used to track whether initial_resource_versions should be populated on the + // next reconnection. + bool should_send_initial_resource_versions_{true}; + bool started_{false}; // True iff Envoy is shutting down; no messages should be sent on the `grpc_stream_` when this is // true because it may contain dangling pointers. diff --git a/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc b/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc index 18bafc1a8015..38ca7c980f2e 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc +++ b/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc @@ -37,7 +37,7 @@ bool SotwSubscriptionState::subscriptionUpdatePending() const { return update_pending_ || dynamicContextChanged(); } -void SotwSubscriptionState::markStreamFresh() { +void SotwSubscriptionState::markStreamFresh(bool) { last_good_nonce_ = absl::nullopt; update_pending_ = true; clearDynamicContextChanged(); diff --git a/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.h b/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.h index 79d44b1ec73b..a084b03efbcb 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.h +++ b/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.h @@ -35,7 +35,7 @@ class SotwSubscriptionState // Whether there was a change in our subscription interest we have yet to inform the server of. bool subscriptionUpdatePending() const override; - void markStreamFresh() override; + void markStreamFresh(bool) override; void ttlExpiryCallback(const std::vector& expired) override; diff --git a/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h b/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h index 3c7ec8d0c542..1602c9196bc6 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h +++ b/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h @@ -60,7 +60,7 @@ class BaseSubscriptionState : public SubscriptionState, // Whether there was a change in our subscription interest we have yet to inform the server of. virtual bool subscriptionUpdatePending() const PURE; - virtual void markStreamFresh() PURE; + virtual void markStreamFresh(bool should_send_initial_resource_versions) PURE; UpdateAck handleResponse(const RS& response) { // We *always* copy the response's nonce into the next request, even if we're going to make that diff --git a/test/extensions/config_subscription/grpc/delta_subscription_state_test.cc b/test/extensions/config_subscription/grpc/delta_subscription_state_test.cc index 7f29e466dbc4..59e9cb501fa0 100644 --- a/test/extensions/config_subscription/grpc/delta_subscription_state_test.cc +++ b/test/extensions/config_subscription/grpc/delta_subscription_state_test.cc @@ -138,11 +138,11 @@ class DeltaSubscriptionStateTestBase : public testing::TestWithParam(state_)->markStreamFresh(); + absl::get<1>(state_)->markStreamFresh(should_send_initial_resource_versions); } else { - absl::get<0>(state_)->markStreamFresh(); + absl::get<0>(state_)->markStreamFresh(should_send_initial_resource_versions); } } @@ -193,7 +193,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, SubscriptionPendingTest) { // We should send a request after a new stream is established if we are interested in some // resource. EXPECT_FALSE(subscriptionUpdatePending()); - markStreamFresh(); + markStreamFresh(true); EXPECT_TRUE(subscriptionUpdatePending()); getNextRequestAckless(); @@ -206,7 +206,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, SubscriptionPendingTest) { // We should not be sending anything after stream reestablishing, because we are not interested in // anything. - markStreamFresh(); + markStreamFresh(true); EXPECT_FALSE(subscriptionUpdatePending()); } @@ -224,7 +224,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionNonWildcardFromRequest EXPECT_TRUE(req->initial_resource_versions().empty()); deliverSimpleDiscoveryResponse({{"foo", "1"}, {"bar", "1"}}, {}, "d1"); - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre("foo", "bar")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -237,7 +237,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionNonWildcardFromRequest EXPECT_THAT(req->resource_names_unsubscribe(), UnorderedElementsAre("foo")); deliverSimpleDiscoveryResponse({}, {"foo"}, "d2"); - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre("bar")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -256,7 +256,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionWithWildcardFromReques deliverSimpleDiscoveryResponse({{"foo", "1"}, {"bar", "1"}, {"wild1", "1"}}, {}, "d1"); // ensure that foo is a part of resource versions - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "foo", "bar")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -270,7 +270,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionWithWildcardFromReques EXPECT_TRUE(req->resource_names_subscribe().empty()); EXPECT_THAT(req->resource_names_unsubscribe(), UnorderedElementsAre("foo")); // didn't receive a reply - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "bar")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -292,7 +292,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionWithWildcardFromReques deliverSimpleDiscoveryResponse({{"foo", "1"}, {"baz", "1"}, {"wild1", "1"}}, {}, "d1"); // ensure that foo is a part of resource versions, bar won't be, because we don't have its version - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "foo", "bar", "baz")); @@ -307,7 +307,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionWithWildcardFromReques EXPECT_TRUE(req->resource_names_subscribe().empty()); EXPECT_THAT(req->resource_names_unsubscribe(), UnorderedElementsAre("foo", "bar")); deliverSimpleDiscoveryResponse({}, {"foo"}, "d2"); - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "baz")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -326,7 +326,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionWithWildcardFromWildca deliverSimpleDiscoveryResponse({{"foo", "1"}, {"wild1", "1"}}, {}, "d1"); updateSubscriptionInterest({"foo"}, {}); - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "foo")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -347,7 +347,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ResourceTransitionWithWildcardFromAmbigu // make foo ambiguous and request it again updateSubscriptionInterest({}, {"foo"}); updateSubscriptionInterest({"foo"}, {}); - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "foo")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -366,7 +366,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, LegacyWildcardInitialRequests) { // unsubscribing from unknown resource should keep the legacy // wildcard mode updateSubscriptionInterest({}, {"unknown"}); - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_TRUE(req->resource_names_subscribe().empty()); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -382,7 +382,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, LegacyWildcardInitialRequests) { EXPECT_THAT(req->resource_names_unsubscribe(), UnorderedElementsAre("foo")); deliverSimpleDiscoveryResponse({}, {"foo"}, "d1"); - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_TRUE(req->resource_names_subscribe().empty()); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -404,7 +404,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, ReconnectResourcesVersions) { deliverSimpleDiscoveryResponse({{"foo", "2"}, {"wild", "2"}}, {}, "d2"); // Reconnect, and end validate the initial resources versions. - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "foo", "bar")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -412,6 +412,29 @@ TEST_P(DeltaSubscriptionStateTestBlank, ReconnectResourcesVersions) { UnorderedElementsAre(Pair("foo", "2"), Pair("bar", "1"), Pair("wild", "2"))); } +// Validates that if the reconnection notes that it should not send initial resource version, +// then that field isn't populated. +TEST_P(DeltaSubscriptionStateTestBlank, ReconnectAvoidResourcesVersions) { + // Subscribe to foo and bar. + updateSubscriptionInterest({WildcardStr, "foo", "bar"}, {}); + auto req = getNextRequestAckless(); + EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "foo", "bar")); + EXPECT_TRUE(req->resource_names_unsubscribe().empty()); + EXPECT_TRUE(req->initial_resource_versions().empty()); + // Deliver foo, bar, and a wild with version 1. + deliverSimpleDiscoveryResponse({{"foo", "1"}, {"bar", "1"}, {"wild", "1"}}, {}, "d1"); + + // Update the versions of foo and wild to 2. + deliverSimpleDiscoveryResponse({{"foo", "2"}, {"wild", "2"}}, {}, "d2"); + + // Reconnect, and end validate the initial resources versions. + markStreamFresh(false); + req = getNextRequestAckless(); + EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "foo", "bar")); + EXPECT_TRUE(req->resource_names_unsubscribe().empty()); + EXPECT_TRUE(req->initial_resource_versions().empty()); +} + // Check that ambiguous resources may also receive a heartbeat message. TEST_P(DeltaSubscriptionStateTestBlank, AmbiguousResourceTTL) { Event::SimulatedTimeSystem time_system; @@ -482,7 +505,7 @@ TEST_P(DeltaSubscriptionStateTestBlank, IgnoreSuperfluousResources) { // Force a reconnection and resending of the "initial" message. If the initial_resource_versions // in the message contains resources like did-not-want or spam, we haven't ignored that as we // should. - markStreamFresh(); + markStreamFresh(true); req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre("foo", "bar")); EXPECT_TRUE(req->resource_names_unsubscribe().empty()); @@ -550,7 +573,7 @@ TEST_P(DeltaSubscriptionStateTest, NewPushDoesntAddUntrackedResources) { } { // On Reconnection, only "name4", "name5", "name6" are sent. - markStreamFresh(); + markStreamFresh(true); auto cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre("name4", "name5", "name6")); @@ -571,7 +594,7 @@ TEST_P(DeltaSubscriptionStateTest, NewPushDoesntAddUntrackedResources) { EXPECT_EQ(Grpc::Status::WellKnownGrpcStatus::Ok, ack.error_detail_.code()); } { // Simulate a stream reconnection, just to see the current resource_state_. - markStreamFresh(); + markStreamFresh(true); auto cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre("name4", "name5", "name6")); @@ -725,7 +748,7 @@ TEST_P(DeltaSubscriptionStateTest, ResourceGoneLeadsToBlankInitialVersion) { populateRepeatedResource({{"name1", "version1A"}, {"name2", "version2A"}}); EXPECT_CALL(*ttl_timer_, disableTimer()); deliverDiscoveryResponse(add1_2, {}, "debugversion1"); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); EXPECT_EQ("version1A", cur_request->initial_resource_versions().at("name1")); EXPECT_EQ("version2A", cur_request->initial_resource_versions().at("name2")); @@ -741,7 +764,7 @@ TEST_P(DeltaSubscriptionStateTest, ResourceGoneLeadsToBlankInitialVersion) { *remove2.Add() = "name2"; EXPECT_CALL(*ttl_timer_, disableTimer()).Times(2); deliverDiscoveryResponse(add1_3, remove2, "debugversion2"); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); EXPECT_EQ("version1B", cur_request->initial_resource_versions().at("name1")); EXPECT_EQ(cur_request->initial_resource_versions().end(), @@ -755,7 +778,7 @@ TEST_P(DeltaSubscriptionStateTest, ResourceGoneLeadsToBlankInitialVersion) { *remove1_3.Add() = "name1"; *remove1_3.Add() = "name3"; deliverDiscoveryResponse({}, remove1_3, "debugversion3"); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); EXPECT_TRUE(cur_request->initial_resource_versions().empty()); } @@ -786,7 +809,7 @@ TEST_P(DeltaSubscriptionStateTest, SubscribeAndUnsubscribeAfterReconnect) { deliverDiscoveryResponse(add1_2, {}, "debugversion1"); updateSubscriptionInterest({"name4"}, {"name1"}); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); // Regarding the resource_names_subscribe field: // name1: do not include: we lost interest. @@ -810,7 +833,7 @@ TEST_P(DeltaSubscriptionStateTest, SwitchIntoWildcardMode) { // switch into wildcard mode updateSubscriptionInterest({"name4", WildcardStr}, {"name1"}); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); // Regarding the resource_names_subscribe field: // name1: do not include: we lost interest. @@ -826,7 +849,7 @@ TEST_P(DeltaSubscriptionStateTest, SwitchIntoWildcardMode) { populateRepeatedResource({{"name4", "version4A"}, {"name5", "version5A"}}); deliverDiscoveryResponse(add4_5, {}, "debugversion1"); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection cur_request = getNextRequestAckless(); // Regarding the resource_names_subscribe field: // name1: do not include: we lost interest. @@ -851,7 +874,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, SubscribeAndUnsubscribeAfterReconnect EXPECT_CALL(*ttl_timer_, disableTimer()); deliverDiscoveryResponse(add1_2, {}, "debugversion1"); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); // Regarding the resource_names_subscribe field: // name1: do not include: we lost interest. @@ -872,7 +895,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, SubscribeAndUnsubscribeAfterReconnect deliverDiscoveryResponse(add1_2, {}, "debugversion1"); updateSubscriptionInterest({"name3"}, {}); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); // Regarding the resource_names_subscribe field: // name1: do not include: see below @@ -896,7 +919,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, CancellingImplicitWildcardSubscriptio auto cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre("name3")); EXPECT_THAT(cur_request->resource_names_unsubscribe(), UnorderedElementsAre(Wildcard)); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection // Regarding the resource_names_subscribe field: // name1: do not include, see below // name2: do not include: it came from wildcard subscription we lost interest in, so we are not @@ -926,7 +949,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, CancellingExplicitWildcardSubscriptio cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre("name4")); EXPECT_THAT(cur_request->resource_names_unsubscribe(), UnorderedElementsAre(Wildcard)); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection // Regarding the resource_names_subscribe field: // name1: do not include: see name2 // name2: do not include: it came as a part of wildcard subscription we cancelled, so we are not @@ -948,7 +971,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, ExplicitInterestOverridesImplicit) { // verify that neither name1 nor name2 appears in the initial request (they are of implicit // interest and initial wildcard request should not contain those). - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); EXPECT_TRUE(cur_request->resource_names_subscribe().empty()); EXPECT_TRUE(cur_request->resource_names_unsubscribe().empty()); @@ -963,7 +986,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, ExplicitInterestOverridesImplicit) { // verify that name1 and * appear in the initial request (name1 is of explicit interest and we are // in explicit wildcard mode). - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre("name1", Wildcard)); EXPECT_TRUE(cur_request->resource_names_unsubscribe().empty()); @@ -972,7 +995,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, ExplicitInterestOverridesImplicit) { Protobuf::RepeatedPtrField add1_2_b = populateRepeatedResource({{"name1", "version1B"}, {"name2", "version2B"}}); deliverDiscoveryResponse(add1_2_b, {}, "debugversion1"); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre("name1", Wildcard)); EXPECT_TRUE(cur_request->resource_names_unsubscribe().empty()); @@ -992,7 +1015,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, ResetToLegacyWildcardBehaviorOnStream cur_request = getNextRequestAckless(); EXPECT_TRUE(cur_request->resource_names_subscribe().empty()); EXPECT_THAT(cur_request->resource_names_unsubscribe(), UnorderedElementsAre("resource")); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection cur_request = getNextRequestAckless(); EXPECT_TRUE(cur_request->resource_names_subscribe().empty()); EXPECT_TRUE(cur_request->resource_names_unsubscribe().empty()); @@ -1007,7 +1030,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, ResetToLegacyWildcardBehaviorOnStream cur_request = getNextRequestAckless(); EXPECT_TRUE(cur_request->resource_names_subscribe().empty()); EXPECT_THAT(cur_request->resource_names_unsubscribe(), UnorderedElementsAre("resource")); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection updateSubscriptionInterest({}, {}); cur_request = getNextRequestAckless(); EXPECT_TRUE(cur_request->resource_names_subscribe().empty()); @@ -1025,7 +1048,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, AllResourcesFromServerAreTrackedInWil } { // On Reconnection, only "name4", "name5", "name6" and wildcard resource are sent. - markStreamFresh(); + markStreamFresh(true); auto cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "name4", "name5", "name6")); @@ -1046,7 +1069,7 @@ TEST_P(WildcardDeltaSubscriptionStateTest, AllResourcesFromServerAreTrackedInWil EXPECT_EQ(Grpc::Status::WellKnownGrpcStatus::Ok, ack.error_detail_.code()); } { // Simulate a stream reconnection, just to see the current resource_state_. - markStreamFresh(); + markStreamFresh(true); auto cur_request = getNextRequestAckless(); EXPECT_THAT(cur_request->resource_names_subscribe(), UnorderedElementsAre(WildcardStr, "name4", "name5", "name6")); @@ -1069,7 +1092,7 @@ TEST_P(DeltaSubscriptionStateTest, InitialVersionMapFirstMessageOnly) { {{"name1", "version1A"}, {"name2", "version2A"}, {"name3", "version3A"}}); EXPECT_CALL(*ttl_timer_, disableTimer()); deliverDiscoveryResponse(add_all, {}, "debugversion1"); - markStreamFresh(); // simulate a stream reconnection + markStreamFresh(true); // simulate a stream reconnection auto cur_request = getNextRequestAckless(); EXPECT_EQ("version1A", cur_request->initial_resource_versions().at("name1")); EXPECT_EQ("version2A", cur_request->initial_resource_versions().at("name2")); @@ -1098,7 +1121,7 @@ TEST_P(DeltaSubscriptionStateTest, CheckUpdatePending) { EXPECT_FALSE(subscriptionUpdatePending()); updateSubscriptionInterest({}, {}); // no change EXPECT_FALSE(subscriptionUpdatePending()); - markStreamFresh(); + markStreamFresh(true); EXPECT_TRUE(subscriptionUpdatePending()); // no change, BUT fresh stream updateSubscriptionInterest({}, {"name3"}); // one removed EXPECT_TRUE(subscriptionUpdatePending()); @@ -1250,7 +1273,7 @@ TEST_P(DeltaSubscriptionStateTest, NoVersionUpdateOnNack) { EXPECT_NE(Grpc::Status::WellKnownGrpcStatus::Ok, ack.error_detail_.code()); } // Verify that a reconnect keeps the old versions. - markStreamFresh(); + markStreamFresh(true); { auto req = getNextRequestAckless(); EXPECT_THAT(req->resource_names_subscribe(), UnorderedElementsAre("name1", "name2", "name3")); diff --git a/test/extensions/config_subscription/grpc/grpc_mux_failover_test.cc b/test/extensions/config_subscription/grpc/grpc_mux_failover_test.cc index 383b13a750d6..8a990f134fcb 100644 --- a/test/extensions/config_subscription/grpc/grpc_mux_failover_test.cc +++ b/test/extensions/config_subscription/grpc/grpc_mux_failover_test.cc @@ -100,8 +100,8 @@ TEST_F(GrpcMuxFailoverNoFailoverTest, PrimaryOnEstablishmentFailureInvoked) { EXPECT_CALL(primary_stream_, establishNewStream()); grpc_mux_failover_.establishNewStream(); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); - primary_callbacks_->onEstablishmentFailure(); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); + primary_callbacks_->onEstablishmentFailure(false); } // Validates that onDiscoveryResponse callback is invoked on the primary stream @@ -208,16 +208,16 @@ class GrpcMuxFailoverTest : public testing::Test { grpc_mux_failover_->establishNewStream(); // First disconnect. - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); - primary_callbacks_->onEstablishmentFailure(); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); + primary_callbacks_->onEstablishmentFailure(false); // Emulate a retry that ends with a second disconnect. It should close the // primary stream and try to establish the failover stream. EXPECT_CALL(primary_stream_, closeStream()); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); EXPECT_CALL(primary_stream_, establishNewStream()).Times(0); EXPECT_CALL(failover_stream_, establishNewStream()); - primary_callbacks_->onEstablishmentFailure(); + primary_callbacks_->onEstablishmentFailure(false); } // Successfully connect to the failover source. @@ -316,9 +316,9 @@ TEST_F(GrpcMuxFailoverTest, AttemptPrimaryAfterPrimaryInitialFailure) { // First disconnect. EXPECT_CALL(primary_stream_, closeStream()).Times(0); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); EXPECT_CALL(failover_stream_, establishNewStream()).Times(0); - primary_callbacks_->onEstablishmentFailure(); + primary_callbacks_->onEstablishmentFailure(false); } // Validate that upon failure of the second connection to the primary, the @@ -327,16 +327,16 @@ TEST_F(GrpcMuxFailoverTest, AttemptFailoverAfterPrimaryTwoFailures) { connectingToPrimary(); // First disconnect. - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); - primary_callbacks_->onEstablishmentFailure(); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); + primary_callbacks_->onEstablishmentFailure(false); // Emulate a retry that ends with a second disconnect. It should close the // primary stream and try to establish the failover stream. EXPECT_CALL(primary_stream_, closeStream()); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); EXPECT_CALL(primary_stream_, establishNewStream()).Times(0); EXPECT_CALL(failover_stream_, establishNewStream()); - primary_callbacks_->onEstablishmentFailure(); + primary_callbacks_->onEstablishmentFailure(false); } // Validate that starting from the second failure to reach the primary, @@ -345,8 +345,8 @@ TEST_F(GrpcMuxFailoverTest, AlternatingBetweenFailoverAndPrimary) { connectingToPrimary(); // First disconnect. - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); - primary_callbacks_->onEstablishmentFailure(); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); + primary_callbacks_->onEstablishmentFailure(false); // Emulate a 5 times disconnects. for (int attempt = 0; attempt < 5; ++attempt) { @@ -355,19 +355,19 @@ TEST_F(GrpcMuxFailoverTest, AlternatingBetweenFailoverAndPrimary) { // connect to the failover. It should close the primary stream, and // try to establish the failover stream. EXPECT_CALL(primary_stream_, closeStream()); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); EXPECT_CALL(primary_stream_, establishNewStream()).Times(0); EXPECT_CALL(failover_stream_, establishNewStream()); - primary_callbacks_->onEstablishmentFailure(); + primary_callbacks_->onEstablishmentFailure(false); } else { // Emulate a failover source failure that will result in an attempt to // connect to the primary. It should close the failover stream, and // enable the retry timer. EXPECT_CALL(failover_stream_, closeStream()); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); EXPECT_CALL(failover_stream_, establishNewStream()).Times(0); EXPECT_CALL(*timer_, enableTimer(_, _)); - failover_callbacks_->onEstablishmentFailure(); + failover_callbacks_->onEstablishmentFailure(false); // Emulate a timer tick, which should try to reconnect to the primary // stream. EXPECT_CALL(primary_stream_, establishNewStream()); @@ -387,9 +387,9 @@ TEST_F(GrpcMuxFailoverTest, PrimaryOnlyAttemptsAfterPrimaryAvailable) { // connect to the failover. It should not close the primary stream (so // the retry mechanism will kick in). EXPECT_CALL(primary_stream_, closeStream()).Times(0); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(true)); EXPECT_CALL(failover_stream_, establishNewStream()).Times(0); - primary_callbacks_->onEstablishmentFailure(); + primary_callbacks_->onEstablishmentFailure(false); } // Emulate a call to establishNewStream(). @@ -411,10 +411,10 @@ TEST_F(GrpcMuxFailoverTest, AlternatingPrimaryAndFailoverAttemptsAfterFailoverAv // connect to the primary. It should close the failover stream, and // enable the retry timer. EXPECT_CALL(failover_stream_, closeStream()); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); EXPECT_CALL(failover_stream_, establishNewStream()).Times(0); EXPECT_CALL(*timer_, enableTimer(_, _)); - failover_callbacks_->onEstablishmentFailure(); + failover_callbacks_->onEstablishmentFailure(false); // Emulate a timer tick, which should try to reconnect to the primary // stream. EXPECT_CALL(primary_stream_, establishNewStream()); @@ -424,10 +424,12 @@ TEST_F(GrpcMuxFailoverTest, AlternatingPrimaryAndFailoverAttemptsAfterFailoverAv // connect to the failover. It should close the primary stream, and // try to establish the failover stream. EXPECT_CALL(primary_stream_, closeStream()); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + // Expecting "true" to be passed as it was previously connected to the + // failover. + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(true)); EXPECT_CALL(primary_stream_, establishNewStream()).Times(0); EXPECT_CALL(failover_stream_, establishNewStream()); - primary_callbacks_->onEstablishmentFailure(); + primary_callbacks_->onEstablishmentFailure(false); } } @@ -457,10 +459,10 @@ TEST_F(GrpcMuxFailoverTest, TimerDisabledUponExternalReconnect) { // Fail the attempt to connect to the failover. EXPECT_CALL(failover_stream_, closeStream()); - EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure()); + EXPECT_CALL(grpc_mux_callbacks_, onEstablishmentFailure(false)); EXPECT_CALL(failover_stream_, establishNewStream()).Times(0); EXPECT_CALL(*timer_, enableTimer(_, _)); - failover_callbacks_->onEstablishmentFailure(); + failover_callbacks_->onEstablishmentFailure(false); // Attempt to reconnect again. EXPECT_CALL(*timer_, disableTimer()); diff --git a/test/extensions/config_subscription/grpc/grpc_mux_impl_test.cc b/test/extensions/config_subscription/grpc/grpc_mux_impl_test.cc index 93e5d13c5457..df541cd6bf98 100644 --- a/test/extensions/config_subscription/grpc/grpc_mux_impl_test.cc +++ b/test/extensions/config_subscription/grpc/grpc_mux_impl_test.cc @@ -1390,7 +1390,7 @@ TEST_F(NullGrpcMuxImplTest, OnStreamEstablishedImplemented) { EXPECT_NO_THROW(null_mux_.onStreamEstablished()); } TEST_F(NullGrpcMuxImplTest, OnEstablishmentFailureImplemented) { - EXPECT_NO_THROW(null_mux_.onEstablishmentFailure()); + EXPECT_NO_THROW(null_mux_.onEstablishmentFailure(false)); } TEST_F(NullGrpcMuxImplTest, OnDiscoveryResponseImplemented) { std::unique_ptr response; diff --git a/test/extensions/config_subscription/grpc/grpc_stream_test.cc b/test/extensions/config_subscription/grpc/grpc_stream_test.cc index 9f7645c3b712..2ef55b4b367b 100644 --- a/test/extensions/config_subscription/grpc/grpc_stream_test.cc +++ b/test/extensions/config_subscription/grpc/grpc_stream_test.cc @@ -118,14 +118,14 @@ TEST_F(GrpcStreamTest, LogClose) { EXPECT_FALSE(grpc_stream_->getCloseStatusForTest().has_value()); // Benign status: debug. - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS("debug", "gRPC config stream to test_destination closed", { grpc_stream_->onRemoteClose(Grpc::Status::WellKnownGrpcStatus::Ok, "Ok"); }); EXPECT_FALSE(grpc_stream_->getCloseStatusForTest().has_value()); // Non-retriable failure: warn. - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS("warn", "gRPC config stream to test_destination closed", { grpc_stream_->onRemoteClose(Grpc::Status::WellKnownGrpcStatus::NotFound, "Not Found"); }); @@ -134,7 +134,7 @@ TEST_F(GrpcStreamTest, LogClose) { // Repeated failures that warn after enough time. { // Retriable failure: debug. - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS("debug", "gRPC config stream to test_destination closed", { grpc_stream_->onRemoteClose(Grpc::Status::WellKnownGrpcStatus::Unavailable, "Unavailable"); }); @@ -143,7 +143,7 @@ TEST_F(GrpcStreamTest, LogClose) { // Different retriable failure: warn. time_system_.advanceTimeWait(std::chrono::seconds(1)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS("warn", "stream to test_destination closed: 4, Deadline Exceeded (previously 14, " "Unavailable since 1s ago)", @@ -157,7 +157,7 @@ TEST_F(GrpcStreamTest, LogClose) { // Same retriable failure after a short amount of time: debug. time_system_.advanceTimeWait(std::chrono::seconds(1)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS("debug", "gRPC config stream to test_destination closed", { grpc_stream_->onRemoteClose(Grpc::Status::WellKnownGrpcStatus::DeadlineExceeded, "Deadline Exceeded"); @@ -167,7 +167,7 @@ TEST_F(GrpcStreamTest, LogClose) { // Same retriable failure after a long time: warn. time_system_.advanceTimeWait(std::chrono::seconds(100)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS( "warn", "gRPC config stream to test_destination closed since 101s ago: 4, Deadline Exceeded", { @@ -179,7 +179,7 @@ TEST_F(GrpcStreamTest, LogClose) { // Warn again, using the newest message. time_system_.advanceTimeWait(std::chrono::seconds(1)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS( "warn", "gRPC config stream to test_destination closed since 102s ago: 4, new message", { grpc_stream_->onRemoteClose(Grpc::Status::WellKnownGrpcStatus::DeadlineExceeded, @@ -190,7 +190,7 @@ TEST_F(GrpcStreamTest, LogClose) { // Different retriable failure, using the most recent error message from the previous one. time_system_.advanceTimeWait(std::chrono::seconds(1)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_LOG_CONTAINS("warn", "gRPC config stream to test_destination closed: 14, Unavailable " "(previously 4, new message since 103s ago)", @@ -222,7 +222,7 @@ TEST_F(GrpcStreamTest, LogClose) { // sendMessage would segfault. TEST_F(GrpcStreamTest, FailToEstablishNewStream) { EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(nullptr)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); grpc_stream_->establishNewStream(); EXPECT_FALSE(grpc_stream_->grpcStreamAvailable()); } @@ -296,7 +296,7 @@ TEST_F(GrpcStreamTest, RetryOnEstablishNewStreamFailure) { // simulate that first call to establish GRPC stream fails { EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(nullptr)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); // First backoff interval should be 27%25=2 EXPECT_CALL(*grpc_stream_retry_timer, enableTimer(std::chrono::milliseconds(2), _)); grpc_stream_->establishNewStream(); @@ -306,7 +306,7 @@ TEST_F(GrpcStreamTest, RetryOnEstablishNewStreamFailure) { // assume 2ms have passed, invoke callback, fail 2nd time { EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(nullptr)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); // Second backoff interval will be 27%30=27 EXPECT_CALL(*grpc_stream_retry_timer, enableTimer(std::chrono::milliseconds(27), _)); grpc_stream_retry_timer_cb(); @@ -347,7 +347,7 @@ TEST_F(GrpcStreamTest, RetryOnRemoteClose) { } // simulate that remote closes the stream, this should trigger a retry - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); // First backoff interval will be 27%25=2 EXPECT_CALL(*grpc_stream_retry_timer, enableTimer(std::chrono::milliseconds(2), _)); grpc_stream_->onRemoteClose(Grpc::Status::WellKnownGrpcStatus::Unavailable, ""); @@ -356,7 +356,7 @@ TEST_F(GrpcStreamTest, RetryOnRemoteClose) { // assume 2ms have passed, invoke callback, fail the first time { EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(nullptr)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); // Second backoff interval will be 27%30=27 EXPECT_CALL(*grpc_stream_retry_timer, enableTimer(std::chrono::milliseconds(27), _)); grpc_stream_retry_timer_cb(); @@ -366,7 +366,7 @@ TEST_F(GrpcStreamTest, RetryOnRemoteClose) { // assume 27ms have passed, invoke callback, fail the second time { EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(nullptr)); - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); // First backoff interval will be 27%30=27 EXPECT_CALL(*grpc_stream_retry_timer, enableTimer(std::chrono::milliseconds(27), _)); grpc_stream_retry_timer_cb(); @@ -417,7 +417,7 @@ TEST_F(GrpcStreamTest, CloseStreamDisablesRetryTimer) { EXPECT_FALSE(grpc_stream_->grpcStreamAvailable()); // Simulate an establishment failure that will not recreate the timer. - EXPECT_CALL(callbacks_, onEstablishmentFailure()); + EXPECT_CALL(callbacks_, onEstablishmentFailure(true)); EXPECT_CALL(*grpc_stream_retry_timer, enableTimer(_, _)).Times(0); grpc_stream_->onRemoteClose(Grpc::Status::WellKnownGrpcStatus::Unavailable, ""); EXPECT_FALSE(grpc_stream_->grpcStreamAvailable()); diff --git a/test/extensions/config_subscription/grpc/new_grpc_mux_impl_test.cc b/test/extensions/config_subscription/grpc/new_grpc_mux_impl_test.cc index 71f33b93118b..5c27473e03f0 100644 --- a/test/extensions/config_subscription/grpc/new_grpc_mux_impl_test.cc +++ b/test/extensions/config_subscription/grpc/new_grpc_mux_impl_test.cc @@ -61,11 +61,12 @@ class NewGrpcMuxImplTestBase : public testing::TestWithParam(GetParam())) { // Once "envoy.restart_features.xds_failover_support" is deprecated, the // test should no longer be parameterized on the bool value. - scoped_runtime_.mergeValues({{"envoy.restart_features.xds_failover_support", - std::get<1>(GetParam()) ? "true" : "false"}}); + scoped_runtime_.mergeValues( + {{"envoy.restart_features.xds_failover_support", using_xds_failover_ ? "true" : "false"}}); } void setup() { @@ -186,6 +187,7 @@ class NewGrpcMuxImplTestBase : public testing::TestWithParamresponse_nonce()); EXPECT_EQ("version1", cur_request->version_info()); // Reconnect the stream. - state_->markStreamFresh(); + state_->markStreamFresh(true); cur_request = getNextDiscoveryRequestAckless(); EXPECT_EQ("", cur_request->response_nonce()); EXPECT_EQ("version1", cur_request->version_info()); @@ -313,7 +313,7 @@ TEST_F(SotwSubscriptionStateTest, CheckUpdatePending) { EXPECT_FALSE(state_->subscriptionUpdatePending()); state_->updateSubscriptionInterest({}, {}); // no change EXPECT_FALSE(state_->subscriptionUpdatePending()); - state_->markStreamFresh(); + state_->markStreamFresh(true); EXPECT_TRUE(state_->subscriptionUpdatePending()); // no change, BUT fresh stream state_->updateSubscriptionInterest({}, {"name3"}); // one removed EXPECT_TRUE(state_->subscriptionUpdatePending()); diff --git a/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc b/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc index 9318d0150bf3..de4948c91336 100644 --- a/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc +++ b/test/extensions/config_subscription/grpc/xds_failover_integration_test.cc @@ -664,16 +664,17 @@ TEST_P(XdsFailoverAdsIntegrationTest, PrimaryUseAfterFailoverResponseAndDisconne // Ensure basic flow with primary works. Validate that the // initial_resource_versions for delta-xDS is empty. - // TODO(adisuissa): ensure initial_resource_versions is empty, once this is supported. + const absl::flat_hash_map empty_initial_resource_versions_map; EXPECT_TRUE(compareDiscoveryRequest(CdsTypeUrl, "", {}, {}, {}, true, - Grpc::Status::WellKnownGrpcStatus::Ok, "", - xds_stream_.get())); - EXPECT_TRUE( - compareDiscoveryRequest(EdsTypeUrl, "", {"failover_cluster_0"}, {"failover_cluster_0"}, {}, - false, Grpc::Status::WellKnownGrpcStatus::Ok, "", xds_stream_.get())); + Grpc::Status::WellKnownGrpcStatus::Ok, "", xds_stream_.get(), + OptRef(empty_initial_resource_versions_map))); + EXPECT_TRUE(compareDiscoveryRequest(EdsTypeUrl, "", {"failover_cluster_0"}, + {"failover_cluster_0"}, {}, false, + Grpc::Status::WellKnownGrpcStatus::Ok, "", xds_stream_.get(), + OptRef(empty_initial_resource_versions_map))); EXPECT_TRUE(compareDiscoveryRequest(LdsTypeUrl, "", {}, {}, {}, false, - Grpc::Status::WellKnownGrpcStatus::Ok, "", - xds_stream_.get())); + Grpc::Status::WellKnownGrpcStatus::Ok, "", xds_stream_.get(), + OptRef(empty_initial_resource_versions_map))); sendDiscoveryResponse( CdsTypeUrl, {ConfigHelper::buildCluster("primary_cluster_0")}, {ConfigHelper::buildCluster("primary_cluster_0")}, {}, "primary1", {}, xds_stream_.get()); @@ -778,18 +779,22 @@ TEST_P(XdsFailoverAdsIntegrationTest, FailoverUseAfterFailoverResponseAndDisconn RELEASE_ASSERT(result, result.message()); failover_xds_stream_->startGrpcStream(); - // Ensure basic flow with primary works. Validate that the - // initial_resource_versions for delta-xDS is empty. - // TODO(adisuissa): ensure initial_resource_versions contains the correct versions. - EXPECT_TRUE(compareDiscoveryRequest(CdsTypeUrl, "", {}, {}, {}, true, - Grpc::Status::WellKnownGrpcStatus::Ok, "", - failover_xds_stream_.get())); + // Ensure basic flow with failover after it was connected to failover is + // preserved. The initial resource versions of LDS will be empty, because no + // LDS response was previously sent. + const absl::flat_hash_map cds_eds_initial_resource_versions_map{ + {"failover_cluster_0", "failover1"}}; + const absl::flat_hash_map empty_initial_resource_versions_map; + EXPECT_TRUE(compareDiscoveryRequest( + CdsTypeUrl, "", {}, {}, {}, true, Grpc::Status::WellKnownGrpcStatus::Ok, "", + failover_xds_stream_.get(), OptRef(cds_eds_initial_resource_versions_map))); EXPECT_TRUE(compareDiscoveryRequest( EdsTypeUrl, "", {"failover_cluster_0"}, {"failover_cluster_0"}, {}, false, - Grpc::Status::WellKnownGrpcStatus::Ok, "", failover_xds_stream_.get())); - EXPECT_TRUE(compareDiscoveryRequest(LdsTypeUrl, "", {}, {}, {}, false, - Grpc::Status::WellKnownGrpcStatus::Ok, "", - failover_xds_stream_.get())); + Grpc::Status::WellKnownGrpcStatus::Ok, "", failover_xds_stream_.get(), + OptRef(cds_eds_initial_resource_versions_map))); + EXPECT_TRUE(compareDiscoveryRequest( + LdsTypeUrl, "", {}, {}, {}, false, Grpc::Status::WellKnownGrpcStatus::Ok, "", + failover_xds_stream_.get(), OptRef(empty_initial_resource_versions_map))); sendDiscoveryResponse( CdsTypeUrl, {ConfigHelper::buildCluster("failover_cluster_1")}, {ConfigHelper::buildCluster("failover_cluster_1")}, {}, "failover2", {}, diff --git a/test/integration/base_integration_test.cc b/test/integration/base_integration_test.cc index 457f03b0a011..6cabd66f3dfb 100644 --- a/test/integration/base_integration_test.cc +++ b/test/integration/base_integration_test.cc @@ -613,16 +613,17 @@ AssertionResult BaseIntegrationTest::compareDiscoveryRequest( const std::vector& expected_resource_names_added, const std::vector& expected_resource_names_removed, bool expect_node, const Protobuf::int32 expected_error_code, const std::string& expected_error_substring, - FakeStream* stream) { + FakeStream* stream, + OptRef> initial_resource_versions) { if (sotw_or_delta_ == Grpc::SotwOrDelta::Sotw || sotw_or_delta_ == Grpc::SotwOrDelta::UnifiedSotw) { return compareSotwDiscoveryRequest(expected_type_url, expected_version, expected_resource_names, expect_node, expected_error_code, expected_error_substring, stream); } else { - return compareDeltaDiscoveryRequest(expected_type_url, expected_resource_names_added, - expected_resource_names_removed, stream, - expected_error_code, expected_error_substring, expect_node); + return compareDeltaDiscoveryRequest( + expected_type_url, expected_resource_names_added, expected_resource_names_removed, stream, + expected_error_code, expected_error_substring, expect_node, initial_resource_versions); } } @@ -730,7 +731,8 @@ AssertionResult BaseIntegrationTest::compareDeltaDiscoveryRequest( const std::vector& expected_resource_subscriptions, const std::vector& expected_resource_unsubscriptions, FakeStream* xds_stream, const Protobuf::int32 expected_error_code, const std::string& expected_error_substring, - bool expect_node) { + bool expect_node, + OptRef> initial_resource_versions) { envoy::service::discovery::v3::DeltaDiscoveryRequest request; if (xds_stream == nullptr) { xds_stream = xds_stream_.get(); @@ -765,7 +767,34 @@ AssertionResult BaseIntegrationTest::compareDeltaDiscoveryRequest( if (!unsub_result) { return unsub_result; } - // (We don't care about response_nonce or initial_resource_versions.) + // Validate initial_resource_versions if given (otherwise, we don't care what + // the request contains). + if (initial_resource_versions.has_value()) { + const auto& req_map = request.initial_resource_versions(); + // Compare size, and that elements in one map appear in the other. + if (req_map.size() != initial_resource_versions->size()) { + return AssertionFailure() << fmt::format( + "Wrong size of initial_resource_versions. Expected: {}, observed: {}.\n{}", + initial_resource_versions->size(), req_map.size(), + absl::StrJoin(req_map, ", ", absl::PairFormatter("="))); + } + EXPECT_EQ(req_map.size(), initial_resource_versions->size()); + for (const auto& [resource_name, resource_version] : *initial_resource_versions) { + auto it = req_map.find(resource_name); + if (it == req_map.end()) { + return AssertionFailure() << fmt::format( + "Could not find resource {} in received initial_resource_versions map: {}", + resource_name, absl::StrJoin(req_map, ", ", absl::PairFormatter("="))); + } + if (resource_version != it->second) { + return AssertionFailure() << fmt::format( + "Incorrect resource version {} in received initial_resource_versions map. " + "Expected: {}, observed: {}", + resource_name, resource_version, it->second); + } + } + } + // (We don't care about response_nonce.) if (request.error_detail().code() != expected_error_code) { return AssertionFailure() << fmt::format( diff --git a/test/integration/base_integration_test.h b/test/integration/base_integration_test.h index 6278768d6d2d..a1b571699b60 100644 --- a/test/integration/base_integration_test.h +++ b/test/integration/base_integration_test.h @@ -185,7 +185,9 @@ class BaseIntegrationTest : protected Logger::Loggable { const std::vector& expected_resource_names_added, const std::vector& expected_resource_names_removed, bool expect_node = false, const Protobuf::int32 expected_error_code = Grpc::Status::WellKnownGrpcStatus::Ok, - const std::string& expected_error_message = "", FakeStream* stream = nullptr); + const std::string& expected_error_message = "", FakeStream* stream = nullptr, + OptRef> initial_resource_versions = + absl::nullopt); template void @@ -219,7 +221,9 @@ class BaseIntegrationTest : protected Logger::Loggable { const std::vector& expected_resource_subscriptions, const std::vector& expected_resource_unsubscriptions, FakeStream* stream, const Protobuf::int32 expected_error_code = Grpc::Status::WellKnownGrpcStatus::Ok, - const std::string& expected_error_message = "", bool expect_node = true); + const std::string& expected_error_message = "", bool expect_node = true, + OptRef> initial_resource_versions = + absl::nullopt); AssertionResult compareSotwDiscoveryRequest( const std::string& expected_type_url, const std::string& expected_version, diff --git a/test/mocks/config/mocks.h b/test/mocks/config/mocks.h index f24e28806b51..f153a22aa229 100644 --- a/test/mocks/config/mocks.h +++ b/test/mocks/config/mocks.h @@ -140,7 +140,7 @@ class MockGrpcStreamCallbacks ~MockGrpcStreamCallbacks() override; MOCK_METHOD(void, onStreamEstablished, ()); - MOCK_METHOD(void, onEstablishmentFailure, ()); + MOCK_METHOD(void, onEstablishmentFailure, (bool)); MOCK_METHOD(void, onDiscoveryResponse, (std::unique_ptr && message, ControlPlaneStats& control_plane_stats)); From c778169c66af0ebc15398129ac0790fc08942439 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Sun, 25 Aug 2024 00:30:45 +0000 Subject: [PATCH 32/53] deps/api: Bump `envoy_toolshed` -> 0.1.11 (#35838) Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index c02bf5e55ed3..d7f92d9ff693 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -179,12 +179,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "envoy_toolshed", project_desc = "Tooling, libraries, runners and checkers for Envoy proxy's CI", project_url = "https://github.com/envoyproxy/toolshed", - version = "0.1.4", - sha256 = "7ddfd251a89518b97c4eb8064a7d37454bbd998bf29e4cd3ad8f44227b5ca7b3", + version = "0.1.11", + sha256 = "f868812bff7ae372e4b53d565ee75a999d33e09b2980cc0c3dfa40684f85bbda", strip_prefix = "toolshed-bazel-v{version}/bazel", urls = ["https://github.com/envoyproxy/toolshed/archive/bazel-v{version}.tar.gz"], use_category = ["build"], - release_date = "2024-07-22", + release_date = "2024-08-24", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/envoyproxy/envoy/blob/bazel-v{version}/LICENSE", From 47d71007d5eae2f8d686d46aeaf6cef9eccecb72 Mon Sep 17 00:00:00 2001 From: htuch Date: Sun, 25 Aug 2024 12:23:01 -0400 Subject: [PATCH 33/53] owners: move htuch@ to emeritus. (#35828) End of an era, thanks everyone for the opportunity to be part of this amazing community. --------- Signed-off-by: Harvey Tuch --- CODEOWNERS | 26 +++++++++++++------------- OWNERS.md | 3 +-- SECURITY-INSIGHTS.yml | 1 - reviewers.yaml | 4 ---- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 0f41ef52037c..be38c7a507cd 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -29,8 +29,8 @@ extensions/filters/common/original_src @klarose @mattklein123 # cdn_loop extension /*/extensions/filters/http/cdn_loop @justin-mp @penguingao @alyssawilk # external processing filter -/*/extensions/filters/http/ext_proc @gbrail @stevenzzzz @tyxia @mattklein123 @htuch @yanavlasov -/*/extensions/filters/common/mutation_rules @gbrail @tyxia @mattklein123 @htuch @yanavlasov +/*/extensions/filters/http/ext_proc @gbrail @stevenzzzz @tyxia @mattklein123 @yanavlasov +/*/extensions/filters/common/mutation_rules @gbrail @tyxia @mattklein123 @yanavlasov # jwt_authn http filter extension /*/extensions/filters/http/jwt_authn @taoxuy @lizan @tyxia @yanavlasov # grpc_field_extraction http filter extension @@ -68,7 +68,7 @@ extensions/filters/common/original_src @klarose @mattklein123 # tracers.skywalking extension /*/extensions/tracers/skywalking @wbpcode @Shikugawa # tracers.opentelemetry extension -/*/extensions/tracers/opentelemetry @alexanderellis @htuch +/*/extensions/tracers/opentelemetry @alexanderellis @yanavlasov # quic extension /*/extensions/quic/ @alyssawilk @danzh2010 @mattklein123 @mpwarres @wu-bin @ggreenway # UDP packet writer @@ -128,8 +128,8 @@ extensions/filters/common/original_src @klarose @mattklein123 /*/extensions/filters/http/connect_grpc_bridge @jchadwick-buf @mattklein123 /*/extensions/filters/common/original_src @klarose @mattklein123 /*/extensions/filters/listener/tls_inspector @ggreenway @KBaichoo -/*/extensions/grpc_credentials/example @wozz @htuch -/*/extensions/grpc_credentials/file_based_metadata @wozz @htuch +/*/extensions/grpc_credentials/example @wozz @yanavlasov +/*/extensions/grpc_credentials/file_based_metadata @wozz @yanavlasov /*/extensions/internal_redirect @alyssawilk @penguingao /*/extensions/stat_sinks/dog_statsd @taiki45 @jmarantz /*/extensions/stat_sinks/graphite_statsd @vaccarium @mattklein123 @@ -138,22 +138,22 @@ extensions/filters/common/original_src @klarose @mattklein123 /*/extensions/stat_sinks/open_telemetry @ohadvano @mattklein123 # webassembly stat-sink extensions /*/extensions/stat_sinks/wasm @mpwarres @lizan @UNOWNED -/*/extensions/resource_monitors/injected_resource @eziskind @htuch -/*/extensions/resource_monitors/common @eziskind @htuch @nezdolik -/*/extensions/resource_monitors/fixed_heap @eziskind @htuch @nezdolik +/*/extensions/resource_monitors/injected_resource @eziskind @yanavlasov +/*/extensions/resource_monitors/common @eziskind @yanavlasov @nezdolik +/*/extensions/resource_monitors/fixed_heap @eziskind @yanavlasov @nezdolik /*/extensions/resource_monitors/downstream_connections @nezdolik @mattklein123 /*/extensions/retry/priority @alyssawilk @mattklein123 /*/extensions/retry/priority/previous_priorities @alyssawilk @mattklein123 /*/extensions/retry/host @alyssawilk @mattklein123 /*/extensions/filters/network/http_connection_manager @alyssawilk @mattklein123 /*/extensions/filters/network/tcp_proxy @alyssawilk @zuercher @ggreenway -/*/extensions/filters/network/echo @htuch @alyssawilk +/*/extensions/filters/network/echo @yanavlasov @alyssawilk /*/extensions/filters/udp/dns_filter @mattklein123 @yanjunxiang-google /*/extensions/filters/network/direct_response @kyessenov @zuercher /*/extensions/filters/udp/udp_proxy @mattklein123 @danzh2010 /*/extensions/clusters/aggregate @yxue @mattklein123 # support for on-demand VHDS requests -/*/extensions/filters/http/on_demand @dmitri-d @htuch @kyessenov +/*/extensions/filters/http/on_demand @dmitri-d @yanavlasov @kyessenov /*/extensions/filters/network/connection_limit @mattklein123 @alyssawilk @delong-coder /*/extensions/filters/http/aws_request_signing @derekargueta @suniltheta @mattklein123 @marcomagdy @nbaws /*/extensions/filters/http/aws_lambda @suniltheta @mattklein123 @marcomagdy @nbaws @@ -170,7 +170,7 @@ extensions/filters/http/oauth2 @derekargueta @mattklein123 /*/extensions/filters/http/local_ratelimit @mattklein123 @wbpcode /*/extensions/filters/common/local_ratelimit @mattklein123 @wbpcode # HTTP Kill Request -/*/extensions/filters/http/kill_request @qqustc @htuch +/*/extensions/filters/http/kill_request @qqustc @yanavlasov # Rate limit expression descriptor /*/extensions/rate_limit_descriptors/expr @kyessenov @cpakulski # hash input matcher @@ -223,7 +223,7 @@ extensions/filters/http/oauth2 @derekargueta @mattklein123 # Key Value store /*/extensions/key_value @alyssawilk @ryantheoptimist # Config Validators -/*/extensions/config/validators/minimum_clusters @adisuissa @htuch +/*/extensions/config/validators/minimum_clusters @adisuissa @yanavlasov # File system based extensions /*/extensions/common/async_files @mattklein123 @ravenblackx /*/extensions/filters/http/file_system_buffer @mattklein123 @ravenblackx @@ -335,7 +335,7 @@ extensions/filters/http/oauth2 @derekargueta @mattklein123 # String matching extensions /*/extensions/string_matcher/ @ggreenway @cpakulski # Header mutation -/*/extensions/filters/http/header_mutation @wbpcode @htuch @soulxu +/*/extensions/filters/http/header_mutation @wbpcode @yanavlasov @soulxu # Health checkers /*/extensions/health_checkers/grpc @zuercher @botengyao /*/extensions/health_checkers/http @zuercher @botengyao diff --git a/OWNERS.md b/OWNERS.md index aeccaeb0fe10..c001eb66a13e 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -11,8 +11,6 @@ routing PRs, questions, etc. to the right place. * Matt Klein ([mattklein123](https://github.com/mattklein123)) (mattklein123@gmail.com) * Catch-all, "all the things", and generally trying to make himself obsolete as fast as possible. -* Harvey Tuch ([htuch](https://github.com/htuch)) (htuch@google.com) - * xDS APIs, configuration and control plane. * Alyssa Wilk ([alyssawilk](https://github.com/alyssawilk)) (alyssar@google.com) * HTTP, flow control, cluster manager, load balancing, and core networking (listeners, connections, etc.), Envoy Mobile. @@ -107,6 +105,7 @@ without further review. * Rafal Augustyniak ([Augustyniak](https://github.com/Augustyniak)) (raugustyniak@lyft.com) * Snow Pettersen ([snowp](https://github.com/snowp)) (aickck@gmail.com) * Lizan Zhou ([lizan](https://github.com/lizan)) (lizan.j@gmail.com) +* Harvey Tuch ([htuch](https://github.com/htuch)) (htuch@google.com) # Friends of Envoy diff --git a/SECURITY-INSIGHTS.yml b/SECURITY-INSIGHTS.yml index 9fb54737a199..e065fbc636eb 100644 --- a/SECURITY-INSIGHTS.yml +++ b/SECURITY-INSIGHTS.yml @@ -12,7 +12,6 @@ project-lifecycle: core-maintainers: # from https://github.com/envoyproxy/envoy/blob/main/OWNERS.md # Senior maintainers - github:mattklein123 - - github:htuch - github:alyssawilk - github:zuercher - github:lizan diff --git a/reviewers.yaml b/reviewers.yaml index 7bd02f4eee65..49760243e993 100644 --- a/reviewers.yaml +++ b/reviewers.yaml @@ -16,10 +16,6 @@ ggreenway: maintainer: true opsgenie: Greg slack: U78MBV869 -htuch: - maintainer: true - opsgenie: Harvey - slack: U78E7055Z jmarantz: maintainer: true opsgenie: Joshua From 20e27887d29d735e1cc47cbb9af1cfe9baac4b4d Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Sun, 25 Aug 2024 12:24:43 -0400 Subject: [PATCH 34/53] Add jitter to strict and logical dns clusters (#35745) Resolves #35641. Adding DNS jitter to resolvers makes it so that envoy doesnt stampede the DNS server when it has multiple entries with the same expiration. Testing is still WIP. I am open to any suggestions. Commit Message: dns: add jitter to strict dns Additional Description: Risk Level: low Testing: unit tests Docs Changes: Release Notes: for the :ref:`strict DNS ` and :ref:`logical DNS ` cluster types, the new :ref:`dns_jitter ` field, if provided, will causes the cluster to refresh DNS entries later by a random amount of time as to avoid stampedes of DNS requests. This field sets the upper bound (exclusive) for the random amount. Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] --------- Signed-off-by: Steven Jin Xuan Signed-off-by: Steven Jin Co-authored-by: Adi (Suissa) Peleg --- api/envoy/config/cluster/v3/cluster.proto | 13 +++++- changelogs/current.yaml | 7 +++ .../logical_dns/logical_dns_cluster.cc | 4 ++ .../logical_dns/logical_dns_cluster.h | 1 + .../clusters/strict_dns/strict_dns_cluster.cc | 8 ++++ .../clusters/strict_dns/strict_dns_cluster.h | 1 + test/common/upstream/upstream_impl_test.cc | 45 ++++++++++++++++++- test/extensions/clusters/logical_dns/BUILD | 1 + .../logical_dns/logical_dns_cluster_test.cc | 40 +++++++++++++++++ 9 files changed, 118 insertions(+), 2 deletions(-) diff --git a/api/envoy/config/cluster/v3/cluster.proto b/api/envoy/config/cluster/v3/cluster.proto index ef6bbe121b4c..0e034b3dde44 100644 --- a/api/envoy/config/cluster/v3/cluster.proto +++ b/api/envoy/config/cluster/v3/cluster.proto @@ -45,7 +45,7 @@ message ClusterCollection { } // Configuration for a single upstream cluster. -// [#next-free-field: 58] +// [#next-free-field: 59] message Cluster { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.Cluster"; @@ -956,6 +956,17 @@ message Cluster { google.protobuf.Duration dns_refresh_rate = 16 [(validate.rules).duration = {gt {nanos: 1000000}}]; + // DNS jitter can be optionally specified if the cluster type is either + // :ref:`STRICT_DNS`, + // or :ref:`LOGICAL_DNS`. + // DNS jitter causes the cluster to refresh DNS entries later by a random amount of time to avoid a + // stampede of DNS requests. This value sets the upper bound (exclusive) for the random amount. + // There will be no jitter if this value is omitted. For cluster types other than + // :ref:`STRICT_DNS` + // and :ref:`LOGICAL_DNS` + // this setting is ignored. + google.protobuf.Duration dns_jitter = 58; + // If the DNS failure refresh rate is specified and the cluster type is either // :ref:`STRICT_DNS`, // or :ref:`LOGICAL_DNS`, diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 571570861bdc..33d669ab5915 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -159,6 +159,13 @@ removed_config_or_runtime: Removed ``envoy.reloadable_features.normalize_host_for_preresolve_dfp_dns`` runtime flag and legacy code paths. new_features: +- area: dns + change: | + for the :ref:`strict DNS ` and :ref:`logical DNS + ` cluster types, + the new :ref:`dns_jitter ` field, if + provided, will causes the cluster to refresh DNS entries later by a random amount of time as to + avoid stampedes of DNS requests. This field sets the upper bound (exclusive) for the random amount. - area: redis change: | Added support for publish. diff --git a/source/extensions/clusters/logical_dns/logical_dns_cluster.cc b/source/extensions/clusters/logical_dns/logical_dns_cluster.cc index 927a49804c1f..a29ac2194940 100644 --- a/source/extensions/clusters/logical_dns/logical_dns_cluster.cc +++ b/source/extensions/clusters/logical_dns/logical_dns_cluster.cc @@ -51,6 +51,7 @@ LogicalDnsCluster::LogicalDnsCluster(const envoy::config::cluster::v3::Cluster& : ClusterImplBase(cluster, context, creation_status), dns_resolver_(dns_resolver), dns_refresh_rate_ms_( std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_refresh_rate, 5000))), + dns_jitter_ms_(std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_jitter, 0))), respect_dns_ttl_(cluster.respect_dns_ttl()), resolve_timer_(context.serverFactoryContext().mainThreadDispatcher().createTimer( [this]() -> void { startResolve(); })), @@ -149,6 +150,9 @@ void LogicalDnsCluster::startResolve() { if (respect_dns_ttl_ && addrinfo.ttl_ != std::chrono::seconds(0)) { final_refresh_rate = addrinfo.ttl_; } + if (dns_jitter_ms_.count() != 0) { + final_refresh_rate += std::chrono::milliseconds(random_.random()) % dns_jitter_ms_; + } ENVOY_LOG(debug, "DNS refresh rate reset for {}, refresh rate {} ms", dns_address_, final_refresh_rate.count()); } else { diff --git a/source/extensions/clusters/logical_dns/logical_dns_cluster.h b/source/extensions/clusters/logical_dns/logical_dns_cluster.h index b94d551b240b..8522af08edd8 100644 --- a/source/extensions/clusters/logical_dns/logical_dns_cluster.h +++ b/source/extensions/clusters/logical_dns/logical_dns_cluster.h @@ -69,6 +69,7 @@ class LogicalDnsCluster : public ClusterImplBase { Network::DnsResolverSharedPtr dns_resolver_; const std::chrono::milliseconds dns_refresh_rate_ms_; + const std::chrono::milliseconds dns_jitter_ms_; BackOffStrategyPtr failure_backoff_strategy_; const bool respect_dns_ttl_; Network::DnsLookupFamily dns_lookup_family_; diff --git a/source/extensions/clusters/strict_dns/strict_dns_cluster.cc b/source/extensions/clusters/strict_dns/strict_dns_cluster.cc index a052fd9cb3df..d2b1794ec57c 100644 --- a/source/extensions/clusters/strict_dns/strict_dns_cluster.cc +++ b/source/extensions/clusters/strict_dns/strict_dns_cluster.cc @@ -1,5 +1,7 @@ #include "source/extensions/clusters/strict_dns/strict_dns_cluster.h" +#include + #include "envoy/common/exception.h" #include "envoy/config/cluster/v3/cluster.pb.h" #include "envoy/config/endpoint/v3/endpoint.pb.h" @@ -29,6 +31,7 @@ StrictDnsClusterImpl::StrictDnsClusterImpl(const envoy::config::cluster::v3::Clu local_info_(context.serverFactoryContext().localInfo()), dns_resolver_(dns_resolver), dns_refresh_rate_ms_( std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_refresh_rate, 5000))), + dns_jitter_ms_(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_jitter, 0)), respect_dns_ttl_(cluster.respect_dns_ttl()) { failure_backoff_strategy_ = Config::Utility::prepareDnsRefreshStrategy( @@ -189,6 +192,11 @@ void StrictDnsClusterImpl::ResolveTarget::startResolve() { ASSERT(ttl_refresh_rate != std::chrono::seconds::max() && final_refresh_rate.count() > 0); } + if (parent_.dns_jitter_ms_.count() > 0) { + final_refresh_rate += + std::chrono::milliseconds(parent_.random_.random()) % parent_.dns_jitter_ms_; + } + ENVOY_LOG(debug, "DNS refresh rate reset for {}, refresh rate {} ms", dns_address_, final_refresh_rate.count()); } else { diff --git a/source/extensions/clusters/strict_dns/strict_dns_cluster.h b/source/extensions/clusters/strict_dns/strict_dns_cluster.h index 6d8cd9f3923d..72b4070e5a85 100644 --- a/source/extensions/clusters/strict_dns/strict_dns_cluster.h +++ b/source/extensions/clusters/strict_dns/strict_dns_cluster.h @@ -69,6 +69,7 @@ class StrictDnsClusterImpl : public BaseDynamicClusterImpl { Network::DnsResolverSharedPtr dns_resolver_; std::list resolve_targets_; const std::chrono::milliseconds dns_refresh_rate_ms_; + const std::chrono::milliseconds dns_jitter_ms_; BackOffStrategyPtr failure_backoff_strategy_; const bool respect_dns_ttl_; Network::DnsLookupFamily dns_lookup_family_; diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index b0d5217b2bb2..b7c23e96f2ae 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -1432,7 +1432,7 @@ TEST_F(StrictDnsClusterImplTest, FailureRefreshRateBackoffResetsWhenSuccessHappe TestUtility::makeDnsResponse({})); } -TEST_F(StrictDnsClusterImplTest, TtlAsDnsRefreshRate) { +TEST_F(StrictDnsClusterImplTest, TtlAsDnsRefreshRateNoJitter) { ResolverData resolver(*dns_resolver_, server_context_.dispatcher_); const std::string yaml = R"EOF( @@ -1488,6 +1488,49 @@ TEST_F(StrictDnsClusterImplTest, TtlAsDnsRefreshRate) { TestUtility::makeDnsResponse({}, std::chrono::seconds(5))); } +TEST_F(StrictDnsClusterImplTest, TtlAsDnsRefreshRateYesJitter) { + ResolverData resolver(*dns_resolver_, server_context_.dispatcher_); + + const std::string yaml = R"EOF( + name: name + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + dns_refresh_rate: 4s + dns_jitter: 1s + respect_dns_ttl: true + load_assignment: + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost1 + port_value: 11001 + )EOF"; + + envoy::config::cluster::v3::Cluster cluster_config = parseClusterFromV3Yaml(yaml); + + Envoy::Upstream::ClusterFactoryContextImpl factory_context( + server_context_, server_context_.cluster_manager_, nullptr, ssl_context_manager_, nullptr, + false); + + auto cluster = *StrictDnsClusterImpl::create(cluster_config, factory_context, dns_resolver_); + + cluster->initialize([] {}); + + uint64_t random_return = 8500; + uint64_t jitter_ms = random_return % 1000; + uint64_t ttl_s = 6; + + EXPECT_CALL(*resolver.timer_, + enableTimer(std::chrono::milliseconds(ttl_s * 1000 + jitter_ms), _)); + ON_CALL(random_, random()).WillByDefault(Return(random_return)); + resolver.dns_callback_( + Network::DnsResolver::ResolutionStatus::Success, "", + TestUtility::makeDnsResponse({"192.168.1.1", "192.168.1.2"}, std::chrono::seconds(ttl_s))); +} + // Ensures that HTTP/2 user defined SETTINGS parameter validation is enforced on clusters. TEST_F(StrictDnsClusterImplTest, Http2UserDefinedSettingsParametersValidation) { const std::string yaml = R"EOF( diff --git a/test/extensions/clusters/logical_dns/BUILD b/test/extensions/clusters/logical_dns/BUILD index c5d3e64052c6..a2d92aa47e8f 100644 --- a/test/extensions/clusters/logical_dns/BUILD +++ b/test/extensions/clusters/logical_dns/BUILD @@ -12,6 +12,7 @@ envoy_cc_test( name = "logical_dns_cluster_test", srcs = ["logical_dns_cluster_test.cc"], deps = [ + "//source/common/common:random_generator_lib", "//source/common/event:dispatcher_lib", "//source/common/network:utility_lib", "//source/common/upstream:upstream_lib", diff --git a/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc b/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc index 65de11b49f41..b781b28e2697 100644 --- a/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc +++ b/test/extensions/clusters/logical_dns/logical_dns_cluster_test.cc @@ -607,6 +607,46 @@ TEST_F(LogicalDnsClusterTest, DontWaitForDNSOnInit) { TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"})); } +TEST_F(LogicalDnsClusterTest, DNSRefreshHasJitter) { + const std::string config = R"EOF( + name: name + type: LOGICAL_DNS + dns_refresh_rate: 4s + dns_jitter: + seconds: 0 + nanos: 512000000 + connect_timeout: 0.25s + lb_policy: ROUND_ROBIN + # Since the following expectResolve() requires Network::DnsLookupFamily::V4Only we need to set + # dns_lookup_family to V4_ONLY explicitly for v2 .yaml config. + dns_lookup_family: V4_ONLY + wait_for_warm_on_init: false + load_assignment: + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: foo.bar.com + port_value: 443 + )EOF"; + + uint64_t random_return = 8000; + uint64_t jitter_ms = random_return % 512; // default value + + EXPECT_CALL(initialized_, ready()); + expectResolve(Network::DnsLookupFamily::V4Only, "foo.bar.com"); + setupFromV3Yaml(config); + + EXPECT_CALL(membership_updated_, ready()); + EXPECT_CALL(*resolve_timer_, enableTimer(std::chrono::milliseconds(4000 + jitter_ms), _)); + ON_CALL(random_, random()).WillByDefault(Return(random_return)); + + dns_callback_( + Network::DnsResolver::ResolutionStatus::Success, "", + TestUtility::makeDnsResponse({"127.0.0.1", "127.0.0.2"}, std::chrono::seconds(3000))); +} + } // namespace } // namespace Upstream } // namespace Envoy From c981081571012391602c50382b1ff032fcb05c08 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Sun, 25 Aug 2024 09:31:18 -0700 Subject: [PATCH 35/53] dynamic_modules: scaffolds ABI header and compatibility check (#35626) Commit Message: dynamic_modules: scaffolds ABI header and compatibility check Additional Description: This commit scaffolds the ABI header and implements the version check. sha256 hash will be calculated on the ABI headers, and the result value is used to check the compatibility. Risk Level: N/A Testing: unit Docs Changes: N/A Release Notes: N/A Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] --------- Signed-off-by: Takeshi Yoneda --- .clang-tidy | 1 + source/extensions/dynamic_modules/BUILD | 13 +++- source/extensions/dynamic_modules/abi.h | 68 +++++++++++++++++++ .../extensions/dynamic_modules/abi_version.h | 15 ++++ .../dynamic_modules/dynamic_modules.cc | 27 +++++++- test/extensions/dynamic_modules/BUILD | 20 +++++- .../dynamic_modules/abi_version_test.cc | 32 +++++++++ .../dynamic_modules/dynamic_modules_test.cc | 68 ++++++++++++++++--- .../dynamic_modules/test_data/BUILD | 7 -- .../dynamic_modules/test_data/c/BUILD | 13 ++++ .../test_data/c/abi_version_mismatch.c | 5 ++ .../dynamic_modules/test_data/c/no_op.c | 10 +++ .../test_data/c/no_program_init.c | 1 + .../test_data/c/program_init_fail.c | 3 + .../test_data/{ => c}/test_data.bzl | 2 +- .../dynamic_modules/test_data/no_op.c | 5 -- 16 files changed, 264 insertions(+), 26 deletions(-) create mode 100644 source/extensions/dynamic_modules/abi.h create mode 100644 source/extensions/dynamic_modules/abi_version.h create mode 100644 test/extensions/dynamic_modules/abi_version_test.cc delete mode 100644 test/extensions/dynamic_modules/test_data/BUILD create mode 100644 test/extensions/dynamic_modules/test_data/c/BUILD create mode 100644 test/extensions/dynamic_modules/test_data/c/abi_version_mismatch.c create mode 100644 test/extensions/dynamic_modules/test_data/c/no_op.c create mode 100644 test/extensions/dynamic_modules/test_data/c/no_program_init.c create mode 100644 test/extensions/dynamic_modules/test_data/c/program_init_fail.c rename test/extensions/dynamic_modules/test_data/{ => c}/test_data.bzl (74%) delete mode 100644 test/extensions/dynamic_modules/test_data/no_op.c diff --git a/.clang-tidy b/.clang-tidy index 72f533b39c11..2d6ca62206d1 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -83,6 +83,7 @@ CheckOptions: |Returns(Default)?WorkerId$| |^sched_getaffinity$| |^shutdownThread_$| + |^envoy_dynamic_module(.*)$| |TEST| |^use_count$) - key: readability-identifier-naming.ParameterCase diff --git a/source/extensions/dynamic_modules/BUILD b/source/extensions/dynamic_modules/BUILD index 008e2ad84734..b7e22b2a9edc 100644 --- a/source/extensions/dynamic_modules/BUILD +++ b/source/extensions/dynamic_modules/BUILD @@ -11,12 +11,19 @@ envoy_extension_package() envoy_cc_library( name = "dynamic_modules_lib", srcs = [ + "abi.h", "dynamic_modules.cc", ], - hdrs = [ - "dynamic_modules.h", - ], + hdrs = ["dynamic_modules.h"], deps = [ + ":abi_version_lib", "//envoy/common:exception_lib", ], ) + +envoy_cc_library( + name = "abi_version_lib", + hdrs = [ + "abi_version.h", + ], +) diff --git a/source/extensions/dynamic_modules/abi.h b/source/extensions/dynamic_modules/abi.h new file mode 100644 index 000000000000..460dc00cef58 --- /dev/null +++ b/source/extensions/dynamic_modules/abi.h @@ -0,0 +1,68 @@ +#pragma once + +// NOLINT(namespace-envoy) + +// This is a pure C header file that defines the ABI of the core of dynamic modules used by Envoy. +// +// This must not contain any dependencies besides standard library since it is not only used by +// Envoy itself but also by dynamic module SDKs written in non-C++ languages. +// +// Currently, compatibility is only guaranteed by an exact version match between the Envoy +// codebase and the dynamic module SDKs. In the future, after the ABI is stabilized, we will revisit +// this restriction and hopefully provide a wider compatibility guarantee. Until then, Envoy +// checks the hash of the ABI header files to ensure that the dynamic modules are built against the +// same version of the ABI. + +#ifdef __cplusplus +#include + +extern "C" { +#else +#include +#endif + +// ----------------------------------------------------------------------------- +// ---------------------------------- Types ------------------------------------ +// ----------------------------------------------------------------------------- +// +// Types used in the ABI. The name of a type must be prefixed with "envoy_dynamic_module_type_". + +/** + * envoy_dynamic_module_type_abi_version represents a null-terminated string that contains the ABI + * version of the dynamic module. This is used to ensure that the dynamic module is built against + * the compatible version of the ABI. + */ +typedef const char* envoy_dynamic_module_type_abi_version; // NOLINT(modernize-use-using) + +// ----------------------------------------------------------------------------- +// ------------------------------- Event Hooks --------------------------------- +// ----------------------------------------------------------------------------- +// +// Event hooks are functions that are called by Envoy in response to certain events. +// The module must implement and export these functions in the dynamic module object file. +// +// Each event hook is defined as a function prototype. The symbol must be prefixed with +// "envoy_dynamic_module_on_". + +/** + * envoy_dynamic_module_on_program_init is called by the main thread exactly when the module is + * loaded. The function returns the ABI version of the dynamic module. If null is returned, the + * module will be unloaded immediately. + * + * For Envoy, the return value will be used to check the compatibility of the dynamic module. + * + * For dynamic modules, this is useful when they need to perform some process-wide + * initialization or check if the module is compatible with the platform, such as CPU features. + * Note that initialization routines of a dynamic module can also be performed without this function + * through constructor functions in an object file. However, normal constructors cannot be used + * to check compatibility and gracefully fail the initialization because there is no way to + * report an error to Envoy. + * + * @return envoy_dynamic_module_type_abi_version is the ABI version of the dynamic module. Null + * means the error and the module will be unloaded immediately. + */ +envoy_dynamic_module_type_abi_version envoy_dynamic_module_on_program_init(); + +#ifdef __cplusplus +} +#endif diff --git a/source/extensions/dynamic_modules/abi_version.h b/source/extensions/dynamic_modules/abi_version.h new file mode 100644 index 000000000000..6262f9b54bdc --- /dev/null +++ b/source/extensions/dynamic_modules/abi_version.h @@ -0,0 +1,15 @@ +#pragma once +#ifdef __cplusplus +namespace Envoy { +namespace Extensions { +namespace DynamicModules { +#endif +// This is the ABI version calculated as a sha256 hash of the ABI header files. When the ABI +// changes, this value must change, and the correctness of this value is checked by the test. +const char* kAbiVersion = "749b1e6bf97309b7d171009700a80e651ac61e35f9770c24a63460d765895a51"; + +#ifdef __cplusplus +} // namespace DynamicModules +} // namespace Extensions +} // namespace Envoy +#endif diff --git a/source/extensions/dynamic_modules/dynamic_modules.cc b/source/extensions/dynamic_modules/dynamic_modules.cc index e28917fac16f..7579b9fe2a79 100644 --- a/source/extensions/dynamic_modules/dynamic_modules.cc +++ b/source/extensions/dynamic_modules/dynamic_modules.cc @@ -7,6 +7,9 @@ #include "envoy/common/exception.h" +#include "source/extensions/dynamic_modules/abi.h" +#include "source/extensions/dynamic_modules/abi_version.h" + namespace Envoy { namespace Extensions { namespace DynamicModules { @@ -27,7 +30,29 @@ absl::StatusOr newDynamicModule(const absl::string_view return absl::InvalidArgumentError( absl::StrCat("Failed to load dynamic module: ", object_file_path, " : ", dlerror())); } - return std::make_shared(handle); + + DynamicModuleSharedPtr dynamic_module = std::make_shared(handle); + + const auto init_function = + dynamic_module->getFunctionPointer( + "envoy_dynamic_module_on_program_init"); + + if (init_function == nullptr) { + return absl::InvalidArgumentError( + absl::StrCat("Failed to resolve envoy_dynamic_module_on_program_init: ", dlerror())); + } + + const char* abi_version = (*init_function)(); + if (abi_version == nullptr) { + return absl::InvalidArgumentError( + absl::StrCat("Failed to initialize dynamic module: ", object_file_path)); + } + // Checks the kAbiVersion and the version of the dynamic module. + if (absl::string_view(abi_version) != absl::string_view(kAbiVersion)) { + return absl::InvalidArgumentError( + absl::StrCat("ABI version mismatch: got ", abi_version, ", but expected ", kAbiVersion)); + } + return dynamic_module; } DynamicModule::~DynamicModule() { dlclose(handle_); } diff --git a/test/extensions/dynamic_modules/BUILD b/test/extensions/dynamic_modules/BUILD index 8c831226c66a..487553679f41 100644 --- a/test/extensions/dynamic_modules/BUILD +++ b/test/extensions/dynamic_modules/BUILD @@ -12,7 +12,10 @@ envoy_cc_test( name = "dynamic_modules_test", srcs = ["dynamic_modules_test.cc"], data = [ - "//test/extensions/dynamic_modules/test_data:no_op", + "//test/extensions/dynamic_modules/test_data/c:abi_version_mismatch", + "//test/extensions/dynamic_modules/test_data/c:no_op", + "//test/extensions/dynamic_modules/test_data/c:no_program_init", + "//test/extensions/dynamic_modules/test_data/c:program_init_fail", ], deps = [ "//source/extensions/dynamic_modules:dynamic_modules_lib", @@ -20,3 +23,18 @@ envoy_cc_test( "//test/test_common:utility_lib", ], ) + +envoy_cc_test( + name = "abi_version_test", + srcs = ["abi_version_test.cc"], + data = [ + "//source/extensions/dynamic_modules:abi.h", + ], + deps = [ + "//source/common/common:hex_lib", + "//source/common/crypto:utility_lib", + "//source/extensions/dynamic_modules:abi_version_lib", + "//test/test_common:environment_lib", + "//test/test_common:utility_lib", + ], +) diff --git a/test/extensions/dynamic_modules/abi_version_test.cc b/test/extensions/dynamic_modules/abi_version_test.cc new file mode 100644 index 000000000000..3f7b4eb74834 --- /dev/null +++ b/test/extensions/dynamic_modules/abi_version_test.cc @@ -0,0 +1,32 @@ +#include + +#include "envoy/common/exception.h" + +#include "source/common/common/hex.h" +#include "source/common/crypto/utility.h" +#include "source/extensions/dynamic_modules/abi_version.h" + +#include "test/test_common/environment.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace DynamicModules { + +// This test ensure that abi_version.h contains the correct sha256 hash of ABI header files. +TEST(DynamicModules, ABIVersionCheck) { + const auto abi_header_path = + TestEnvironment::substitute("{{ test_rundir }}/source/extensions/dynamic_modules/abi.h"); + // Read the header file and calculate the sha256 hash. + const std::string abi_header = TestEnvironment::readFileToStringForTest(abi_header_path); + const std::string sha256 = + Hex::encode(Envoy::Common::Crypto::UtilitySingleton::get().getSha256Digest( + Buffer::OwnedImpl(abi_header))); + EXPECT_EQ(sha256, kAbiVersion); +} + +} // namespace DynamicModules +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/dynamic_modules/dynamic_modules_test.cc b/test/extensions/dynamic_modules/dynamic_modules_test.cc index 6f5f21f5988f..1c02d4e9d4fb 100644 --- a/test/extensions/dynamic_modules/dynamic_modules_test.cc +++ b/test/extensions/dynamic_modules/dynamic_modules_test.cc @@ -14,22 +14,37 @@ namespace Extensions { namespace DynamicModules { // This loads a shared object file from the test_data directory. -std::string testSharedObjectPath(std::string name) { +std::string testSharedObjectPath(std::string name, std::string language) { return TestEnvironment::substitute( "{{ test_rundir }}/test/extensions/dynamic_modules/test_data/") + - "lib" + name + ".so"; + language + "/lib" + name + ".so"; } -TEST(DynamicModuleTest, InvalidPath) { +TEST(DynamicModuleTestGeneral, InvalidPath) { absl::StatusOr result = newDynamicModule("invalid_name", false); EXPECT_FALSE(result.ok()); EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); } -TEST(DynamicModuleTest, LoadNoOp) { +/** + * Class to test the identical behavior of the dynamic module in different languages. + */ +class DynamicModuleTestLanguages : public ::testing::TestWithParam { +public: + static std::string languageParamToTestName(const ::testing::TestParamInfo& info) { + return info.param; + }; +}; + +INSTANTIATE_TEST_SUITE_P(LanguageTests, DynamicModuleTestLanguages, + testing::Values("c"), // TODO: Other languages. + DynamicModuleTestLanguages::languageParamToTestName); + +TEST_P(DynamicModuleTestLanguages, DoNotClose) { + std::string language = GetParam(); using GetSomeVariableFuncType = int (*)(); absl::StatusOr module = - newDynamicModule(testSharedObjectPath("no_op"), false); + newDynamicModule(testSharedObjectPath("no_op", language), false); EXPECT_TRUE(module.ok()); const auto getSomeVariable = module->get()->getFunctionPointer("getSomeVariable"); @@ -39,8 +54,8 @@ TEST(DynamicModuleTest, LoadNoOp) { // Release the module, and reload it. module->reset(); - module = - newDynamicModule(testSharedObjectPath("no_op"), true); // This time, do not close the module. + module = newDynamicModule(testSharedObjectPath("no_op", language), + true); // This time, do not close the module. EXPECT_TRUE(module.ok()); // This module must be reloaded and the variable must be reset. @@ -53,7 +68,7 @@ TEST(DynamicModuleTest, LoadNoOp) { // Release the module, and reload it. module->reset(); - module = newDynamicModule(testSharedObjectPath("no_op"), false); + module = newDynamicModule(testSharedObjectPath("no_op", language), false); EXPECT_TRUE(module.ok()); // This module must be the already loaded one, and the variable must be kept. @@ -63,6 +78,43 @@ TEST(DynamicModuleTest, LoadNoOp) { EXPECT_EQ(getSomeVariable3(), 4); // Start from 4. } +TEST_P(DynamicModuleTestLanguages, LoadNoOp) { + std::string language = GetParam(); + absl::StatusOr module = + newDynamicModule(testSharedObjectPath("no_op", language), false); + EXPECT_TRUE(module.ok()); +} + +TEST_P(DynamicModuleTestLanguages, NoProgramInit) { + std::string language = GetParam(); + absl::StatusOr result = + newDynamicModule(testSharedObjectPath("no_program_init", language), false); + EXPECT_FALSE(result.ok()); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(result.status().message(), + testing::HasSubstr("undefined symbol: envoy_dynamic_module_on_program_init")); +} + +TEST_P(DynamicModuleTestLanguages, ProgramInitFail) { + std::string language = GetParam(); + absl::StatusOr result = + newDynamicModule(testSharedObjectPath("program_init_fail", language), false); + EXPECT_FALSE(result.ok()); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(result.status().message(), + testing::HasSubstr("Failed to initialize dynamic module:")); +} + +TEST_P(DynamicModuleTestLanguages, ABIVersionMismatch) { + std::string language = GetParam(); + absl::StatusOr result = + newDynamicModule(testSharedObjectPath("abi_version_mismatch", language), false); + EXPECT_FALSE(result.ok()); + EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT(result.status().message(), + testing::HasSubstr("ABI version mismatch: got invalid-version-hash, but expected")); +} + } // namespace DynamicModules } // namespace Extensions } // namespace Envoy diff --git a/test/extensions/dynamic_modules/test_data/BUILD b/test/extensions/dynamic_modules/test_data/BUILD deleted file mode 100644 index f199f10d3218..000000000000 --- a/test/extensions/dynamic_modules/test_data/BUILD +++ /dev/null @@ -1,7 +0,0 @@ -load("//test/extensions/dynamic_modules/test_data:test_data.bzl", "test_program") - -licenses(["notice"]) # Apache 2 - -package(default_visibility = ["//visibility:public"]) - -test_program(name = "no_op") diff --git a/test/extensions/dynamic_modules/test_data/c/BUILD b/test/extensions/dynamic_modules/test_data/c/BUILD new file mode 100644 index 000000000000..cab0535d5bc0 --- /dev/null +++ b/test/extensions/dynamic_modules/test_data/c/BUILD @@ -0,0 +1,13 @@ +load("//test/extensions/dynamic_modules/test_data/c:test_data.bzl", "test_program") + +licenses(["notice"]) # Apache 2 + +package(default_visibility = ["//test/extensions/dynamic_modules:__pkg__"]) + +test_program(name = "no_op") + +test_program(name = "no_program_init") + +test_program(name = "program_init_fail") + +test_program(name = "abi_version_mismatch") diff --git a/test/extensions/dynamic_modules/test_data/c/abi_version_mismatch.c b/test/extensions/dynamic_modules/test_data/c/abi_version_mismatch.c new file mode 100644 index 000000000000..c93056aafe9a --- /dev/null +++ b/test/extensions/dynamic_modules/test_data/c/abi_version_mismatch.c @@ -0,0 +1,5 @@ +#include "source/extensions/dynamic_modules/abi.h" + +envoy_dynamic_module_type_abi_version envoy_dynamic_module_on_program_init() { + return "invalid-version-hash"; +} diff --git a/test/extensions/dynamic_modules/test_data/c/no_op.c b/test/extensions/dynamic_modules/test_data/c/no_op.c new file mode 100644 index 000000000000..0993c38f09ee --- /dev/null +++ b/test/extensions/dynamic_modules/test_data/c/no_op.c @@ -0,0 +1,10 @@ +#include "source/extensions/dynamic_modules/abi.h" +#include "source/extensions/dynamic_modules/abi_version.h" + +int getSomeVariable() { + static int some_variable = 0; + some_variable++; + return some_variable; +} + +envoy_dynamic_module_type_abi_version envoy_dynamic_module_on_program_init() { return kAbiVersion; } diff --git a/test/extensions/dynamic_modules/test_data/c/no_program_init.c b/test/extensions/dynamic_modules/test_data/c/no_program_init.c new file mode 100644 index 000000000000..9fe07f82f9ed --- /dev/null +++ b/test/extensions/dynamic_modules/test_data/c/no_program_init.c @@ -0,0 +1 @@ +int foo() { return 0; } diff --git a/test/extensions/dynamic_modules/test_data/c/program_init_fail.c b/test/extensions/dynamic_modules/test_data/c/program_init_fail.c new file mode 100644 index 000000000000..62c903ac2dd3 --- /dev/null +++ b/test/extensions/dynamic_modules/test_data/c/program_init_fail.c @@ -0,0 +1,3 @@ +#include "source/extensions/dynamic_modules/abi.h" + +envoy_dynamic_module_type_abi_version envoy_dynamic_module_on_program_init() { return NULL; } diff --git a/test/extensions/dynamic_modules/test_data/test_data.bzl b/test/extensions/dynamic_modules/test_data/c/test_data.bzl similarity index 74% rename from test/extensions/dynamic_modules/test_data/test_data.bzl rename to test/extensions/dynamic_modules/test_data/c/test_data.bzl index fbe1af7f580e..78ad5991d55f 100644 --- a/test/extensions/dynamic_modules/test_data/test_data.bzl +++ b/test/extensions/dynamic_modules/test_data/c/test_data.bzl @@ -5,7 +5,7 @@ load("@rules_cc//cc:defs.bzl", "cc_library") def test_program(name): cc_library( name = name, - srcs = [name + ".c"], + srcs = [name + ".c", "//source/extensions/dynamic_modules:abi.h", "//source/extensions/dynamic_modules:abi_version.h"], linkopts = [ "-shared", "-fPIC", diff --git a/test/extensions/dynamic_modules/test_data/no_op.c b/test/extensions/dynamic_modules/test_data/no_op.c deleted file mode 100644 index 81815e007da7..000000000000 --- a/test/extensions/dynamic_modules/test_data/no_op.c +++ /dev/null @@ -1,5 +0,0 @@ -int getSomeVariable() { - static int some_variable = 0; - some_variable++; - return some_variable; -} From 77357cac6e6fd1dc4d91884a7cb93156f6e2feb7 Mon Sep 17 00:00:00 2001 From: botengyao Date: Mon, 26 Aug 2024 03:27:18 -0400 Subject: [PATCH 36/53] grpc_field_extraction: fix empty ListValue indication (#35842) ProtobufWkt::Value is introduced by #35162 Commit Message: Additional Description: Risk Level: low Testing: Docs Changes: Release Notes: Platform Specific Features: Signed-off-by: Boteng Yao --- .../filters/http/grpc_field_extraction/v3/config.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/grpc_field_extraction/v3/config.proto b/api/envoy/extensions/filters/http/grpc_field_extraction/v3/config.proto index aae62145731a..6eb225980a3f 100644 --- a/api/envoy/extensions/filters/http/grpc_field_extraction/v3/config.proto +++ b/api/envoy/extensions/filters/http/grpc_field_extraction/v3/config.proto @@ -66,7 +66,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // 1. the extracted field names/values will be wrapped in be ``field`` -> ``values``, which will be added in the dynamic ``metadata``. // -// 2. if the field value is empty, an empty ```` will be set. +// 2. if the field value is empty, an empty ``Value`` will be set. // // Performance // ----------- From e48719dbc3c0dd9ae929630e89a580195531732e Mon Sep 17 00:00:00 2001 From: Kevin Baichoo Date: Mon, 26 Aug 2024 05:53:40 -0400 Subject: [PATCH 37/53] Docs: add doc premature reset stat. (#35832) Commit Message: Docs: add doc premature reset stat. Additional Description: Was missed in https://github.com/envoyproxy/envoy/commit/230331f9bd4ec8d2ca25ae104436fcab3747985b Risk Level: low Testing: low Docs Changes: yes Release Notes: n/a Platform Specific Features: n/a Signed-off-by: Kevin Baichoo --- docs/root/configuration/http/http_conn_man/stats.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/root/configuration/http/http_conn_man/stats.rst b/docs/root/configuration/http/http_conn_man/stats.rst index fbd4e3ba4a69..48426b0b4eea 100644 --- a/docs/root/configuration/http/http_conn_man/stats.rst +++ b/docs/root/configuration/http/http_conn_man/stats.rst @@ -67,6 +67,7 @@ statistics: ``downstream_rq_timeout``, Counter, Total requests closed due to a timeout on the request path ``downstream_rq_overload_close``, Counter, Total requests closed due to Envoy overload ``downstream_rq_redirected_with_normalized_path``, Counter, Total requests redirected due to different original and normalized URL paths. This action is configured by setting the :ref:`path_with_escaped_slashes_action ` config option. + ``downstream_rq_too_many_premature_resets``, Counter, Total number of connections closed due to too many premature request resets on the connection. ``rs_too_large``, Counter, Total response errors due to buffering an overly large body .. _config_http_conn_man_stats_per_ua: From e36fd2e90bb311987c33843d36f061bc2cb3859b Mon Sep 17 00:00:00 2001 From: Shivam7-1 <55046031+Shivam7-1@users.noreply.github.com> Date: Mon, 26 Aug 2024 15:34:48 +0530 Subject: [PATCH 38/53] Update searchtools.js DOM text reinterpreted as HTML (#35824) Additional Description: By using `innerText`, it will avoid the risk of HTML injection, as these properties automatically escape any HTML special characters in the provided text. This helps prevent cross-site scripting (XSS) vulnerabilities by treating the input as plain text rather than interpreted HTML. Signed-off-by: Shivam7-1 <55046031+Shivam7-1@users.noreply.github.com> --- docs/root/_static/searchtools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/root/_static/searchtools.js b/docs/root/_static/searchtools.js index 02d0473059b3..b00137b34009 100644 --- a/docs/root/_static/searchtools.js +++ b/docs/root/_static/searchtools.js @@ -105,7 +105,7 @@ const _displayItem = (item, searchTerms) => { let linkEl = listItem.appendChild(document.createElement("a")); linkEl.href = linkUrl + anchor; linkEl.dataset.score = score; - linkEl.innerHTML = title; + linkEl.innerText = title; // const apiVersion = _renderApiVersionLabel(linkUrl); if (apiVersion !== "") { From 25f68aead5408796b0a681adfe4c7874bdcaf486 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:14:54 +0100 Subject: [PATCH 39/53] build(deps): bump github/codeql-action from 3.26.4 to 3.26.5 (#35843) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-daily.yml | 4 ++-- .github/workflows/codeql-push.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index fca0a8a43a65..456c09b3f747 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -34,7 +34,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 + uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # codeql-bundle-v3.26.5 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -68,4 +68,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 + uses: github/codeql-action/analyze@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # codeql-bundle-v3.26.5 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 94cb412ee164..d8092db1892c 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -65,7 +65,7 @@ jobs: - name: Initialize CodeQL if: ${{ env.BUILD_TARGETS != '' }} - uses: github/codeql-action/init@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 + uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # codeql-bundle-v3.26.5 with: languages: cpp @@ -109,4 +109,4 @@ jobs: - name: Perform CodeQL Analysis if: ${{ env.BUILD_TARGETS != '' }} - uses: github/codeql-action/analyze@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # codeql-bundle-v3.26.4 + uses: github/codeql-action/analyze@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # codeql-bundle-v3.26.5 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b92ce6d670e5..b9fd746935d6 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -40,6 +40,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f0f3afee809481da311ca3a6ff1ff51d81dbeb24 # v3.26.4 + uses: github/codeql-action/upload-sarif@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # v3.26.5 with: sarif_file: results.sarif From 5dd33ce39e2977cb85a9c72dbf742e10c8483257 Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Mon, 26 Aug 2024 12:50:08 +0200 Subject: [PATCH 40/53] datadog-tracing: remove example in source directory (#35761) Commit Message: Add example for Datadog tracing. Additional Description: This commit relocates the Datadog example form the /source directory. Additionally, it adds public documentation. Risk Level: Low. Testing: Manual testing. Docs Changes: Add public documentation. Release Notes: This change is not impacting user, no release notes update required. Doc PR: https://github.com/envoyproxy/examples/pull/97 Fixes #33846 Signed-off-by: Damien Mehala --- source/extensions/tracers/datadog/README.md | 65 +------------ .../extensions/tracers/datadog/demo/README.md | 3 - .../tracers/datadog/demo/docker-compose.yaml | 35 ------- source/extensions/tracers/datadog/demo/envoy | 4 - .../tracers/datadog/demo/envoy.yaml | 95 ------------------- .../tracers/datadog/demo/http.dockerfile | 14 --- .../extensions/tracers/datadog/demo/http.js | 33 ------- 7 files changed, 4 insertions(+), 245 deletions(-) delete mode 100644 source/extensions/tracers/datadog/demo/README.md delete mode 100644 source/extensions/tracers/datadog/demo/docker-compose.yaml delete mode 100755 source/extensions/tracers/datadog/demo/envoy delete mode 100644 source/extensions/tracers/datadog/demo/envoy.yaml delete mode 100644 source/extensions/tracers/datadog/demo/http.dockerfile delete mode 100644 source/extensions/tracers/datadog/demo/http.js diff --git a/source/extensions/tracers/datadog/README.md b/source/extensions/tracers/datadog/README.md index 69922a7bf8f5..424330f5fe06 100644 --- a/source/extensions/tracers/datadog/README.md +++ b/source/extensions/tracers/datadog/README.md @@ -47,7 +47,7 @@ Contains `class AgentHTTPClient`, which is an implementation of [🐶::HTTPClient][3] in terms of `Http::AsyncClient::Callbacks`. The HTTP client is passed to the configuration of -[🐶::DatadogAgent][10], a [🐶::Collector][11] +[🐶::DatadogAgent][9], a [🐶::Collector][10] implementation that uses the HTTP client to send traces to the Datadog Agent. #### `BUILD` @@ -69,7 +69,7 @@ Contains `class EventScheduler`, which is an implementation of [🐶::EventScheduler][4] in terms of `Event::Dispatcher`. The event scheduler is passed to the configuration of -[🐶::DatadogAgent][10], a [🐶::Collector][11] +[🐶::DatadogAgent][9], a [🐶::Collector][10] implementation that uses the event scheduler to periodically send batched traces to the Datadog Agent. @@ -112,62 +112,6 @@ Each instance of `Tracer` is local to a worker thread. `Tracer` is what is returned by `DatadogTracerFactory::createTracerDriverTyped`. -Demo ----- -[demo/](demo/) contains a [docker compose][9] setup and supporting -configuration that can be used to manually test Datadog tracing in a local -build of Envoy. - -The local build of Envoy runs on the host, while the Datadog Agent and an -upstream HTTP server are services within the [docker compose setup](demo/docker-compose.yaml). - -See [demo/envoy](demo/envoy) and -[demo/docker-compose.yaml](demo/docker-compose.yaml). - -### Example Usage -In a command shell: -```console -$ cd demo -$ DD_API_KEY=your_datadog_api_key_here docker compose up --build -[...] -demo-http-1 | http node.js web server is running -demo-dd-agent-1 | system-probe exited with code 0, disabling -``` - -In another command shell: -```console -$ cd demo -$ ./envoy -[...] -[2022-11-10 20:06:10.217][264507][info][main] [source/server/server.cc:907] starting main dispatch loop -``` - -In a third command shell: -```console -$ curl 'http://localhost:1337' -{ - "service": "http", - "headers": { - "host": "localhost:1337", - "user-agent": "curl/7.81.0", - "accept": "*/*", - "x-forwarded-for": "172.16.14.142", - "x-forwarded-proto": "http", - "x-envoy-internal": "true", - "x-request-id": "cfa52b85-8660-9532-b347-bd484da76166", - "x-envoy-expected-rq-timeout-ms": "15000", - "x-foobar-banana": "", - "x-datadog-tags": "_dd.p.dm=-0", - "x-datadog-trace-id": "6487770461011569198", - "x-datadog-parent-id": "6487770461011569198", - "x-datadog-sampling-priority": "1" - } -} -``` - -If all went well, then the resulting trace will be visible in Datadog's UI. The -service name is `envoy-demo`. See the [Envoy config](demo/envoy.yaml). - [1]: ../../../../test/extensions/tracers/datadog/ [2]: https://github.com/DataDog/dd-trace-cpp [3]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/http_client.h @@ -176,6 +120,5 @@ service name is `envoy-demo`. See the [Envoy config](demo/envoy.yaml). [6]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/span.h [7]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/clock.h [8]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/tracer.h -[9]: https://docs.docker.com/compose/ -[10]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/datadog_agent.h -[11]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/collector.h +[9]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/datadog_agent.h +[10]: https://github.com/DataDog/dd-trace-cpp/blob/main/src/datadog/collector.h diff --git a/source/extensions/tracers/datadog/demo/README.md b/source/extensions/tracers/datadog/demo/README.md deleted file mode 100644 index 0c5756263e13..000000000000 --- a/source/extensions/tracers/datadog/demo/README.md +++ /dev/null @@ -1,3 +0,0 @@ -See the "Demo" section of the [parent readme][1]. - -[1]: ../README.md diff --git a/source/extensions/tracers/datadog/demo/docker-compose.yaml b/source/extensions/tracers/datadog/demo/docker-compose.yaml deleted file mode 100644 index 55b288572a76..000000000000 --- a/source/extensions/tracers/datadog/demo/docker-compose.yaml +++ /dev/null @@ -1,35 +0,0 @@ -version: "3.2" - -services: - - # `agent` is the Datadog Agent to which traces are sent. - # `agent` needs an API key set in the environment as the - # `DD_API_KEY` environment variable. - dd-agent: - volumes: - - '/var/run/docker.sock:/var/run/docker.sock:ro' - - '/run/user:/run/user:ro' - - '/proc/:/host/proc/:ro' - - '/sys/fs/cgroup/:/host/sys/fs/cgroup:ro' - environment: - - DOCKER_HOST - - DD_API_KEY - - DD_APM_ENABLED=true - - DD_LOG_LEVEL=ERROR - ports: - - 8126:8126 - image: 'datadog/agent@sha256:1d9b8e28704b207626cdeca5386019f673d9f3a9baf817f5094b8e08b1f99fca' - - # `http` is an HTTP server that is reverse proxied by `nginx`. - http: - build: - context: . - dockerfile: ./http.dockerfile - environment: - - DD_ENV=prod - - DD_AGENT_HOST=dd-agent - - DD_SERVICE=envoy-demo-http - ports: - - 8080:8080 - depends_on: - - dd-agent diff --git a/source/extensions/tracers/datadog/demo/envoy b/source/extensions/tracers/datadog/demo/envoy deleted file mode 100755 index a84b13ed97e0..000000000000 --- a/source/extensions/tracers/datadog/demo/envoy +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -here=$(dirname "$0") -"$here"/../../../../../bazel-bin/source/exe/envoy-static --config-path "$here"/envoy.yaml "$@" diff --git a/source/extensions/tracers/datadog/demo/envoy.yaml b/source/extensions/tracers/datadog/demo/envoy.yaml deleted file mode 100644 index 839ba18aac44..000000000000 --- a/source/extensions/tracers/datadog/demo/envoy.yaml +++ /dev/null @@ -1,95 +0,0 @@ -static_resources: - listeners: - - address: - socket_address: - address: 0.0.0.0 - port_value: 1337 - traffic_direction: OUTBOUND - filter_chains: - - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - generate_request_id: true - tracing: - provider: - name: envoy.tracers.datadog - typed_config: - "@type": type.googleapis.com/envoy.config.trace.v3.DatadogConfig - collector_cluster: datadog_agent - service_name: envoy-demo - access_log: - - name: envoy.access_loggers.file - typed_config: - "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog - path: /dev/stdout - log_format: - text_format_source: - inline_string: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH):256% \ - %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% \ - %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \ - \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" \ - \"%RESP(X-AMZN-RequestId)%\" \"%REQ(X-DATADOG-TRACE-ID)%\" \"%REQ(X-DATADOG-PARENT-ID)%\"\n" - codec_type: auto - stat_prefix: ingress_http - route_config: - request_headers_to_add: - - header: - key: X-Foobar-Banana - value: " " - name: local_route - virtual_hosts: - - name: backend - domains: - - "*" - routes: - - match: - prefix: "/" - route: - cluster: service1 - http_filters: - - name: envoy.filters.http.health_check - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck - pass_through_mode: false - headers: - - exact_match: /healthcheck - name: :path - - name: envoy.filters.http.router - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - use_remote_address: true - clusters: - - name: service1 - connect_timeout: 0.250s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: service1 - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: localhost - port_value: 8080 - - name: datadog_agent - connect_timeout: 1s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: datadog_agent - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: localhost - port_value: 8126 - -admin: - access_log_path: "/dev/null" - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 diff --git a/source/extensions/tracers/datadog/demo/http.dockerfile b/source/extensions/tracers/datadog/demo/http.dockerfile deleted file mode 100644 index a1b1d3b56b00..000000000000 --- a/source/extensions/tracers/datadog/demo/http.dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM alpine:3.16@sha256:e4cdb7d47b06ba0a062ad2a97a7d154967c8f83934594d9f2bd3efa89292996b - -RUN mkdir /opt/app -WORKDIR /opt/app - -# Note: WORKDIR must already be set (as it is above) before installing npm. -# If WORKDIR is not set, then npm is installed at the container root, -# which then causes `npm install` to fail later. -RUN apk update && apk add nodejs npm -RUN npm install dd-trace - -COPY ./http.js /opt/app/http.js - -CMD ["node", "--require", "dd-trace/init", "http.js"] diff --git a/source/extensions/tracers/datadog/demo/http.js b/source/extensions/tracers/datadog/demo/http.js deleted file mode 100644 index 1858c89d8e8d..000000000000 --- a/source/extensions/tracers/datadog/demo/http.js +++ /dev/null @@ -1,33 +0,0 @@ -// This is an HTTP server that listens on port 8080 and responds to all -// requests with some text, including the request headers as JSON. - -const http = require('http'); -const process = require('process'); - -// In order for the span(s) associated with an HTTP request to be considered -// finished, the body of the response corresponding to the request must have -// ended. -function ignoreRequestBody(request) { - function ignore() {} - request.on('data', ignore); - request.on('end', ignore); -} - -function requestListener (request, response) { - ignoreRequestBody(request); - const responseBody = JSON.stringify({ - "service": "http", - "headers": request.headers - }, null, 2); - console.log(responseBody); - response.end(responseBody); -} - -console.log('http node.js web server is running'); -const server = http.createServer(requestListener); -server.listen(8080); - -process.on('SIGTERM', function () { - console.log('Received SIGTERM'); - server.close(function () { process.exit(0); }); -}); From bd5bec9abb537b3d462ed4e74bb5ea4bf1844655 Mon Sep 17 00:00:00 2001 From: Paul Sohn Date: Mon, 26 Aug 2024 09:52:53 -0400 Subject: [PATCH 41/53] Allow specified UDP cmsg to be saved to QuicReceivedPacket (#35382) Commit Message: Allow specified UDP cmsg to be saved to QuicReceivedPacket Additional Description: This can be accessed via QuicListenerFilter::onFirstPacketReceived. Risk Level: Low Testing: Integration test Docs Changes: N/A Release Notes: added --------- Signed-off-by: Paul Sohn --- .../config/core/v3/socket_cmsg_headers.proto | 28 +++++++++++++++++++ .../config/listener/v3/quic_config.proto | 10 ++++++- changelogs/current.yaml | 5 ++++ contrib/vcl/source/vcl_io_handle.cc | 6 ++-- contrib/vcl/source/vcl_io_handle.h | 4 ++- .../common_messages/common_messages.rst | 1 + envoy/network/BUILD | 1 + envoy/network/io_handle.h | 19 ++++++++++++- envoy/network/listener.h | 6 ++++ .../common/network/io_socket_handle_impl.cc | 22 +++++++++++++-- source/common/network/io_socket_handle_impl.h | 4 ++- .../network/io_uring_socket_handle_impl.cc | 5 +++- .../network/io_uring_socket_handle_impl.h | 5 +++- source/common/network/udp_listener_impl.cc | 9 ++++-- source/common/network/udp_listener_impl.h | 5 +++- source/common/network/utility.cc | 27 ++++++++++-------- source/common/network/utility.h | 6 ++-- .../network/win32_socket_handle_impl.cc | 18 +++++++----- .../common/network/win32_socket_handle_impl.h | 5 +++- source/common/quic/active_quic_listener.cc | 26 +++++++++++++---- source/common/quic/active_quic_listener.h | 4 +++ .../quic/envoy_quic_client_connection.cc | 2 +- .../quic/envoy_quic_client_connection.h | 7 ++++- source/common/quic/quic_io_handle_wrapper.h | 8 ++++-- .../filters/udp/udp_proxy/udp_proxy_filter.cc | 13 ++++++--- .../filters/udp/udp_proxy/udp_proxy_filter.h | 9 ++++-- .../io_socket/user_space/io_handle_impl.cc | 5 +++- .../io_socket/user_space/io_handle_impl.h | 5 +++- .../upstreams/http/udp/upstream_request.cc | 2 +- .../upstreams/http/udp/upstream_request.h | 7 ++++- source/server/active_udp_listener.h | 4 +++ .../io_uring_socket_handle_impl_test.cc | 4 +-- test/common/network/udp_fuzz.cc | 6 ++++ test/common/network/udp_listener_impl_test.cc | 3 ++ test/common/network/utility_test.cc | 3 ++ test/common/quic/active_quic_listener_test.cc | 3 ++ .../quic/envoy_quic_client_session_test.cc | 9 +++--- .../quic/quic_io_handle_wrapper_test.cc | 8 +++--- .../udp/udp_proxy/udp_proxy_filter_test.cc | 5 ++-- .../user_space/io_handle_impl_test.cc | 5 ++-- .../http/udp/upstream_request_test.cc | 3 +- .../filters/test_listener_filter.h | 7 ++++- .../filters/test_socket_interface.cc | 4 ++- .../filters/test_socket_interface.h | 3 +- .../integration/quic_http_integration_test.cc | 20 +++++++++---- test/mocks/network/io_handle.h | 5 ++-- test/mocks/network/mocks.h | 4 ++- test/test_common/network_utility.cc | 14 ++++++++-- 48 files changed, 298 insertions(+), 86 deletions(-) create mode 100644 api/envoy/config/core/v3/socket_cmsg_headers.proto diff --git a/api/envoy/config/core/v3/socket_cmsg_headers.proto b/api/envoy/config/core/v3/socket_cmsg_headers.proto new file mode 100644 index 000000000000..cc3e58e0996a --- /dev/null +++ b/api/envoy/config/core/v3/socket_cmsg_headers.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; + +package envoy.config.core.v3; + +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.config.core.v3"; +option java_outer_classname = "SocketCmsgHeadersProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/core/v3;corev3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Socket CMSG headers] + +// Configuration for socket cmsg headers. +// See `:ref:CMSG `_ for further information. +message SocketCmsgHeaders { + // cmsg level. Default is unset. + google.protobuf.UInt32Value level = 1; + + // cmsg type. Default is unset. + google.protobuf.UInt32Value type = 2; + + // Expected size of cmsg value. Default is zero. + uint32 expected_size = 3; +} diff --git a/api/envoy/config/listener/v3/quic_config.proto b/api/envoy/config/listener/v3/quic_config.proto index 3ddebe900ef3..6ba5bbc56b1e 100644 --- a/api/envoy/config/listener/v3/quic_config.proto +++ b/api/envoy/config/listener/v3/quic_config.proto @@ -5,6 +5,7 @@ package envoy.config.listener.v3; import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/extension.proto"; import "envoy/config/core/v3/protocol.proto"; +import "envoy/config/core/v3/socket_cmsg_headers.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; @@ -24,7 +25,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: QUIC listener config] // Configuration specific to the UDP QUIC listener. -// [#next-free-field: 12] +// [#next-free-field: 13] message QuicProtocolOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.listener.QuicProtocolOptions"; @@ -86,4 +87,11 @@ message QuicProtocolOptions { // If not specified, no debug visitor will be attached to connections. // [#extension-category: envoy.quic.connection_debug_visitor] core.v3.TypedExtensionConfig connection_debug_visitor_config = 11; + + // Configure a type of UDP cmsg to pass to listener filters via QuicReceivedPacket. + // Both level and type must be specified for cmsg to be saved. + // Cmsg may be truncated or omitted if expected size is not set. + // If not specified, no cmsg will be saved to QuicReceivedPacket. + repeated core.v3.SocketCmsgHeaders save_cmsg_config = 12 + [(validate.rules).repeated = {max_items: 1}]; } diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 33d669ab5915..260262fcccb6 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -224,6 +224,11 @@ new_features: change: | Added new access log command operators ``%START_TIME_LOCAL%`` and ``%EMIT_TIME_LOCAL%``, similar to ``%START_TIME%`` and ``%EMIT_TIME%``, but use local time zone. +- area: quic + change: | + Added QUIC protocol option :ref:`save_cmsg_config + ` to optionally specify a CMSG header type to be + propagated from the first packet on the connection to QuicListenerFilter. - area: dns change: | Prefer using IPv6 address when addresses from both families are available. diff --git a/contrib/vcl/source/vcl_io_handle.cc b/contrib/vcl/source/vcl_io_handle.cc index 0855ca6cd82f..f345857f8365 100644 --- a/contrib/vcl/source/vcl_io_handle.cc +++ b/contrib/vcl/source/vcl_io_handle.cc @@ -327,7 +327,8 @@ Api::IoCallUint64Result VclIoHandle::sendmsg(const Buffer::RawSlice* slices, uin } Api::IoCallUint64Result VclIoHandle::recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) { + uint32_t self_port, const UdpSaveCmsgConfig&, + RecvMsgOutput& output) { if (!VCL_SH_VALID(sh_)) { return vclCallResultToIoCallResult(VPPCOM_EBADFD); } @@ -373,7 +374,8 @@ Api::IoCallUint64Result VclIoHandle::recvmsg(Buffer::RawSlice* slices, const uin return vclCallResultToIoCallResult(result); } -Api::IoCallUint64Result VclIoHandle::recvmmsg(RawSliceArrays&, uint32_t, RecvMsgOutput&) { +Api::IoCallUint64Result VclIoHandle::recvmmsg(RawSliceArrays&, uint32_t, const UdpSaveCmsgConfig&, + RecvMsgOutput&) { PANIC("not implemented"); } diff --git a/contrib/vcl/source/vcl_io_handle.h b/contrib/vcl/source/vcl_io_handle.h index 631ca20e3342..819fb5600b54 100644 --- a/contrib/vcl/source/vcl_io_handle.h +++ b/contrib/vcl/source/vcl_io_handle.h @@ -42,8 +42,10 @@ class VclIoHandle : public Envoy::Network::IoHandle, const Envoy::Network::Address::Ip* self_ip, const Envoy::Network::Address::Instance& peer_address) override; Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) override; + uint32_t self_port, const UdpSaveCmsgConfig& save_cmsg_config, + RecvMsgOutput& output) override; Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output) override; absl::optional lastRoundTripTime() override; absl::optional congestionWindowInBytes() const override; diff --git a/docs/root/api-v3/common_messages/common_messages.rst b/docs/root/api-v3/common_messages/common_messages.rst index 0b5c9032b933..7d40c0218f57 100644 --- a/docs/root/api-v3/common_messages/common_messages.rst +++ b/docs/root/api-v3/common_messages/common_messages.rst @@ -41,3 +41,4 @@ Common messages ../config/core/v3/substitution_format_string.proto ../config/core/v3/udp_socket_config.proto ../extensions/filters/common/set_filter_state/v3/value.proto + ../config/core/v3/socket_cmsg_headers.proto diff --git a/envoy/network/BUILD b/envoy/network/BUILD index 230f7c065d58..cef61c8cb93b 100644 --- a/envoy/network/BUILD +++ b/envoy/network/BUILD @@ -140,6 +140,7 @@ envoy_cc_library( ":address_interface", "//envoy/api:io_error_interface", "//envoy/api:os_sys_calls_interface", + "//envoy/buffer:buffer_interface", "//envoy/event:file_event_interface", "//source/common/common:assert_lib", ], diff --git a/envoy/network/io_handle.h b/envoy/network/io_handle.h index 7c22a792ab93..ce1dcd802b4f 100644 --- a/envoy/network/io_handle.h +++ b/envoy/network/io_handle.h @@ -5,6 +5,7 @@ #include "envoy/api/io_error.h" #include "envoy/api/os_sys_calls_common.h" +#include "envoy/buffer/buffer.h" #include "envoy/common/platform.h" #include "envoy/common/pure.h" #include "envoy/event/file_event.h" @@ -134,6 +135,8 @@ class IoHandle { bool truncated_and_dropped_{false}; // The contents of the TOS byte in the IP header. uint8_t tos_{0}; + // UDP control message specified by save_cmsg_config in QUIC config. + Buffer::RawSlice saved_cmsg_; }; /** @@ -160,6 +163,15 @@ class IoHandle { absl::FixedArray msg_; }; + // Struct representation of QuicProtocolOptions::SaveCmsgConfig config proto. + struct UdpSaveCmsgConfig { + absl::optional level; + absl::optional type; + uint32_t expected_size = 0; + + bool hasConfig() const { return (level.has_value() && type.has_value()); } + }; + /** * Receive a message into given slices, output overflow, source/destination * addresses via passed-in parameters upon success. @@ -167,12 +179,15 @@ class IoHandle { * @param num_slice indicates number of slices |slices| contains. * @param self_port the port this handle is assigned to. This is used to populate * local_address because local port can't be retrieved from control message. + * @param save_cmsg_config config that determines whether cmsg is saved to output. * @param output modified upon each call to return fields requested in it. * @return a Api::IoCallUint64Result with err_ = an Api::IoError instance or * err_ = nullptr and rc_ = the bytes received for success. */ virtual Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) PURE; + uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, + RecvMsgOutput& output) PURE; /** * If the platform supports, receive multiple messages into given slices, output overflow, @@ -180,9 +195,11 @@ class IoHandle { * @param slices are the receive buffers for the messages. Each message * received are stored in an individual entry of |slices|. * @param self_port is the same as the one in recvmsg(). + * @param save_cmsg_config config that determines whether cmsg is saved to output. * @param output is modified upon each call and each message received. */ virtual Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output) PURE; /** diff --git a/envoy/network/listener.h b/envoy/network/listener.h index 6dba640bb5b0..fb56abe08114 100644 --- a/envoy/network/listener.h +++ b/envoy/network/listener.h @@ -358,6 +358,7 @@ struct UdpRecvData { Buffer::InstancePtr buffer_; MonotonicTime receive_time_; uint8_t tos_ = 0; + Buffer::RawSlice saved_cmsg_; }; /** @@ -446,6 +447,11 @@ class UdpListenerCallbacks { * An estimated number of UDP packets this callback expects to process in current read event. */ virtual size_t numPacketsExpectedPerEventLoop() const PURE; + + /** + * Information about which cmsg to save to QuicReceivedPacket, if any. + */ + virtual const IoHandle::UdpSaveCmsgConfig& udpSaveCmsgConfig() const PURE; }; using UdpListenerCallbacksOptRef = absl::optional>; diff --git a/source/common/network/io_socket_handle_impl.cc b/source/common/network/io_socket_handle_impl.cc index edfa56f6cc3d..956054ad4532 100644 --- a/source/common/network/io_socket_handle_impl.cc +++ b/source/common/network/io_socket_handle_impl.cc @@ -282,11 +282,13 @@ absl::optional maybeGetPacketsDroppedFromHeader([[maybe_unused]] const Api::IoCallUint64Result IoSocketHandleImpl::recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output) { ASSERT(!output.msg_.empty()); - absl::FixedArray cbuf(cmsg_space_); - memset(cbuf.begin(), 0, cmsg_space_); + size_t cmsg_space = cmsg_space_ + save_cmsg_config.expected_size; + absl::FixedArray cbuf(cmsg_space); + memset(cbuf.begin(), 0, cmsg_space); absl::FixedArray iov(num_slice); uint64_t num_slices_for_read = 0; @@ -334,6 +336,12 @@ Api::IoCallUint64Result IoSocketHandleImpl::recvmsg(Buffer::RawSlice* slices, // Get overflow, local address and gso_size from control message. for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&hdr, cmsg)) { + if (save_cmsg_config.hasConfig() && + cmsg->cmsg_type == static_cast(save_cmsg_config.type.value()) && + cmsg->cmsg_level == static_cast(save_cmsg_config.level.value())) { + Buffer::RawSlice cmsg_slice{CMSG_DATA(cmsg), cmsg->cmsg_len}; + output.msg_[0].saved_cmsg_ = cmsg_slice; + } if (output.msg_[0].local_address_ == nullptr) { Address::InstanceConstSharedPtr addr = maybeGetDstAddressFromHeader(*cmsg, self_port); if (addr != nullptr) { @@ -370,6 +378,7 @@ Api::IoCallUint64Result IoSocketHandleImpl::recvmsg(Buffer::RawSlice* slices, } Api::IoCallUint64Result IoSocketHandleImpl::recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output) { ASSERT(output.msg_.size() == slices.size()); if (slices.empty()) { @@ -380,8 +389,9 @@ Api::IoCallUint64Result IoSocketHandleImpl::recvmmsg(RawSliceArrays& slices, uin absl::FixedArray> iovs( num_packets_per_mmsg_call, absl::FixedArray(slices[0].size())); absl::FixedArray raw_addresses(num_packets_per_mmsg_call); + size_t cmsg_space = cmsg_space_ + save_cmsg_config.expected_size; absl::FixedArray> cbufs(num_packets_per_mmsg_call, - absl::FixedArray(cmsg_space_)); + absl::FixedArray(cmsg_space)); for (uint32_t i = 0; i < num_packets_per_mmsg_call; ++i) { memset(&raw_addresses[i], 0, sizeof(sockaddr_storage)); @@ -438,6 +448,12 @@ Api::IoCallUint64Result IoSocketHandleImpl::recvmmsg(RawSliceArrays& slices, uin if (hdr.msg_controllen > 0) { struct cmsghdr* cmsg; for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&hdr, cmsg)) { + if (save_cmsg_config.hasConfig() && + cmsg->cmsg_type == static_cast(save_cmsg_config.type.value()) && + cmsg->cmsg_level == static_cast(save_cmsg_config.level.value())) { + Buffer::RawSlice cmsg_slice{CMSG_DATA(cmsg), cmsg->cmsg_len}; + output.msg_[0].saved_cmsg_ = cmsg_slice; + } Address::InstanceConstSharedPtr addr = maybeGetDstAddressFromHeader(*cmsg, self_port); if (receive_ecn_ && #ifdef __APPLE__ diff --git a/source/common/network/io_socket_handle_impl.h b/source/common/network/io_socket_handle_impl.h index e919cc0c6bac..7374627a886b 100644 --- a/source/common/network/io_socket_handle_impl.h +++ b/source/common/network/io_socket_handle_impl.h @@ -58,9 +58,11 @@ class IoSocketHandleImpl : public IoSocketHandleBaseImpl { const Address::Instance& peer_address) override; Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) override; + uint32_t self_port, const UdpSaveCmsgConfig& save_cmsg_config, + RecvMsgOutput& output) override; Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output) override; Api::IoCallUint64Result recv(void* buffer, size_t length, int flags) override; diff --git a/source/common/network/io_uring_socket_handle_impl.cc b/source/common/network/io_uring_socket_handle_impl.cc index 2bbcf1d85b11..7d10acd098df 100644 --- a/source/common/network/io_uring_socket_handle_impl.cc +++ b/source/common/network/io_uring_socket_handle_impl.cc @@ -135,12 +135,15 @@ Api::IoCallUint64Result IoUringSocketHandleImpl::sendmsg(const Buffer::RawSlice* } Api::IoCallUint64Result IoUringSocketHandleImpl::recvmsg(Buffer::RawSlice*, const uint64_t, - uint32_t, RecvMsgOutput&) { + uint32_t, + const IoHandle::UdpSaveCmsgConfig&, + RecvMsgOutput&) { ENVOY_LOG(trace, "recvmsg, fd = {}, type = {}", fd_, ioUringSocketTypeStr()); return Network::IoSocketError::ioResultSocketInvalidAddress(); } Api::IoCallUint64Result IoUringSocketHandleImpl::recvmmsg(RawSliceArrays&, uint32_t, + const IoHandle::UdpSaveCmsgConfig&, RecvMsgOutput&) { ENVOY_LOG(trace, "recvmmsg, fd = {}, type = {}", fd_, ioUringSocketTypeStr()); return Network::IoSocketError::ioResultSocketInvalidAddress(); diff --git a/source/common/network/io_uring_socket_handle_impl.h b/source/common/network/io_uring_socket_handle_impl.h index 85e8469b11d1..91c083a529d2 100644 --- a/source/common/network/io_uring_socket_handle_impl.h +++ b/source/common/network/io_uring_socket_handle_impl.h @@ -46,8 +46,11 @@ class IoUringSocketHandleImpl : public IoSocketHandleBaseImpl { const Address::Ip* self_ip, const Address::Instance& peer_address) override; Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) override; + uint32_t self_port, + const IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, + RecvMsgOutput& output) override; Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, RecvMsgOutput& output) override; Api::IoCallUint64Result recv(void* buffer, size_t length, int flags) override; Api::SysCallIntResult bind(Address::InstanceConstSharedPtr address) override; diff --git a/source/common/network/udp_listener_impl.cc b/source/common/network/udp_listener_impl.cc index bccba8aab8a2..08b000831945 100644 --- a/source/common/network/udp_listener_impl.cc +++ b/source/common/network/udp_listener_impl.cc @@ -124,12 +124,15 @@ void UdpListenerImpl::handleReadCallback() { void UdpListenerImpl::processPacket(Address::InstanceConstSharedPtr local_address, Address::InstanceConstSharedPtr peer_address, Buffer::InstancePtr buffer, MonotonicTime receive_time, - uint8_t tos) { + uint8_t tos, Buffer::RawSlice saved_cmsg) { // UDP listeners are always configured with the socket option that allows pulling the local // address. This should never be null. ASSERT(local_address != nullptr); - UdpRecvData recvData{ - {std::move(local_address), std::move(peer_address)}, std::move(buffer), receive_time, tos}; + UdpRecvData recvData{{std::move(local_address), std::move(peer_address)}, + std::move(buffer), + receive_time, + tos, + saved_cmsg}; cb_.onData(std::move(recvData)); } diff --git a/source/common/network/udp_listener_impl.h b/source/common/network/udp_listener_impl.h index 55d26d5470ce..9de7debcdb1a 100644 --- a/source/common/network/udp_listener_impl.h +++ b/source/common/network/udp_listener_impl.h @@ -46,12 +46,15 @@ class UdpListenerImpl : public BaseListenerImpl, // Network::UdpPacketProcessor void processPacket(Address::InstanceConstSharedPtr local_address, Address::InstanceConstSharedPtr peer_address, Buffer::InstancePtr buffer, - MonotonicTime receive_time, uint8_t tos) override; + MonotonicTime receive_time, uint8_t tos, Buffer::RawSlice saved_cmsg) override; uint64_t maxDatagramSize() const override { return config_.max_rx_datagram_size_; } void onDatagramsDropped(uint32_t dropped) override { cb_.onDatagramsDropped(dropped); } size_t numPacketsExpectedPerEventLoop() const override { return cb_.numPacketsExpectedPerEventLoop(); } + const IoHandle::UdpSaveCmsgConfig& saveCmsgConfig() const override { + return cb_.udpSaveCmsgConfig(); + } protected: void handleWriteCallback(); diff --git a/source/common/network/utility.cc b/source/common/network/utility.cc index eeea3f4982e6..d1b2e3734d79 100644 --- a/source/common/network/utility.cc +++ b/source/common/network/utility.cc @@ -92,11 +92,13 @@ namespace { Api::IoCallUint64Result receiveMessage(uint64_t max_rx_datagram_size, Buffer::InstancePtr& buffer, IoHandle::RecvMsgOutput& output, IoHandle& handle, - const Address::Instance& local_address) { + const Address::Instance& local_address, + const IoHandle::UdpSaveCmsgConfig& save_cmsg_config) { auto reservation = buffer->reserveSingleSlice(max_rx_datagram_size); Buffer::RawSlice slice = reservation.slice(); - Api::IoCallUint64Result result = handle.recvmsg(&slice, 1, local_address.ip()->port(), output); + Api::IoCallUint64Result result = + handle.recvmsg(&slice, 1, local_address.ip()->port(), save_cmsg_config, output); if (result.ok()) { reservation.commit(std::min(max_rx_datagram_size, result.return_value_)); @@ -535,7 +537,7 @@ void passPayloadToProcessor(uint64_t bytes_read, Buffer::InstancePtr buffer, Address::InstanceConstSharedPtr peer_addess, Address::InstanceConstSharedPtr local_address, UdpPacketProcessor& udp_packet_processor, MonotonicTime receive_time, - uint8_t tos) { + uint8_t tos, Buffer::RawSlice saved_cmsg) { ENVOY_BUG(peer_addess != nullptr, fmt::format("Unable to get remote address on the socket bound to local address: {}.", (local_address == nullptr ? "unknown" : local_address->asString()))); @@ -548,7 +550,7 @@ void passPayloadToProcessor(uint64_t bytes_read, Buffer::InstancePtr buffer, (local_address == nullptr ? "unknown" : local_address->asString()), bytes_read)); udp_packet_processor.processPacket(std::move(local_address), std::move(peer_addess), - std::move(buffer), receive_time, tos); + std::move(buffer), receive_time, tos, saved_cmsg); } Api::IoCallUint64Result readFromSocketRecvGro(IoHandle& handle, @@ -572,7 +574,8 @@ Api::IoCallUint64Result readFromSocketRecvGro(IoHandle& handle, ENVOY_LOG_MISC(trace, "starting gro recvmsg with max={}", max_rx_datagram_size_with_gro); Api::IoCallUint64Result result = - receiveMessage(max_rx_datagram_size_with_gro, buffer, output, handle, local_address); + receiveMessage(max_rx_datagram_size_with_gro, buffer, output, handle, local_address, + udp_packet_processor.saveCmsgConfig()); if (!result.ok() || output.msg_[0].truncated_and_dropped_) { return result; @@ -589,7 +592,7 @@ Api::IoCallUint64Result readFromSocketRecvGro(IoHandle& handle, passPayloadToProcessor(result.return_value_, std::move(buffer), std::move(output.msg_[0].peer_address_), std::move(output.msg_[0].local_address_), udp_packet_processor, - receive_time, output.msg_[0].tos_); + receive_time, output.msg_[0].tos_, output.msg_[0].saved_cmsg_); return result; } @@ -605,7 +608,7 @@ Api::IoCallUint64Result readFromSocketRecvGro(IoHandle& handle, } passPayloadToProcessor(bytes_to_copy, std::move(sub_buffer), output.msg_[0].peer_address_, output.msg_[0].local_address_, udp_packet_processor, receive_time, - output.msg_[0].tos_); + output.msg_[0].tos_, output.msg_[0].saved_cmsg_); } return result; @@ -645,7 +648,8 @@ readFromSocketRecvMmsg(IoHandle& handle, const Address::Instance& local_address, IoHandle::RecvMsgOutput output(NUM_DATAGRAMS_PER_RECEIVE, packets_dropped); ENVOY_LOG_MISC(trace, "starting recvmmsg with packets={} max={}", NUM_DATAGRAMS_PER_RECEIVE, max_rx_datagram_size); - Api::IoCallUint64Result result = handle.recvmmsg(slices, local_address.ip()->port(), output); + Api::IoCallUint64Result result = handle.recvmmsg(slices, local_address.ip()->port(), + udp_packet_processor.saveCmsgConfig(), output); if (!result.ok()) { return result; } @@ -670,7 +674,7 @@ readFromSocketRecvMmsg(IoHandle& handle, const Address::Instance& local_address, } passPayloadToProcessor(msg_len, std::move(buffers[i].buffer_), output.msg_[i].peer_address_, output.msg_[i].local_address_, udp_packet_processor, receive_time, - output.msg_[i].tos_); + output.msg_[i].tos_, output.msg_[i].saved_cmsg_); } return result; } @@ -688,7 +692,8 @@ Api::IoCallUint64Result readFromSocketRecvMsg(IoHandle& handle, ENVOY_LOG_MISC(trace, "starting recvmsg with max={}", udp_packet_processor.maxDatagramSize()); Api::IoCallUint64Result result = - receiveMessage(udp_packet_processor.maxDatagramSize(), buffer, output, handle, local_address); + receiveMessage(udp_packet_processor.maxDatagramSize(), buffer, output, handle, local_address, + udp_packet_processor.saveCmsgConfig()); if (!result.ok() || output.msg_[0].truncated_and_dropped_) { return result; @@ -702,7 +707,7 @@ Api::IoCallUint64Result readFromSocketRecvMsg(IoHandle& handle, passPayloadToProcessor(result.return_value_, std::move(buffer), std::move(output.msg_[0].peer_address_), std::move(output.msg_[0].local_address_), udp_packet_processor, - receive_time, output.msg_[0].tos_); + receive_time, output.msg_[0].tos_, output.msg_[0].saved_cmsg_); return result; } diff --git a/source/common/network/utility.h b/source/common/network/utility.h index 007e190dfb83..7a6e623f61fa 100644 --- a/source/common/network/utility.h +++ b/source/common/network/utility.h @@ -34,8 +34,8 @@ class UdpPacketProcessor { */ virtual void processPacket(Address::InstanceConstSharedPtr local_address, Address::InstanceConstSharedPtr peer_address, - Buffer::InstancePtr buffer, MonotonicTime receive_time, - uint8_t tos) PURE; + Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos, + Buffer::RawSlice saved_cmsg) PURE; /** * Called whenever datagrams are dropped due to overflow or truncation. @@ -53,6 +53,8 @@ class UdpPacketProcessor { * An estimated number of packets to read in each read event. */ virtual size_t numPacketsExpectedPerEventLoop() const PURE; + + virtual const IoHandle::UdpSaveCmsgConfig& saveCmsgConfig() const PURE; }; static const uint64_t DEFAULT_UDP_MAX_DATAGRAM_SIZE = 1500; diff --git a/source/common/network/win32_socket_handle_impl.cc b/source/common/network/win32_socket_handle_impl.cc index 413ce9ddd361..852410a9bacf 100644 --- a/source/common/network/win32_socket_handle_impl.cc +++ b/source/common/network/win32_socket_handle_impl.cc @@ -62,18 +62,22 @@ Api::IoCallUint64Result Win32SocketHandleImpl::sendmsg(const Buffer::RawSlice* s return result; } -Api::IoCallUint64Result Win32SocketHandleImpl::recvmsg(Buffer::RawSlice* slices, - const uint64_t num_slice, uint32_t self_port, - RecvMsgOutput& output) { +Api::IoCallUint64Result Win32SocketHandleImpl::recvmsg( + Buffer::RawSlice* slices, const uint64_t num_slice, uint32_t self_port, + const IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, RecvMsgOutput& output) { Api::IoCallUint64Result result = - IoSocketHandleImpl::recvmsg(slices, num_slice, self_port, output); + IoSocketHandleImpl::recvmsg(slices, num_slice, self_port, udp_save_cmsg_config, output); reEnableEventBasedOnIOResult(result, Event::FileReadyType::Read); return result; } -Api::IoCallUint64Result Win32SocketHandleImpl::recvmmsg(RawSliceArrays& slices, uint32_t self_port, - RecvMsgOutput& output) { - Api::IoCallUint64Result result = IoSocketHandleImpl::recvmmsg(slices, self_port, output); +Api::IoCallUint64Result +Win32SocketHandleImpl::recvmmsg(RawSliceArrays& slices, uint32_t self_port, + + const IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, + RecvMsgOutput& output) { + Api::IoCallUint64Result result = + IoSocketHandleImpl::recvmmsg(slices, self_port, udp_save_cmsg_config, output); reEnableEventBasedOnIOResult(result, Event::FileReadyType::Read); return result; } diff --git a/source/common/network/win32_socket_handle_impl.h b/source/common/network/win32_socket_handle_impl.h index f8835e5aed54..d3c8c93560f5 100644 --- a/source/common/network/win32_socket_handle_impl.h +++ b/source/common/network/win32_socket_handle_impl.h @@ -37,9 +37,12 @@ class Win32SocketHandleImpl : public IoSocketHandleImpl { const Address::Instance& peer_address) override; Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) override; + uint32_t self_port, + const IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, + RecvMsgOutput& output) override; Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, RecvMsgOutput& output) override; Api::IoCallUint64Result recv(void* buffer, size_t length, int flags) override; diff --git a/source/common/quic/active_quic_listener.cc b/source/common/quic/active_quic_listener.cc index 735472bbddf6..002b8f586605 100644 --- a/source/common/quic/active_quic_listener.cc +++ b/source/common/quic/active_quic_listener.cc @@ -112,6 +112,22 @@ ActiveQuicListener::ActiveQuicListener( } else { quic_dispatcher_->InitializeWithWriter(new EnvoyQuicPacketWriter(std::move(udp_packet_writer))); } + + if (listener_config.udpListenerConfig()) { + const auto& save_cmsg_configs = + listener_config.udpListenerConfig()->config().quic_options().save_cmsg_config(); + if (save_cmsg_configs.size() > 0) { + // QUIC only supports a single cmsg config. + const envoy::config::core::v3::SocketCmsgHeaders save_cmsg_config = save_cmsg_configs.at(0); + if (save_cmsg_config.has_level()) { + udp_save_cmsg_config_.level = save_cmsg_config.level().value(); + } + if (save_cmsg_config.has_type()) { + udp_save_cmsg_config_.type = save_cmsg_config.type().value(); + } + udp_save_cmsg_config_.expected_size = save_cmsg_config.expected_size(); + } + } } ActiveQuicListener::~ActiveQuicListener() { onListenerShutdown(); } @@ -139,11 +155,11 @@ void ActiveQuicListener::onDataWorker(Network::UdpRecvData&& data) { Buffer::RawSlice slice = data.buffer_->frontSlice(); ASSERT(data.buffer_->length() == slice.len_); // TODO(danzh): pass in TTL and UDP header. - quic::QuicReceivedPacket packet(reinterpret_cast(slice.mem_), slice.len_, timestamp, - /*owns_buffer=*/false, /*ttl=*/0, /*ttl_valid=*/false, - /*packet_headers=*/nullptr, /*headers_length=*/0, - /*owns_header_buffer*/ false, - getQuicEcnCodepointFromTosByte(data.tos_)); + quic::QuicReceivedPacket packet( + reinterpret_cast(slice.mem_), slice.len_, timestamp, + /*owns_buffer=*/false, /*ttl=*/0, /*ttl_valid=*/false, + reinterpret_cast(data.saved_cmsg_.mem_), data.saved_cmsg_.len_, + /*owns_header_buffer*/ false, getQuicEcnCodepointFromTosByte(data.tos_)); if (!quic_dispatcher_->processPacket(self_address, peer_address, packet)) { if (non_dispatched_udp_packet_handler_.has_value()) { non_dispatched_udp_packet_handler_->handle(worker_index_, std::move(data)); diff --git a/source/common/quic/active_quic_listener.h b/source/common/quic/active_quic_listener.h index b17538966578..e0f62c0298ce 100644 --- a/source/common/quic/active_quic_listener.h +++ b/source/common/quic/active_quic_listener.h @@ -60,6 +60,9 @@ class ActiveQuicListener : public Envoy::Server::ActiveUdpListenerBase, void onDataWorker(Network::UdpRecvData&& data) override; uint32_t destination(const Network::UdpRecvData& data) const override; size_t numPacketsExpectedPerEventLoop() const override; + const Network::IoHandle::UdpSaveCmsgConfig& udpSaveCmsgConfig() const override { + return udp_save_cmsg_config_; + } // ActiveListenerImplBase void pauseListening() override; @@ -97,6 +100,7 @@ class ActiveQuicListener : public Envoy::Server::ActiveUdpListenerBase, bool reject_all_{false}; // During hot restart, an optional handler for packets that weren't for existing connections. OptRef non_dispatched_udp_packet_handler_; + Network::IoHandle::UdpSaveCmsgConfig udp_save_cmsg_config_; }; using ActiveQuicListenerPtr = std::unique_ptr; diff --git a/source/common/quic/envoy_quic_client_connection.cc b/source/common/quic/envoy_quic_client_connection.cc index 411cfcece015..7b234bdeedbd 100644 --- a/source/common/quic/envoy_quic_client_connection.cc +++ b/source/common/quic/envoy_quic_client_connection.cc @@ -67,7 +67,7 @@ EnvoyQuicClientConnection::EnvoyQuicClientConnection( void EnvoyQuicClientConnection::processPacket( Network::Address::InstanceConstSharedPtr local_address, Network::Address::InstanceConstSharedPtr peer_address, Buffer::InstancePtr buffer, - MonotonicTime receive_time, uint8_t tos) { + MonotonicTime receive_time, uint8_t tos, Buffer::RawSlice /*saved_cmsg*/) { quic::QuicTime timestamp = quic::QuicTime::Zero() + quic::QuicTime::Delta::FromMicroseconds( diff --git a/source/common/quic/envoy_quic_client_connection.h b/source/common/quic/envoy_quic_client_connection.h index 8530386f6483..77a21e6cabdb 100644 --- a/source/common/quic/envoy_quic_client_connection.h +++ b/source/common/quic/envoy_quic_client_connection.h @@ -74,7 +74,8 @@ class EnvoyQuicClientConnection : public quic::QuicConnection, // Network::UdpPacketProcessor void processPacket(Network::Address::InstanceConstSharedPtr local_address, Network::Address::InstanceConstSharedPtr peer_address, - Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos) override; + Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos, + Buffer::RawSlice saved_cmsg) override; uint64_t maxDatagramSize() const override; void onDatagramsDropped(uint32_t) override { // TODO(mattklein123): Emit a stat for this. @@ -87,6 +88,10 @@ class EnvoyQuicClientConnection : public quic::QuicConnection, } return DEFAULT_PACKETS_TO_READ_PER_CONNECTION; } + const Network::IoHandle::UdpSaveCmsgConfig& saveCmsgConfig() const override { + static const Network::IoHandle::UdpSaveCmsgConfig empty_config{}; + return empty_config; + }; // Register file event and apply socket options. void setUpConnectionSocket(Network::ConnectionSocket& connection_socket, diff --git a/source/common/quic/quic_io_handle_wrapper.h b/source/common/quic/quic_io_handle_wrapper.h index 12dce060a2f2..8df726c59055 100644 --- a/source/common/quic/quic_io_handle_wrapper.h +++ b/source/common/quic/quic_io_handle_wrapper.h @@ -59,20 +59,22 @@ class QuicIoHandleWrapper : public Network::IoHandle { return io_handle_.sendmsg(slices, num_slice, flags, self_ip, peer_address); } Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) override { + uint32_t self_port, const UdpSaveCmsgConfig& udp_save_cmsg_config, + RecvMsgOutput& output) override { if (closed_) { ASSERT(false, "recvmmsg is called after close."); return {0, Network::IoSocketError::getIoSocketEbadfError()}; } - return io_handle_.recvmsg(slices, num_slice, self_port, output); + return io_handle_.recvmsg(slices, num_slice, self_port, udp_save_cmsg_config, output); } Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const UdpSaveCmsgConfig& udp_save_cmsg_config, RecvMsgOutput& output) override { if (closed_) { ASSERT(false, "recvmmsg is called after close."); return {0, Network::IoSocketError::getIoSocketEbadfError()}; } - return io_handle_.recvmmsg(slices, self_port, output); + return io_handle_.recvmmsg(slices, self_port, udp_save_cmsg_config, output); } Api::IoCallUint64Result recv(void* buffer, size_t length, int flags) override { if (closed_) { diff --git a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc index 1f0fa6d8c236..52bc70f0a597 100644 --- a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc +++ b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc @@ -633,7 +633,7 @@ void UdpProxyFilter::ActiveSession::onInjectWriteDatagramToFilterChain(ActiveWri void UdpProxyFilter::UdpActiveSession::processPacket( Network::Address::InstanceConstSharedPtr local_address, Network::Address::InstanceConstSharedPtr peer_address, Buffer::InstancePtr buffer, - MonotonicTime receive_time, uint8_t tos) { + MonotonicTime receive_time, uint8_t tos, Buffer::RawSlice saved_cmsg) { const uint64_t rx_buffer_length = buffer->length(); ENVOY_LOG(trace, "received {} byte datagram from upstream: downstream={} local={} upstream={}", rx_buffer_length, addresses_.peer_->asStringView(), addresses_.local_->asStringView(), @@ -642,8 +642,11 @@ void UdpProxyFilter::UdpActiveSession::processPacket( cluster_.cluster_stats_.sess_rx_datagrams_.inc(); cluster_.cluster_.info()->trafficStats()->upstream_cx_rx_bytes_total_.add(rx_buffer_length); - Network::UdpRecvData recv_data{ - {std::move(local_address), std::move(peer_address)}, std::move(buffer), receive_time, tos}; + Network::UdpRecvData recv_data{{std::move(local_address), std::move(peer_address)}, + std::move(buffer), + receive_time, + tos, + saved_cmsg}; processUpstreamDatagram(recv_data); } @@ -1074,7 +1077,9 @@ void UdpProxyFilter::TunnelingActiveSession::onUpstreamData(Buffer::Instance& da Network::UdpRecvData recv_data{{addresses_.local_, addresses_.peer_}, std::make_unique(data), - cluster_.filter_.config_->timeSource().monotonicTime()}; + cluster_.filter_.config_->timeSource().monotonicTime(), + 0, + {}}; processUpstreamDatagram(recv_data); } diff --git a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h index 245c3a40dc82..8b5fa14f38fa 100644 --- a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h +++ b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h @@ -654,8 +654,8 @@ class UdpProxyFilter : public Network::UdpListenerReadFilter, // Network::UdpPacketProcessor void processPacket(Network::Address::InstanceConstSharedPtr local_address, Network::Address::InstanceConstSharedPtr peer_address, - Buffer::InstancePtr buffer, MonotonicTime receive_time, - uint8_t tos) override; + Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos, + Buffer::RawSlice saved_csmg) override; uint64_t maxDatagramSize() const override { return cluster_.filter_.config_->upstreamSocketConfig().max_rx_datagram_size_; @@ -670,6 +670,11 @@ class UdpProxyFilter : public Network::UdpListenerReadFilter, return Network::MAX_NUM_PACKETS_PER_EVENT_LOOP; } + const Network::IoHandle::UdpSaveCmsgConfig& saveCmsgConfig() const override { + static const Network::IoHandle::UdpSaveCmsgConfig empty_config{}; + return empty_config; + }; + private: void onReadReady(); void createUdpSocket(const Upstream::HostConstSharedPtr& host); diff --git a/source/extensions/io_socket/user_space/io_handle_impl.cc b/source/extensions/io_socket/user_space/io_handle_impl.cc index 3081c5b7152c..c953862bc9bd 100644 --- a/source/extensions/io_socket/user_space/io_handle_impl.cc +++ b/source/extensions/io_socket/user_space/io_handle_impl.cc @@ -222,11 +222,14 @@ Api::IoCallUint64Result IoHandleImpl::sendmsg(const Buffer::RawSlice*, uint64_t, } Api::IoCallUint64Result IoHandleImpl::recvmsg(Buffer::RawSlice*, const uint64_t, uint32_t, + const Network::IoHandle::UdpSaveCmsgConfig&, RecvMsgOutput&) { return Network::IoSocketError::ioResultSocketInvalidAddress(); } -Api::IoCallUint64Result IoHandleImpl::recvmmsg(RawSliceArrays&, uint32_t, RecvMsgOutput&) { +Api::IoCallUint64Result IoHandleImpl::recvmmsg(RawSliceArrays&, uint32_t, + const Network::IoHandle::UdpSaveCmsgConfig&, + RecvMsgOutput&) { return Network::IoSocketError::ioResultSocketInvalidAddress(); } diff --git a/source/extensions/io_socket/user_space/io_handle_impl.h b/source/extensions/io_socket/user_space/io_handle_impl.h index e1ff27ae48ad..3b7bbcb6b59a 100644 --- a/source/extensions/io_socket/user_space/io_handle_impl.h +++ b/source/extensions/io_socket/user_space/io_handle_impl.h @@ -59,8 +59,11 @@ class IoHandleImpl final : public Network::IoHandle, const Network::Address::Ip* self_ip, const Network::Address::Instance& peer_address) override; Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) override; + uint32_t self_port, + const Network::IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, + RecvMsgOutput& output) override; Api::IoCallUint64Result recvmmsg(RawSliceArrays& slices, uint32_t self_port, + const Network::IoHandle::UdpSaveCmsgConfig& udp_save_cmsg_config, RecvMsgOutput& output) override; Api::IoCallUint64Result recv(void* buffer, size_t length, int flags) override; bool supportsMmsg() const override; diff --git a/source/extensions/upstreams/http/udp/upstream_request.cc b/source/extensions/upstreams/http/udp/upstream_request.cc index e4a941cf2cc1..fe1af961678f 100644 --- a/source/extensions/upstreams/http/udp/upstream_request.cc +++ b/source/extensions/upstreams/http/udp/upstream_request.cc @@ -130,7 +130,7 @@ void UdpUpstream::onSocketReadReady() { void UdpUpstream::processPacket(Network::Address::InstanceConstSharedPtr /*local_address*/, Network::Address::InstanceConstSharedPtr /*peer_address*/, Buffer::InstancePtr buffer, MonotonicTime /*receive_time*/, - uint8_t /*tos*/) { + uint8_t /*tos*/, Buffer::RawSlice /*saved_cmsg*/) { std::string data = buffer->toString(); quiche::ConnectUdpDatagramUdpPacketPayload payload(data); quiche::QuicheBuffer serialized_capsule = diff --git a/source/extensions/upstreams/http/udp/upstream_request.h b/source/extensions/upstreams/http/udp/upstream_request.h index 34fab9e45da2..168d1754a85b 100644 --- a/source/extensions/upstreams/http/udp/upstream_request.h +++ b/source/extensions/upstreams/http/udp/upstream_request.h @@ -85,7 +85,8 @@ class UdpUpstream : public Router::GenericUpstream, // Handles data received from the UDP Upstream. void processPacket(Network::Address::InstanceConstSharedPtr local_address, Network::Address::InstanceConstSharedPtr peer_address, - Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos) override; + Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos, + Buffer::RawSlice saved_cmsg) override; uint64_t maxDatagramSize() const override { return Network::DEFAULT_UDP_MAX_DATAGRAM_SIZE; } void onDatagramsDropped(uint32_t dropped) override { // TODO(https://github.com/envoyproxy/envoy/issues/23564): Add statistics for CONNECT-UDP @@ -97,6 +98,10 @@ class UdpUpstream : public Router::GenericUpstream, return Network::MAX_NUM_PACKETS_PER_EVENT_LOOP; } uint32_t numOfDroppedDatagrams() { return datagrams_dropped_; } + const Network::IoHandle::UdpSaveCmsgConfig& saveCmsgConfig() const override { + static const Network::IoHandle::UdpSaveCmsgConfig empty_config{}; + return empty_config; + }; // quiche::CapsuleParser::Visitor bool OnCapsule(const quiche::Capsule& capsule) override; diff --git a/source/server/active_udp_listener.h b/source/server/active_udp_listener.h index 3618dd80def6..2933283cc4da 100644 --- a/source/server/active_udp_listener.h +++ b/source/server/active_udp_listener.h @@ -87,6 +87,10 @@ class ActiveRawUdpListener : public ActiveUdpListenerBase, // TODO(mattklein123) change this to a reasonable number if needed. return Network::MAX_NUM_PACKETS_PER_EVENT_LOOP; } + const Network::IoHandle::UdpSaveCmsgConfig& udpSaveCmsgConfig() const override { + static const Network::IoHandle::UdpSaveCmsgConfig empty_config{}; + return empty_config; + } // Network::UdpWorker void onDataWorker(Network::UdpRecvData&& data) override; diff --git a/test/common/network/io_uring_socket_handle_impl_test.cc b/test/common/network/io_uring_socket_handle_impl_test.cc index ce0cd4bd9aeb..44cdc94d719e 100644 --- a/test/common/network/io_uring_socket_handle_impl_test.cc +++ b/test/common/network/io_uring_socket_handle_impl_test.cc @@ -118,7 +118,7 @@ TEST_F(IoUringSocketHandleTest, RecvmsgNotSupported) { Buffer::OwnedImpl write_buffer; auto slice = write_buffer.frontSlice(); IoHandle::RecvMsgOutput output(0, nullptr); - EXPECT_THAT(impl.recvmsg(&slice, 0, 0, output).err_->getErrorCode(), + EXPECT_THAT(impl.recvmsg(&slice, 0, 0, {}, output).err_->getErrorCode(), Api::IoError::IoErrorCode::NoSupport); } @@ -128,7 +128,7 @@ TEST_F(IoUringSocketHandleTest, RecvmmsgNotSupported) { Buffer::OwnedImpl write_buffer; RawSliceArrays array(0, absl::FixedArray(0)); IoHandle::RecvMsgOutput output(0, nullptr); - EXPECT_THAT(impl.recvmmsg(array, 0, output).err_->getErrorCode(), + EXPECT_THAT(impl.recvmmsg(array, 0, {}, output).err_->getErrorCode(), Api::IoError::IoErrorCode::NoSupport); } diff --git a/test/common/network/udp_fuzz.cc b/test/common/network/udp_fuzz.cc index 0614b77bdefc..fe5be5a253ae 100644 --- a/test/common/network/udp_fuzz.cc +++ b/test/common/network/udp_fuzz.cc @@ -47,6 +47,7 @@ class FuzzUdpListenerCallbacks : public Network::UdpListenerCallbacks { uint32_t workerIndex() const override; Network::UdpPacketWriter& udpPacketWriter() override; size_t numPacketsExpectedPerEventLoop() const override; + const Network::IoHandle::UdpSaveCmsgConfig& udpSaveCmsgConfig() const override; private: UdpFuzz* my_upf_; @@ -187,6 +188,11 @@ size_t FuzzUdpListenerCallbacks::numPacketsExpectedPerEventLoop() const { return Network::MAX_NUM_PACKETS_PER_EVENT_LOOP; } +const Network::IoHandle::UdpSaveCmsgConfig& FuzzUdpListenerCallbacks::udpSaveCmsgConfig() const { + static const Network::IoHandle::UdpSaveCmsgConfig empty_config{}; + return empty_config; +} + DEFINE_FUZZER(const uint8_t* buf, size_t len) { UdpFuzz udp_instance(buf, len); } } // namespace } // namespace Envoy diff --git a/test/common/network/udp_listener_impl_test.cc b/test/common/network/udp_listener_impl_test.cc index c603ee816a80..196afc332e62 100644 --- a/test/common/network/udp_listener_impl_test.cc +++ b/test/common/network/udp_listener_impl_test.cc @@ -60,6 +60,8 @@ class UdpListenerImplTest : public UdpListenerImplTestBase { .WillByDefault(Return(os_calls.latched().supportsMmsg())); ON_CALL(listener_callbacks_, numPacketsExpectedPerEventLoop()) .WillByDefault(Return(MAX_NUM_PACKETS_PER_EVENT_LOOP)); + ON_CALL(listener_callbacks_, udpSaveCmsgConfig()) + .WillByDefault(ReturnRef(udp_save_cmsg_config_)); // Set listening socket options. server_socket_->addOptions(SocketOptionFactory::buildIpPacketInfoOptions()); @@ -99,6 +101,7 @@ class UdpListenerImplTest : public UdpListenerImplTestBase { NiceMock override_syscall_; TestThreadsafeSingletonInjector os_calls{&override_syscall_}; bool recvbuf_large_enough_{true}; + const IoHandle::UdpSaveCmsgConfig udp_save_cmsg_config_{}; }; INSTANTIATE_TEST_SUITE_P(IpVersions, UdpListenerImplTest, diff --git a/test/common/network/utility_test.cc b/test/common/network/utility_test.cc index 010a2150494b..804cf3931475 100644 --- a/test/common/network/utility_test.cc +++ b/test/common/network/utility_test.cc @@ -31,6 +31,7 @@ using testing::DoAll; using testing::Eq; using testing::Return; +using testing::ReturnRef; namespace Envoy { namespace Network { @@ -719,6 +720,8 @@ TEST(PacketLoss, LossTest) { IoSocketHandleImpl handle(fd); auto address = Network::Test::getCanonicalLoopbackAddress(version); NiceMock processor; + IoHandle::UdpSaveCmsgConfig udp_save_cmsg_config; + ON_CALL(processor, saveCmsgConfig()).WillByDefault(ReturnRef(udp_save_cmsg_config)); MonotonicTime time(std::chrono::seconds(0)); uint32_t packets_dropped = 0; UdpRecvMsgMethod recv_msg_method = UdpRecvMsgMethod::RecvMsg; diff --git a/test/common/quic/active_quic_listener_test.cc b/test/common/quic/active_quic_listener_test.cc index 84b637abc5e1..7720f70b269d 100644 --- a/test/common/quic/active_quic_listener_test.cc +++ b/test/common/quic/active_quic_listener_test.cc @@ -357,6 +357,9 @@ class ActiveQuicListenerTest : public testing::TestWithParam(stateless_reset_packet->data(), stateless_reset_packet->length()); quic_connection_->processPacket(nullptr, peer_addr_, std::move(buffer), - time_system_.monotonicTime(), /*tos=*/0); + time_system_.monotonicTime(), /*tos=*/0, /*saved_cmsg=*/{}); } EXPECT_CALL(network_connection_callbacks_, onEvent(Network::ConnectionEvent::LocalClose)) .Times(0); auto buffer = std::make_unique(stateless_reset_packet->data(), stateless_reset_packet->length()); quic_connection_->processPacket(nullptr, peer_addr_, std::move(buffer), - time_system_.monotonicTime(), /*tos=*/0); + time_system_.monotonicTime(), /*tos=*/0, /*saved_cmsg=*/{}); } // Tests that receiving a STATELESS_RESET packet on the probing socket doesn't cause crash. diff --git a/test/common/quic/quic_io_handle_wrapper_test.cc b/test/common/quic/quic_io_handle_wrapper_test.cc index 89c4894ffb03..b512ceff2a38 100644 --- a/test/common/quic/quic_io_handle_wrapper_test.cc +++ b/test/common/quic/quic_io_handle_wrapper_test.cc @@ -96,7 +96,7 @@ TEST_F(QuicIoHandleWrapperTest, DelegateIoHandleCalls) { msg->msg_controllen = 0; return Api::SysCallSizeResult{5u, 0}; })); - wrapper_->recvmsg(&slice, 1, /*self_port=*/12345, output); + wrapper_->recvmsg(&slice, 1, /*self_port=*/12345, {}, output); size_t num_packet_per_call = 1u; Network::IoHandle::RecvMsgOutput output2(num_packet_per_call, nullptr); @@ -106,7 +106,7 @@ TEST_F(QuicIoHandleWrapperTest, DelegateIoHandleCalls) { .WillOnce(Invoke([](os_fd_t, struct mmsghdr*, unsigned int, int, struct timespec*) { return Api::SysCallIntResult{-1, SOCKET_ERROR_AGAIN}; })); - wrapper_->recvmmsg(slices, /*self_port=*/12345, output2); + wrapper_->recvmmsg(slices, /*self_port=*/12345, {}, output2); EXPECT_TRUE(wrapper_->close().ok()); @@ -114,9 +114,9 @@ TEST_F(QuicIoHandleWrapperTest, DelegateIoHandleCalls) { wrapper_->readv(5, &slice, 1); wrapper_->writev(&slice, 1); wrapper_->sendmsg(&slice, 1, 0, /*self_ip=*/nullptr, *addr); - EXPECT_DEBUG_DEATH(wrapper_->recvmsg(&slice, 1, /*self_port=*/12345, output), + EXPECT_DEBUG_DEATH(wrapper_->recvmsg(&slice, 1, /*self_port=*/12345, {}, output), "recvmmsg is called after close"); - EXPECT_DEBUG_DEATH(wrapper_->recvmmsg(slices, /*self_port=*/12345, output2), + EXPECT_DEBUG_DEATH(wrapper_->recvmmsg(slices, /*self_port=*/12345, {}, output2), "recvmmsg is called after close"); EXPECT_CALL(os_sys_calls_, supportsUdpGro()); diff --git a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc index 51490fa491a7..69ec1199f3ea 100644 --- a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc +++ b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc @@ -150,10 +150,11 @@ class UdpProxyFilterTest : public UdpProxyFilterBase { } EXPECT_CALL(*socket_->io_handle_, supportsMmsg()).Times(1u); // Return the datagram. - EXPECT_CALL(*socket_->io_handle_, recvmsg(_, 1, _, _)) + EXPECT_CALL(*socket_->io_handle_, recvmsg(_, 1, _, _, _)) .WillOnce( Invoke([this, data, recv_sys_errno]( Buffer::RawSlice* slices, const uint64_t, uint32_t, + const Network::IoHandle::UdpSaveCmsgConfig&, Network::IoHandle::RecvMsgOutput& output) -> Api::IoCallUint64Result { if (recv_sys_errno != 0) { return makeError(recv_sys_errno); @@ -179,7 +180,7 @@ class UdpProxyFilterTest : public UdpProxyFilterBase { } })); // Return an EAGAIN result. - EXPECT_CALL(*socket_->io_handle_, recvmsg(_, 1, _, _)) + EXPECT_CALL(*socket_->io_handle_, recvmsg(_, 1, _, _, _)) .WillOnce(Return(ByMove( Api::IoCallUint64Result(0, Network::IoSocketError::getIoSocketEagainError())))); } diff --git a/test/extensions/io_socket/user_space/io_handle_impl_test.cc b/test/extensions/io_socket/user_space/io_handle_impl_test.cc index 2948f820b9be..7a39edd4ccde 100644 --- a/test/extensions/io_socket/user_space/io_handle_impl_test.cc +++ b/test/extensions/io_socket/user_space/io_handle_impl_test.cc @@ -1261,13 +1261,14 @@ TEST_F(IoHandleImplNotImplementedTest, ErrorOnSendmsg) { TEST_F(IoHandleImplNotImplementedTest, ErrorOnRecvmsg) { Network::IoHandle::RecvMsgOutput output_is_ignored(1, nullptr); - EXPECT_THAT(io_handle_->recvmsg(&slice_, 0, 0, output_is_ignored), IsInvalidAddress()); + EXPECT_THAT(io_handle_->recvmsg(&slice_, 0, 0, {}, output_is_ignored), IsInvalidAddress()); } TEST_F(IoHandleImplNotImplementedTest, ErrorOnRecvmmsg) { RawSliceArrays slices_is_ignored(1, absl::FixedArray({slice_})); Network::IoHandle::RecvMsgOutput output_is_ignored(1, nullptr); - EXPECT_THAT(io_handle_->recvmmsg(slices_is_ignored, 0, output_is_ignored), IsInvalidAddress()); + EXPECT_THAT(io_handle_->recvmmsg(slices_is_ignored, 0, {}, output_is_ignored), + IsInvalidAddress()); } TEST_F(IoHandleImplNotImplementedTest, ErrorOnBind) { diff --git a/test/extensions/upstreams/http/udp/upstream_request_test.cc b/test/extensions/upstreams/http/udp/upstream_request_test.cc index beb3be1d2e3d..42e2e81e8bb2 100644 --- a/test/extensions/upstreams/http/udp/upstream_request_test.cc +++ b/test/extensions/upstreams/http/udp/upstream_request_test.cc @@ -105,7 +105,8 @@ TEST_F(UdpUpstreamTest, ExchangeCapsules) { EXPECT_CALL(mock_upstream_to_downstream_, decodeData(BufferStringEqual(decoded_capsule_fragment), false)); Envoy::MonotonicTime timestamp; - udp_upstream_->processPacket(nullptr, nullptr, std::move(received_data), timestamp, /*tos=*/0); + udp_upstream_->processPacket(nullptr, nullptr, std::move(received_data), timestamp, /*tos=*/0, + /*saved_cmsg=*/{}); } TEST_F(UdpUpstreamTest, HeaderOnlyRequest) { diff --git a/test/integration/filters/test_listener_filter.h b/test/integration/filters/test_listener_filter.h index 40d2b21ba256..e0c7ad03ccd9 100644 --- a/test/integration/filters/test_listener_filter.h +++ b/test/integration/filters/test_listener_filter.h @@ -91,15 +91,19 @@ class TestFirstPacketReceivedFilterState : public StreamInfo::FilterState::Objec static const absl::string_view key() { return "test.filter_state.quic_first_packet_received"; } void incrementPacketCount() { packet_count_++; } void setPacketLength(size_t packet_length) { packet_length_ = packet_length; } + void setPacketHeadersLength(size_t packet_headers_length) { + packet_headers_length_ = packet_headers_length; + } // FilterState::Object absl::optional serializeAsString() const override { - return absl::StrCat(packet_count_, ",", packet_length_); + return absl::StrCat(packet_count_, ",", packet_length_, ",", packet_headers_length_); } private: uint32_t packet_count_ = 0; size_t packet_length_ = 0; + size_t packet_headers_length_ = 0; }; /** @@ -149,6 +153,7 @@ class TestQuicListenerFilter : public Network::QuicListenerFilter { Network::FilterStatus onFirstPacketReceived(const quic::QuicReceivedPacket& packet) override { test_first_packet_received_filter_state_->incrementPacketCount(); test_first_packet_received_filter_state_->setPacketLength(packet.length()); + test_first_packet_received_filter_state_->setPacketHeadersLength(packet.headers_length()); return Network::FilterStatus::Continue; } diff --git a/test/integration/filters/test_socket_interface.cc b/test/integration/filters/test_socket_interface.cc index de2a821a22ec..9099a770072b 100644 --- a/test/integration/filters/test_socket_interface.cc +++ b/test/integration/filters/test_socket_interface.cc @@ -15,9 +15,11 @@ namespace Network { Api::IoCallUint64Result TestIoSocketHandle::recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output) { - auto result = Test::IoSocketHandlePlatformImpl::recvmsg(slices, num_slice, self_port, output); + auto result = Test::IoSocketHandlePlatformImpl::recvmsg(slices, num_slice, self_port, + save_cmsg_config, output); if (read_override_) { read_override_(output); } diff --git a/test/integration/filters/test_socket_interface.h b/test/integration/filters/test_socket_interface.h index b3eba3283375..c1905c62f792 100644 --- a/test/integration/filters/test_socket_interface.h +++ b/test/integration/filters/test_socket_interface.h @@ -80,7 +80,8 @@ class TestIoSocketHandle : public Test::IoSocketHandlePlatformImpl { const Address::Ip* self_ip, const Address::Instance& peer_address) override; Api::IoCallUint64Result recvmsg(Buffer::RawSlice* slices, const uint64_t num_slice, - uint32_t self_port, RecvMsgOutput& output) override; + uint32_t self_port, const UdpSaveCmsgConfig& save_cmsg_config, + RecvMsgOutput& output) override; IoHandlePtr duplicate() override; diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 538b88a82b07..9a39068e7e75 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -168,11 +168,12 @@ class TestEnvoyQuicClientConnection : public EnvoyQuicClientConnection { void processPacket(Network::Address::InstanceConstSharedPtr local_address, Network::Address::InstanceConstSharedPtr peer_address, - Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos) override { + Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos, + Buffer::RawSlice saved_cmsg) override { last_local_address_ = local_address; last_peer_address_ = peer_address; EnvoyQuicClientConnection::processPacket(local_address, peer_address, std::move(buffer), - receive_time, tos); + receive_time, tos, saved_cmsg); } Network::Address::InstanceConstSharedPtr getLastLocalAddress() const { @@ -2455,11 +2456,16 @@ TEST_P(QuicHttpIntegrationTest, StreamTimeoutWithHalfClose) { codec_client_->close(); } -TEST_P(QuicHttpIntegrationTest, QuicListenerFilterReceivesFirstPacket) { +TEST_P(QuicHttpIntegrationTest, QuicListenerFilterReceivesFirstPacketWithCmsg) { useAccessLog(fmt::format("%FILTER_STATE({}:PLAIN)%", TestFirstPacketReceivedFilterState::key())); config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { - auto* listener_filter = - bootstrap.mutable_static_resources()->mutable_listeners(0)->add_listener_filters(); + auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); + envoy::config::core::v3::SocketCmsgHeaders* cmsg = + listener->mutable_udp_listener_config()->mutable_quic_options()->add_save_cmsg_config(); + cmsg->mutable_level()->set_value(GetParam() == Network::Address::IpVersion::v4 ? 0 : 41); + cmsg->mutable_type()->set_value(GetParam() == Network::Address::IpVersion::v4 ? 1 : 50); + cmsg->set_expected_size(128); + auto* listener_filter = listener->add_listener_filters(); listener_filter->set_name("envoy.filters.quic_listener.test"); auto configuration = test::integration::filters::TestQuicListenerFilterConfig(); configuration.set_added_value("foo"); @@ -2478,11 +2484,13 @@ TEST_P(QuicHttpIntegrationTest, QuicListenerFilterReceivesFirstPacket) { std::string log = waitForAccessLog(access_log_name_, 0); // Log format defined in TestFirstPacketReceivedFilterState::serializeAsString. std::vector metrics = absl::StrSplit(log, ','); - ASSERT_EQ(metrics.size(), 2); + ASSERT_EQ(metrics.size(), 3); // onFirstPacketReceived was called only once. EXPECT_EQ(std::stoi(metrics.at(0)), 1); // first packet has length greater than zero. EXPECT_GT(std::stoi(metrics.at(1)), 0); + // first packet has packet headers length greater than zero. + EXPECT_GT(std::stoi(metrics.at(2)), 0); } } // namespace Quic diff --git a/test/mocks/network/io_handle.h b/test/mocks/network/io_handle.h index aff62657ae89..4fac8500e236 100644 --- a/test/mocks/network/io_handle.h +++ b/test/mocks/network/io_handle.h @@ -34,9 +34,10 @@ class MockIoHandle : public IoHandle { const Address::Ip* self_ip, const Address::Instance& peer_address)); MOCK_METHOD(Api::IoCallUint64Result, recvmsg, (Buffer::RawSlice * slices, const uint64_t num_slice, uint32_t self_port, - RecvMsgOutput& output)); + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output)); MOCK_METHOD(Api::IoCallUint64Result, recvmmsg, - (RawSliceArrays & slices, uint32_t self_port, RecvMsgOutput& output)); + (RawSliceArrays & slices, uint32_t self_port, + const UdpSaveCmsgConfig& save_cmsg_config, RecvMsgOutput& output)); MOCK_METHOD(Api::IoCallUint64Result, recv, (void* buffer, size_t length, int flags)); MOCK_METHOD(bool, supportsMmsg, (), (const)); MOCK_METHOD(bool, supportsUdpGro, (), (const)); diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index 3801f334e10a..2ba2fdc77bad 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -188,6 +188,7 @@ class MockUdpListenerCallbacks : public UdpListenerCallbacks { MOCK_METHOD(void, onDataWorker, (Network::UdpRecvData && data)); MOCK_METHOD(void, post, (Network::UdpRecvData && data)); MOCK_METHOD(size_t, numPacketsExpectedPerEventLoop, (), (const)); + MOCK_METHOD(const IoHandle::UdpSaveCmsgConfig&, udpSaveCmsgConfig, (), (const)); }; class MockDrainDecision : public DrainDecision { @@ -719,10 +720,11 @@ class MockUdpPacketProcessor : public UdpPacketProcessor { MOCK_METHOD(void, processPacket, (Address::InstanceConstSharedPtr local_address, Address::InstanceConstSharedPtr peer_address, Buffer::InstancePtr buffer, - MonotonicTime receive_time, uint8_t tos)); + MonotonicTime receive_time, uint8_t tos, Buffer::RawSlice saved_cmsg)); MOCK_METHOD(void, onDatagramsDropped, (uint32_t dropped)); MOCK_METHOD(uint64_t, maxDatagramSize, (), (const)); MOCK_METHOD(size_t, numPacketsExpectedPerEventLoop, (), (const)); + MOCK_METHOD(const IoHandle::UdpSaveCmsgConfig&, saveCmsgConfig, (), (const)); }; class MockSocketInterface : public SocketInterfaceImpl { diff --git a/test/test_common/network_utility.cc b/test/test_common/network_utility.cc index e6462138cad5..874cb2b741f0 100644 --- a/test/test_common/network_utility.cc +++ b/test/test_common/network_utility.cc @@ -206,9 +206,13 @@ struct SyncPacketProcessor : public Network::UdpPacketProcessor { void processPacket(Network::Address::InstanceConstSharedPtr local_address, Network::Address::InstanceConstSharedPtr peer_address, - Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos) override { - Network::UdpRecvData datagram{ - {std::move(local_address), std::move(peer_address)}, std::move(buffer), receive_time, tos}; + Buffer::InstancePtr buffer, MonotonicTime receive_time, uint8_t tos, + Buffer::RawSlice saved_cmsg) override { + Network::UdpRecvData datagram{{std::move(local_address), std::move(peer_address)}, + std::move(buffer), + receive_time, + tos, + saved_cmsg}; data_.push_back(std::move(datagram)); } uint64_t maxDatagramSize() const override { return max_rx_datagram_size_; } @@ -216,6 +220,10 @@ struct SyncPacketProcessor : public Network::UdpPacketProcessor { size_t numPacketsExpectedPerEventLoop() const override { return Network::MAX_NUM_PACKETS_PER_EVENT_LOOP; } + const IoHandle::UdpSaveCmsgConfig& saveCmsgConfig() const override { + static const IoHandle::UdpSaveCmsgConfig empty_config{}; + return empty_config; + } std::list& data_; const uint64_t max_rx_datagram_size_; From 323bb7b8cbfd7323afcf6d0509b5452db2b3020a Mon Sep 17 00:00:00 2001 From: botengyao Date: Mon, 26 Aug 2024 10:40:24 -0400 Subject: [PATCH 42/53] tls: fix openssl 509 null chain malloc leak (#35841) Signed-off-by: Boteng Yao --- test/common/tls/utility_test.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/common/tls/utility_test.cc b/test/common/tls/utility_test.cc index 7f028922fa31..7a3be622ab29 100644 --- a/test/common/tls/utility_test.cc +++ b/test/common/tls/utility_test.cc @@ -223,11 +223,12 @@ TEST(UtilityTest, TestMapX509Stack) { auto func = [](X509& cert) -> std::string { return Utility::getSubjectFromCertificate(cert); }; EXPECT_EQ(expected_subject, Utility::mapX509Stack(*cert_chain, func)); - EXPECT_ENVOY_BUG(Utility::mapX509Stack(*sk_X509_new_null(), func), "x509 stack is empty or NULL"); + bssl::UniquePtr empty_chain(sk_X509_new_null()); + EXPECT_ENVOY_BUG(Utility::mapX509Stack(*empty_chain, func), "x509 stack is empty or NULL"); EXPECT_ENVOY_BUG(Utility::mapX509Stack(*cert_chain, nullptr), "field_extractor is nullptr"); - bssl::UniquePtr fakeCertChain(sk_X509_new_null()); - sk_X509_push(fakeCertChain.get(), nullptr); - EXPECT_EQ(std::vector{""}, Utility::mapX509Stack(*fakeCertChain, func)); + bssl::UniquePtr fake_cert_chain(sk_X509_new_null()); + sk_X509_push(fake_cert_chain.get(), nullptr); + EXPECT_EQ(std::vector{""}, Utility::mapX509Stack(*fake_cert_chain, func)); } } // namespace From df8705b1afcee2e4197ca7932bb9d4c309601260 Mon Sep 17 00:00:00 2001 From: ohadvano <49730675+ohadvano@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:52:06 +0300 Subject: [PATCH 43/53] ecds: hook UDP session filters with config provider (#35713) Adding a new ``ConfigProviderManager`` for UDP session filters with tests. Consuming this provider for static filters. This PR does not add dynamic filters yet, will be done in next PR. --------- Signed-off-by: Ohad Vano --- source/common/filter/config_discovery_impl.h | 48 +++++++++++++++++++ .../filters/udp/udp_proxy/config.cc | 18 ++++++- .../extensions/filters/udp/udp_proxy/config.h | 23 +++++++-- .../filter/config_discovery_impl_test.cc | 41 ++++++++++++++-- 4 files changed, 123 insertions(+), 7 deletions(-) diff --git a/source/common/filter/config_discovery_impl.h b/source/common/filter/config_discovery_impl.h index 7d0cb1c3f7b8..1218971810b3 100644 --- a/source/common/filter/config_discovery_impl.h +++ b/source/common/filter/config_discovery_impl.h @@ -347,6 +347,41 @@ class UdpListenerDynamicFilterConfigProviderImpl } }; +class UdpSessionDynamicFilterConfigProviderImpl + : public DynamicFilterConfigProviderImpl { +public: + UdpSessionDynamicFilterConfigProviderImpl( + FilterConfigSubscriptionSharedPtr& subscription, + const absl::flat_hash_set& require_type_urls, + Server::Configuration::ServerFactoryContext&, + Server::Configuration::FactoryContext& factory_context, + ProtobufTypes::MessagePtr&& default_config, bool last_filter_in_filter_chain, + const std::string& filter_chain_type, absl::string_view stat_prefix, + const Network::ListenerFilterMatcherSharedPtr& listener_filter_matcher) + : DynamicFilterConfigProviderImpl( + subscription, require_type_urls, factory_context.serverFactoryContext().threadLocal(), + std::move(default_config), last_filter_in_filter_chain, filter_chain_type, stat_prefix, + listener_filter_matcher), + factory_context_(factory_context) {} + + void validateMessage(const std::string&, const Protobuf::Message&, + const std::string&) const override { + // UDP session filters don't use the concept of terminal filters. + } + +protected: + Server::Configuration::FactoryContext& factory_context_; + +private: + absl::StatusOr + instantiateFilterFactory(const Protobuf::Message& message) const override { + auto* factory = + Registry::FactoryRegistry:: + getFactoryByType(message.GetTypeName()); + return factory->createFilterFactoryFromProto(message, factory_context_); + } +}; + class QuicListenerDynamicFilterConfigProviderImpl : public ListenerDynamicFilterConfigProviderImpl { public: @@ -774,6 +809,19 @@ class UdpListenerFilterConfigProviderManagerImpl const std::string getConfigDumpType() const override { return "ecds_filter_udp_listener"; } }; +// UDP session filter +class UdpSessionFilterConfigProviderManagerImpl + : public FilterConfigProviderManagerImpl< + Server::Configuration::NamedUdpSessionFilterConfigFactory, + Network::UdpSessionFilterFactoryCb, Server::Configuration::FactoryContext, + UdpSessionDynamicFilterConfigProviderImpl> { +public: + absl::string_view statPrefix() const override { return "udp_session_filter."; } + +protected: + const std::string getConfigDumpType() const override { return "ecds_filter_udp_session"; } +}; + // QUIC listener filter class QuicListenerFilterConfigProviderManagerImpl : public FilterConfigProviderManagerImpl< diff --git a/source/extensions/filters/udp/udp_proxy/config.cc b/source/extensions/filters/udp/udp_proxy/config.cc index 1fee7deedc54..7e157a3305b5 100644 --- a/source/extensions/filters/udp/udp_proxy/config.cc +++ b/source/extensions/filters/udp/udp_proxy/config.cc @@ -1,5 +1,6 @@ #include "source/extensions/filters/udp/udp_proxy/config.h" +#include "source/common/filter/config_discovery_impl.h" #include "source/common/formatter/substitution_format_string.h" namespace Envoy { @@ -88,6 +89,8 @@ UdpProxyFilterConfigImpl::UdpProxyFilterConfigImpl( stats_(generateStats(config.stat_prefix(), context.scope())), // Default prefer_gro to true for upstream client traffic. upstream_socket_config_(config.upstream_socket_config(), true), + udp_session_filter_config_provider_manager_( + createSingletonUdpSessionFilterConfigProviderManager(context.serverFactoryContext())), random_generator_(context.serverFactoryContext().api().randomGenerator()) { if (use_per_packet_load_balancing_ && config.has_tunneling_config()) { throw EnvoyException( @@ -149,12 +152,25 @@ UdpProxyFilterConfigImpl::UdpProxyFilterConfigImpl( Server::Configuration::NamedUdpSessionFilterConfigFactory>(filter); ProtobufTypes::MessagePtr message = Envoy::Config::Utility::translateToFactoryConfig( filter, context.messageValidationVisitor(), factory); + Network::UdpSessionFilterFactoryCb callback = factory.createFilterFactoryFromProto(*message, context); - filter_factories_.push_back(callback); + filter_factories_.push_back( + udp_session_filter_config_provider_manager_->createStaticFilterConfigProvider( + callback, filter.name())); } } +SINGLETON_MANAGER_REGISTRATION(udp_session_filter_config_provider_manager); + +std::shared_ptr +UdpProxyFilterConfigImpl::createSingletonUdpSessionFilterConfigProviderManager( + Server::Configuration::ServerFactoryContext& context) { + return context.singletonManager().getTyped( + SINGLETON_MANAGER_REGISTERED_NAME(udp_session_filter_config_provider_manager), + [] { return std::make_shared(); }); +} + static Registry::RegisterFactory register_; diff --git a/source/extensions/filters/udp/udp_proxy/config.h b/source/extensions/filters/udp/udp_proxy/config.h index 3ecc10711c6d..3fc39ca71d22 100644 --- a/source/extensions/filters/udp/udp_proxy/config.h +++ b/source/extensions/filters/udp/udp_proxy/config.h @@ -2,6 +2,7 @@ #include "envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.pb.h" #include "envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.pb.validate.h" +#include "envoy/filter/config_provider_manager.h" #include "envoy/server/filter_config.h" #include "source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h" @@ -106,6 +107,12 @@ class TunnelingConfigImpl : public UdpTunnelingConfig { bool propagate_response_trailers_; }; +using UdpSessionFilterConfigProviderManager = + Filter::FilterConfigProviderManager; +using UdpSessionFilterFactoriesList = + std::vector>; + class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig, public UdpSessionFilterChainFactory, Logger::Loggable { @@ -151,8 +158,12 @@ class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig, // UdpSessionFilterChainFactory void createFilterChain(Network::UdpSessionFilterChainFactoryCallbacks& callbacks) const override { - for (const Network::UdpSessionFilterFactoryCb& factory : filter_factories_) { - factory(callbacks); + for (const auto& filter_config_provider : filter_factories_) { + auto config = filter_config_provider->config(); + if (config.has_value()) { + Network::UdpSessionFilterFactoryCb& factory = config.value(); + factory(callbacks); + } } }; @@ -164,6 +175,10 @@ class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig, POOL_GAUGE_PREFIX(scope, final_prefix))}; } + std::shared_ptr + createSingletonUdpSessionFilterConfigProviderManager( + Server::Configuration::ServerFactoryContext& context); + Upstream::ClusterManager& cluster_manager_; TimeSource& time_source_; Router::RouterConstSharedPtr router_; @@ -178,7 +193,9 @@ class UdpProxyFilterConfigImpl : public UdpProxyFilterConfig, std::vector session_access_logs_; std::vector proxy_access_logs_; UdpTunnelingConfigPtr tunneling_config_; - std::list filter_factories_; + std::shared_ptr + udp_session_filter_config_provider_manager_; + UdpSessionFilterFactoriesList filter_factories_; Random::RandomGenerator& random_generator_; }; diff --git a/test/common/filter/config_discovery_impl_test.cc b/test/common/filter/config_discovery_impl_test.cc index cb580db0ffde..0c7582279fda 100644 --- a/test/common/filter/config_discovery_impl_test.cc +++ b/test/common/filter/config_discovery_impl_test.cc @@ -130,6 +130,22 @@ class TestUdpListenerFilterFactory std::string name() const override { return "envoy.test.filter"; } }; +class TestUdpSessionFilterFactory + : public TestFilterFactory, + public Server::Configuration::NamedUdpSessionFilterConfigFactory { +public: + Network::UdpSessionFilterFactoryCb + createFilterFactoryFromProto(const Protobuf::Message&, + Server::Configuration::FactoryContext&) override { + created_ = true; + return [](Network::UdpSessionFilterChainFactoryCallbacks&) -> void {}; + } + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + std::string name() const override { return "envoy.test.filter"; } +}; + class TestQuicListenerFilterFactory : public TestFilterFactory, public Server::Configuration::NamedQuicListenerFilterConfigFactory { @@ -374,6 +390,23 @@ class UdpListenerFilterConfigDiscoveryImplTest } }; +// UDP session filter test +class UdpSessionFilterConfigDiscoveryImplTest + : public FilterConfigDiscoveryImplTest< + Network::UdpSessionFilterFactoryCb, Server::Configuration::FactoryContext, + UdpSessionFilterConfigProviderManagerImpl, TestUdpSessionFilterFactory, + Server::Configuration::NamedUdpSessionFilterConfigFactory, + Server::Configuration::MockFactoryContext> { +public: + const std::string getFilterType() const override { return "udp_session"; } + const std::string getConfigReloadCounter() const override { + return "extension_config_discovery.udp_session_filter.foo.config_reload"; + } + const std::string getConfigFailCounter() const override { + return "extension_config_discovery.udp_session_filter.foo.config_fail"; + } +}; + // QUIC listener filter test class QuicListenerFilterConfigDiscoveryImplTest : public FilterConfigDiscoveryImplTest< @@ -393,7 +426,8 @@ class QuicListenerFilterConfigDiscoveryImplTest /*************************************************************************************** * Parameterized test for * - * HTTP filter, Network filter, TCP listener filter And UDP listener filter * + * HTTP filter, Network filter, TCP listener filter, UDP session filter and * + * UDP listener filter * * * ***************************************************************************************/ template @@ -404,7 +438,7 @@ using FilterConfigDiscoveryTestTypes = ::testing::Types< HttpFilterConfigDiscoveryImplTest, HttpUpstreamFilterConfigDiscoveryImplTest, NetworkFilterConfigDiscoveryImplTest, NetworkUpstreamFilterConfigDiscoveryImplTest, TcpListenerFilterConfigDiscoveryImplTest, UdpListenerFilterConfigDiscoveryImplTest, - QuicListenerFilterConfigDiscoveryImplTest>; + UdpSessionFilterConfigDiscoveryImplTest, QuicListenerFilterConfigDiscoveryImplTest>; TYPED_TEST_SUITE(FilterConfigDiscoveryImplTestParameter, FilterConfigDiscoveryTestTypes); @@ -646,7 +680,8 @@ TYPED_TEST(FilterConfigDiscoveryImplTestParameter, TerminalFilterInvalid) { EXPECT_CALL(config_discovery_test.init_watcher_, ready()); if (config_discovery_test.getFilterType() == "listener" || - config_discovery_test.getFilterType() == "upstream_network") { + config_discovery_test.getFilterType() == "upstream_network" || + config_discovery_test.getFilterType() == "udp_session") { ASSERT_TRUE(config_discovery_test.callbacks_ ->onConfigUpdate(decoded_resources.refvec_, response.version_info()) .ok()); From 87d555a716020162f5a9823ebcc7a6723fe8ff07 Mon Sep 17 00:00:00 2001 From: bsurber <73970703+bsurber@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:22:27 -0700 Subject: [PATCH 44/53] Revert "RLQS: Refactor traffic processing in the RLQS filter & fix a broken expiration check" (#35847) Reverts envoyproxy/envoy#35723 Signed-off-by: Brian Surber --- .../http/rate_limit_quota/client_impl.cc | 9 +- .../filters/http/rate_limit_quota/filter.cc | 262 ++++++--------- .../filters/http/rate_limit_quota/filter.h | 8 - .../rate_limit_quota/quota_bucket_cache.h | 10 +- .../http/rate_limit_quota/integration_test.cc | 298 +----------------- 5 files changed, 102 insertions(+), 485 deletions(-) diff --git a/source/extensions/filters/http/rate_limit_quota/client_impl.cc b/source/extensions/filters/http/rate_limit_quota/client_impl.cc index 44851acc2349..f454695b55bc 100644 --- a/source/extensions/filters/http/rate_limit_quota/client_impl.cc +++ b/source/extensions/filters/http/rate_limit_quota/client_impl.cc @@ -85,7 +85,7 @@ void RateLimitClientImpl::onReceiveMessage(RateLimitQuotaResponsePtr&& response) // Get the hash id value from BucketId in the response. const size_t bucket_id = MessageUtil::hash(action.bucket_id()); - ENVOY_LOG(debug, + ENVOY_LOG(trace, "Received a response for bucket id proto :\n {}, and generated " "the associated hashed bucket id: {}", action.bucket_id().DebugString(), bucket_id); @@ -97,11 +97,10 @@ void RateLimitClientImpl::onReceiveMessage(RateLimitQuotaResponsePtr&& response) switch (action.bucket_action_case()) { case envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse_BucketAction:: kQuotaAssignmentAction: { - quota_buckets_[bucket_id]->cached_action = action; - quota_buckets_[bucket_id]->current_assignment_time = time_source_.monotonicTime(); - if (quota_buckets_[bucket_id]->cached_action->has_quota_assignment_action()) { + quota_buckets_[bucket_id]->bucket_action = action; + if (quota_buckets_[bucket_id]->bucket_action.has_quota_assignment_action()) { auto rate_limit_strategy = quota_buckets_[bucket_id] - ->cached_action->quota_assignment_action() + ->bucket_action.quota_assignment_action() .rate_limit_strategy(); if (rate_limit_strategy.has_token_bucket()) { diff --git a/source/extensions/filters/http/rate_limit_quota/filter.cc b/source/extensions/filters/http/rate_limit_quota/filter.cc index e984ae290857..7cbb29fcdb4f 100644 --- a/source/extensions/filters/http/rate_limit_quota/filter.cc +++ b/source/extensions/filters/http/rate_limit_quota/filter.cc @@ -9,8 +9,6 @@ namespace Extensions { namespace HttpFilters { namespace RateLimitQuota { -using envoy::type::v3::RateLimitStrategy; - const char kBucketMetadataNamespace[] = "envoy.extensions.http_filters.rate_limit_quota.bucket"; Http::FilterHeadersStatus RateLimitQuotaFilter::decodeHeaders(Http::RequestHeaderMap& headers, @@ -125,36 +123,34 @@ void RateLimitQuotaFilter::createNewBucket(const BucketId& bucket_id, // Create new bucket and store it into quota cache. std::unique_ptr new_bucket = std::make_unique(); - // The first matched request doesn't have quota assignment from the RLQS - // server yet, so the action is performed based on pre-configured strategy - // from no assignment behavior config. + // The first matched request doesn't have quota assignment from the RLQS server yet, so the + // action is performed based on pre-configured strategy from no assignment behavior config. auto mutable_rate_limit_strategy = - new_bucket->default_action.mutable_quota_assignment_action()->mutable_rate_limit_strategy(); + new_bucket->bucket_action.mutable_quota_assignment_action()->mutable_rate_limit_strategy(); if (match_action.bucketSettings().has_no_assignment_behavior()) { *mutable_rate_limit_strategy = match_action.bucketSettings().no_assignment_behavior().fallback_rate_limit(); } else { - // When `no_assignment_behavior` is not configured, default blanket rule is - // set to ALLOW_ALL. (i.e., fail-open). - mutable_rate_limit_strategy->set_blanket_rule(RateLimitStrategy::ALLOW_ALL); + // When `no_assignment_behavior` is not configured, default blanket rule is set to ALLOW_ALL. + // (i.e., fail-open). + mutable_rate_limit_strategy->set_blanket_rule(envoy::type::v3::RateLimitStrategy::ALLOW_ALL); } // Set up the bucket id. new_bucket->bucket_id = bucket_id; - // Mark the assignment time. - auto now = time_source_.monotonicTime(); - new_bucket->current_assignment_time = now; + // Set up the first time assignment time. + new_bucket->first_assignment_time = time_source_.monotonicTime(); // Set up the quota usage. QuotaUsage quota_usage; - quota_usage.last_report = - std::chrono::duration_cast(now.time_since_epoch()); + quota_usage.last_report = std::chrono::duration_cast( + time_source_.monotonicTime().time_since_epoch()); switch (mutable_rate_limit_strategy->blanket_rule()) { PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; - case RateLimitStrategy::ALLOW_ALL: + case envoy::type::v3::RateLimitStrategy::ALLOW_ALL: quota_usage.num_requests_allowed++; break; - case RateLimitStrategy::DENY_ALL: + case envoy::type::v3::RateLimitStrategy::DENY_ALL: quota_usage.num_requests_denied++; break; } @@ -206,174 +202,102 @@ RateLimitQuotaFilter::sendImmediateReport(const size_t bucket_id, // bucket_matchers for the first time) should be already set based on no assignment behavior in // `createNewBucket` when the bucket is initially created. ASSERT(quota_buckets_.find(bucket_id) != quota_buckets_.end()); - // If not given a default blanket rule, the first matched request is allowed. - if (!quota_buckets_[bucket_id]->default_action.has_quota_assignment_action() || - !quota_buckets_[bucket_id] - ->default_action.quota_assignment_action() - .has_rate_limit_strategy() || - !quota_buckets_[bucket_id] - ->default_action.quota_assignment_action() - .rate_limit_strategy() - .has_blanket_rule()) { - ENVOY_LOG(trace, "Without a default blanket rule configured, the first matched " - "request with hashed bucket_id {} is allowed through."); - ENVOY_LOG(debug, "Default action for bucket_id {} does not contain a blanket action: {}", - bucket_id, quota_buckets_[bucket_id]->default_action.DebugString()); + if (quota_buckets_[bucket_id] + ->bucket_action.quota_assignment_action() + .rate_limit_strategy() + .blanket_rule() == envoy::type::v3::RateLimitStrategy::ALLOW_ALL) { + ENVOY_LOG( + trace, + "For first matched request with hashed bucket_id {}, it is allowed by ALLOW_ALL strategy.", + bucket_id); return Http::FilterHeadersStatus::Continue; - } - auto blanket_rule = quota_buckets_[bucket_id] - ->default_action.quota_assignment_action() - .rate_limit_strategy() - .blanket_rule(); - if (blanket_rule == RateLimitStrategy::DENY_ALL) { - // For the request that is rejected due to DENY_ALL - // no_assignment_behavior, immediate report is still sent to RLQS server - // above, and here the local reply with deny response is sent. - ENVOY_LOG(trace, - "For first matched request with hashed bucket_id {}, it is " - "throttled by DENY_ALL strategy.", - bucket_id); - ENVOY_LOG(debug, "Hit configured default DENY_ALL for bucket_id {}", bucket_id); + } else { + // For the request that is rejected due to DENY_ALL no_assignment_behavior, immediate report is + // still sent to RLQS server above, and here the local reply with deny response is sent. + ENVOY_LOG( + trace, + "For first matched request with hashed bucket_id {}, it is throttled by DENY_ALL strategy.", + bucket_id); sendDenyResponse(); return Envoy::Http::FilterHeadersStatus::StopIteration; } - - ENVOY_LOG(trace, - "For first matched request with hashed bucket_id {}, it is " - "allowed by the configured default ALLOW_ALL strategy.", - bucket_id); - ENVOY_LOG(debug, "Hit configured default ALLOW_ALL for bucket_id {}", bucket_id); - return Http::FilterHeadersStatus::Continue; } -Http::FilterHeadersStatus RateLimitQuotaFilter::getStatusFromAction(const BucketAction& action, - size_t bucket_id) { - if (!action.has_quota_assignment_action() || - !action.quota_assignment_action().has_rate_limit_strategy()) { - ENVOY_LOG(debug, - "Selected bucket action defaulting to ALLOW_ALL as it does not " - "have an assignment for bucket_id {}", - bucket_id); - return Envoy::Http::FilterHeadersStatus::Continue; - } - - // TODO(tyxia) Currently, blanket rule and token bucket strategies are - // implemented. Change to switch case when `RequestsPerTimeUnit` strategy is - // implemented. - auto rate_limit_strategy = action.quota_assignment_action().rate_limit_strategy(); - if (rate_limit_strategy.has_blanket_rule()) { - bool allow = (rate_limit_strategy.blanket_rule() != RateLimitStrategy::DENY_ALL); - ENVOY_LOG(trace, "Request with hashed bucket_id {} is {} by the selected blanket rule.", - bucket_id, allow ? "allowed" : "denied"); - return allow ? Envoy::Http::FilterHeadersStatus::Continue - : Envoy::Http::FilterHeadersStatus::StopIteration; - } - - if (rate_limit_strategy.has_token_bucket()) { - auto token_bucket = quota_buckets_[bucket_id]->token_bucket_limiter.get(); - ASSERT(token_bucket); - - // Try to consume 1 token from the bucket. - if (token_bucket->consume(1, /*allow_partial=*/false)) { - // Request is allowed. - ENVOY_LOG(trace, - "Request with hashed bucket_id {} is allowed by token bucket " - "limiter.", - bucket_id); - ENVOY_LOG(debug, - "Allowing request as token bucket is not empty for bucket_id " - "{}. Initial assignment: {}.", - bucket_id, rate_limit_strategy.token_bucket().ShortDebugString()); - return Envoy::Http::FilterHeadersStatus::Continue; - } - // Request is throttled. - ENVOY_LOG(trace, - "Request with hashed bucket_id {} is throttled by token " - "bucket limiter", - bucket_id); - ENVOY_LOG(debug, - "Denying request as token bucket is exhausted for bucket_id {}. " - "Initial assignment: {}.", - bucket_id, rate_limit_strategy.token_bucket().ShortDebugString()); - return Envoy::Http::FilterHeadersStatus::StopIteration; - } - - ENVOY_LOG(error, - "Failing open as selected bucket action for bucket_id {} contains " - "an unsupported rate limit strategy: {}", - bucket_id, rate_limit_strategy.DebugString()); - return Envoy::Http::FilterHeadersStatus::Continue; -} - -bool isCachedActionExpired(TimeSource& time_source, const Bucket& bucket) { +Http::FilterHeadersStatus +RateLimitQuotaFilter::processCachedBucket(size_t bucket_id, + const RateLimitOnMatchAction& match_action) { // First, check if assignment has expired nor not. auto now = std::chrono::duration_cast( - time_source.monotonicTime().time_since_epoch()); + time_source_.monotonicTime().time_since_epoch()); auto assignment_time_elapsed = Protobuf::util::TimeUtil::NanosecondsToDuration( (now - std::chrono::duration_cast( - bucket.current_assignment_time.time_since_epoch())) + quota_buckets_[bucket_id]->first_assignment_time.time_since_epoch())) .count()); + if (assignment_time_elapsed > quota_buckets_[bucket_id] + ->bucket_action.quota_assignment_action() + .assignment_time_to_live()) { + // If expired, remove the cache entry. + quota_buckets_.erase(bucket_id); + + // Default strategy is fail-Open (i.e., allow_all). + auto ret_status = Envoy::Http::FilterHeadersStatus::Continue; + // Check the expired assignment behavior if configured. + // Note, only fail-open and fail-close are supported, more advanced expired assignment can be + // supported as needed. + if (match_action.bucketSettings().has_expired_assignment_behavior()) { + if (match_action.bucketSettings() + .expired_assignment_behavior() + .fallback_rate_limit() + .blanket_rule() == envoy::type::v3::RateLimitStrategy::DENY_ALL) { + sendDenyResponse(); + ret_status = Envoy::Http::FilterHeadersStatus::StopIteration; + } + } - return (assignment_time_elapsed > - bucket.cached_action->quota_assignment_action().assignment_time_to_live()); -} - -Http::FilterHeadersStatus -RateLimitQuotaFilter::processCachedBucket(size_t bucket_id, - const RateLimitOnMatchAction& match_action) { - auto* cached_bucket = quota_buckets_[bucket_id].get(); - Http::FilterHeadersStatus ret_status; - - if (!cached_bucket->cached_action.has_value()) { - // If no cached action, use the default action. - ret_status = getStatusFromAction(cached_bucket->default_action, bucket_id); - } else if (isCachedActionExpired(time_source_, *cached_bucket)) { - // If expired, remove the expired action & fallback. - ret_status = processExpiredBucket(bucket_id, match_action); - cached_bucket->cached_action = absl::nullopt; - } else { - // If not expired, use the cached action. - ret_status = getStatusFromAction(*cached_bucket->cached_action, bucket_id); - } - - if (ret_status == Envoy::Http::FilterHeadersStatus::StopIteration) { - sendDenyResponse(); - quota_buckets_[bucket_id]->quota_usage.num_requests_denied += 1; - } else { - quota_buckets_[bucket_id]->quota_usage.num_requests_allowed += 1; - } - - return ret_status; -} - -// Note: does not remove the expired entity from the cache. -Http::FilterHeadersStatus -RateLimitQuotaFilter::processExpiredBucket(size_t bucket_id, - const RateLimitOnMatchAction& match_action) { - auto* cached_bucket = quota_buckets_[bucket_id].get(); - - if (!match_action.bucketSettings().has_expired_assignment_behavior() || - !match_action.bucketSettings().expired_assignment_behavior().has_fallback_rate_limit()) { - ENVOY_LOG(debug, "Selecting default action for bucket_id as expiration " - "fallback assignment doesn't have a configured override {}"); - return getStatusFromAction(cached_bucket->default_action, bucket_id); + return ret_status; } - const RateLimitStrategy& fallback_rate_limit = - match_action.bucketSettings().expired_assignment_behavior().fallback_rate_limit(); - if (fallback_rate_limit.has_blanket_rule() && - fallback_rate_limit.blanket_rule() == RateLimitStrategy::DENY_ALL) { - ENVOY_LOG(debug, - "Exipred action falling back to configured DENY_ALL for " - "bucket_id {}", - bucket_id); - return Envoy::Http::FilterHeadersStatus::StopIteration; + // Second, get the quota assignment (if exists) from the cached bucket action. + if (quota_buckets_[bucket_id]->bucket_action.has_quota_assignment_action()) { + auto rate_limit_strategy = + quota_buckets_[bucket_id]->bucket_action.quota_assignment_action().rate_limit_strategy(); + + // TODO(tyxia) Currently, blanket rule and token bucket strategies are implemented. + // Change to switch case when `RequestsPerTimeUnit` strategy is implemented. + if (rate_limit_strategy.has_blanket_rule()) { + if (rate_limit_strategy.blanket_rule() == envoy::type::v3::RateLimitStrategy::ALLOW_ALL) { + quota_buckets_[bucket_id]->quota_usage.num_requests_allowed += 1; + ENVOY_LOG(trace, + "Request with hashed bucket_id {} is allowed by cached ALLOW_ALL strategy.", + bucket_id); + } else if (rate_limit_strategy.blanket_rule() == + envoy::type::v3::RateLimitStrategy::DENY_ALL) { + quota_buckets_[bucket_id]->quota_usage.num_requests_denied += 1; + ENVOY_LOG(trace, + "Request with hashed bucket_id {} is throttled by cached DENY_ALL strategy.", + bucket_id); + sendDenyResponse(); + return Envoy::Http::FilterHeadersStatus::StopIteration; + } + } else if (rate_limit_strategy.has_token_bucket()) { + ASSERT(quota_buckets_[bucket_id]->token_bucket_limiter != nullptr); + TokenBucket* limiter = quota_buckets_[bucket_id]->token_bucket_limiter.get(); + // Try to consume 1 token from the bucket. + if (limiter->consume(1, /*allow_partial=*/false)) { + // Request is allowed. + quota_buckets_[bucket_id]->quota_usage.num_requests_allowed += 1; + ENVOY_LOG(trace, "Request with hashed bucket_id {} is allowed by token bucket limiter.", + bucket_id); + } else { + // Request is throttled. + quota_buckets_[bucket_id]->quota_usage.num_requests_denied += 1; + ENVOY_LOG(trace, "Request with hashed bucket_id {} is throttled by token bucket limiter", + bucket_id); + sendDenyResponse(); + return Envoy::Http::FilterHeadersStatus::StopIteration; + } + } } - - ENVOY_LOG(debug, - "Exipred action falling back to configured ALLOW_ALL for " - "bucket_id {}", - bucket_id); return Envoy::Http::FilterHeadersStatus::Continue; } diff --git a/source/extensions/filters/http/rate_limit_quota/filter.h b/source/extensions/filters/http/rate_limit_quota/filter.h index 570e7245efec..e1302214affb 100644 --- a/source/extensions/filters/http/rate_limit_quota/filter.h +++ b/source/extensions/filters/http/rate_limit_quota/filter.h @@ -93,8 +93,6 @@ class RateLimitQuotaFilter : public Http::PassThroughFilter, Http::FilterHeadersStatus sendImmediateReport(const size_t bucket_id, const RateLimitOnMatchAction& match_action); - Http::FilterHeadersStatus getStatusFromAction(const BucketAction& action, size_t bucket_id); - Http::FilterHeadersStatus processCachedBucket(size_t bucket_id, const RateLimitOnMatchAction& match_action); // TODO(tyxia) Build the customized response based on `DenyResponseSettings`. @@ -103,12 +101,6 @@ class RateLimitQuotaFilter : public Http::PassThroughFilter, callbacks_->streamInfo().setResponseFlag(StreamInfo::CoreResponseFlag::RateLimited); } - // Get the FilterHeadersStatus to return when a selected bucket has an expired - // assignment. Note: this does not actually remove the expired entity from the - // cache. - Http::FilterHeadersStatus processExpiredBucket(size_t bucket_id, - const RateLimitOnMatchAction& match_action); - FilterConfigConstSharedPtr config_; Grpc::GrpcServiceConfigWithHashKey config_with_hash_key_; Server::Configuration::FactoryContext& factory_context_; diff --git a/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h b/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h index 1896a1e24983..e2923b9156d2 100644 --- a/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h +++ b/source/extensions/filters/http/rate_limit_quota/quota_bucket_cache.h @@ -41,17 +41,13 @@ struct Bucket { // RLQS server. BucketId bucket_id; // Cached action from the response that was received from the RLQS server. - absl::optional cached_action = absl::nullopt; - // Default action defined by the bucket's no_assignment_behavior setting. Used - // when the bucket is waiting for an assigned action from the RLQS server - // (e.g. during initial bucket hits & after stale assignments expire). - BucketAction default_action; + BucketAction bucket_action; // Cache quota usage. QuotaUsage quota_usage; // Rate limiter based on token bucket algorithm. TokenBucketPtr token_bucket_limiter; - // Most recent assignment time. - Envoy::MonotonicTime current_assignment_time; + // First assignment time. + Envoy::MonotonicTime first_assignment_time = {}; }; using BucketsCache = absl::flat_hash_map>; diff --git a/test/extensions/filters/http/rate_limit_quota/integration_test.cc b/test/extensions/filters/http/rate_limit_quota/integration_test.cc index bc83c88a539e..ec4e45a89113 100644 --- a/test/extensions/filters/http/rate_limit_quota/integration_test.cc +++ b/test/extensions/filters/http/rate_limit_quota/integration_test.cc @@ -28,7 +28,6 @@ enum class BlanketRule { struct ConfigOption { bool valid_rlqs_server = true; BlanketRule no_assignment_blanket_rule = BlanketRule::NOT_SPECIFIED; - bool unsupported_no_assignment_strategy = false; BlanketRule expired_assignment_blanket_rule = BlanketRule::NOT_SPECIFIED; }; @@ -111,12 +110,6 @@ class RateLimitQuotaIntegrationTest ->mutable_fallback_rate_limit() ->set_blanket_rule(envoy::type::v3::RateLimitStrategy::DENY_ALL); } - } else if (config_option.unsupported_no_assignment_strategy) { - auto* requests_per_time_unit = mutable_bucket_settings.mutable_no_assignment_behavior() - ->mutable_fallback_rate_limit() - ->mutable_requests_per_time_unit(); - requests_per_time_unit->set_requests_per_time_unit(100); - requests_per_time_unit->set_time_unit(envoy::type::v3::RateLimitUnit::SECOND); } if (config_option.expired_assignment_blanket_rule != BlanketRule::NOT_SPECIFIED) { @@ -941,153 +934,6 @@ TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithTokenBucket) { } } -TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithUnsupportedStrategy) { - initializeConfig(); - HttpIntegrationTest::initialize(); - absl::flat_hash_map custom_headers = {{"environment", "staging"}, - {"group", "envoy"}}; - - for (int i = 0; i < 2; ++i) { - // Send downstream client request to upstream. - sendClientRequest(&custom_headers); - - // Handle the request received by upstream. All requests will be allowed - // since the strategy is not supported. - ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); - ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); - ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); - upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); - upstream_request_->encodeData(100, true); - - // Verify the response to downstream. - ASSERT_TRUE(response_->waitForEndStream()); - EXPECT_TRUE(response_->complete()); - EXPECT_EQ(response_->headers().getStatusValue(), "200"); - - // Only first downstream client request will trigger the reports to RLQS - // server as the subsequent requests will find the entry in the cache. - if (i == 0) { - // Start the gRPC stream to RLQS server. - ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); - ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); - - envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; - ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); - rlqs_stream_->startGrpcStream(); - - // Build the response. - envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; - absl::flat_hash_map custom_headers_cpy = custom_headers; - custom_headers_cpy.insert({"name", "prod"}); - auto* bucket_action = rlqs_response.add_bucket_action(); - for (const auto& [key, value] : custom_headers_cpy) { - (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); - auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); - quota_assignment->mutable_assignment_time_to_live()->set_seconds(120); - auto* strategy = quota_assignment->mutable_rate_limit_strategy(); - auto* unsupported_strategy = strategy->mutable_requests_per_time_unit(); - unsupported_strategy->set_requests_per_time_unit(10); - unsupported_strategy->set_time_unit(envoy::type::v3::RateLimitUnit::SECOND); - } - - // Send the response from RLQS server. - rlqs_stream_->sendGrpcMessage(rlqs_response); - absl::SleepFor(absl::Seconds(1)); - } - - cleanUp(); - } -} - -TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithUnsetStrategy) { - initializeConfig(); - HttpIntegrationTest::initialize(); - absl::flat_hash_map custom_headers = {{"environment", "staging"}, - {"group", "envoy"}}; - - for (int i = 0; i < 2; ++i) { - // Send downstream client request to upstream. - sendClientRequest(&custom_headers); - - // Handle the request received by upstream. All requests will be allowed - // since the strategy is not set. - ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); - ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); - ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); - upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); - upstream_request_->encodeData(100, true); - - // Verify the response to downstream. - ASSERT_TRUE(response_->waitForEndStream()); - EXPECT_TRUE(response_->complete()); - EXPECT_EQ(response_->headers().getStatusValue(), "200"); - - // Only first downstream client request will trigger the reports to RLQS - // server as the subsequent requests will find the entry in the cache. - if (i == 0) { - // Start the gRPC stream to RLQS server. - ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); - ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); - - envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; - ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); - rlqs_stream_->startGrpcStream(); - - // Build the response. - envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; - absl::flat_hash_map custom_headers_cpy = custom_headers; - custom_headers_cpy.insert({"name", "prod"}); - auto* bucket_action = rlqs_response.add_bucket_action(); - for (const auto& [key, value] : custom_headers_cpy) { - (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); - auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); - quota_assignment->mutable_assignment_time_to_live()->set_seconds(120); - } - - // Send the response from RLQS server. - rlqs_stream_->sendGrpcMessage(rlqs_response); - absl::SleepFor(absl::Seconds(1)); - } - - cleanUp(); - } -} - -TEST_P(RateLimitQuotaIntegrationTest, MultiRequestWithUnsupportedDefaultAction) { - ConfigOption option; - option.unsupported_no_assignment_strategy = true; - initializeConfig(option); - HttpIntegrationTest::initialize(); - absl::flat_hash_map custom_headers = {{"environment", "staging"}, - {"group", "envoy"}}; - - // Send downstream client request to upstream. - sendClientRequest(&custom_headers); - - // Handle the request received by upstream. All requests will be allowed - // since the strategy is not set. - ASSERT_TRUE(fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); - ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); - ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); - upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); - upstream_request_->encodeData(100, true); - - // Verify the response to downstream. - ASSERT_TRUE(response_->waitForEndStream()); - EXPECT_TRUE(response_->complete()); - EXPECT_EQ(response_->headers().getStatusValue(), "200"); - - // Start the gRPC stream to RLQS server. - ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); - ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); - - envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; - ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); - rlqs_stream_->startGrpcStream(); - - cleanUp(); -} - TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpiredAssignmentDeny) { ConfigOption option; option.expired_assignment_blanket_rule = BlanketRule::DENY_ALL; @@ -1185,10 +1031,9 @@ TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpiredAssignmentAllow ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); rlqs_stream_->startGrpcStream(); } else { - // 3rd request won't start gRPC stream again since it is kept open and the usage will be - // aggregated instead of spawning an immediate report. + // 3rd request won't start gRPC stream again since it is kept open. envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; - ASSERT_FALSE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); + ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); } // Build the response. @@ -1228,145 +1073,6 @@ TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpiredAssignmentAllow } } -TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpirationToDefaultDeny) { - ConfigOption option; - option.expired_assignment_blanket_rule = BlanketRule::DENY_ALL; - option.no_assignment_blanket_rule = BlanketRule::ALLOW_ALL; - initializeConfig(option); - HttpIntegrationTest::initialize(); - absl::flat_hash_map custom_headers = {{"environment", "staging"}, - {"group", "envoy"}}; - - for (int i = 0; i < 4; ++i) { - // Advance the time to make cached assignment expired. - if (i > 0) { - simTime().advanceTimeWait(std::chrono::seconds(15)); - } - // Send downstream client request to upstream. - sendClientRequest(&custom_headers); - - // Query 1: ALLOW_ALL by default. Query 2: DENY_ALL by assignment. - // Query 3: DENY_ALL by assignment expiration. Query 4: ALLOW_ALL by default. - if (i == 0 || i == 3) { - // Handle the request received by upstream. - ASSERT_TRUE( - fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); - ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); - ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); - upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); - upstream_request_->encodeData(100, true); - - // Verify the response to downstream. - ASSERT_TRUE(response_->waitForEndStream()); - EXPECT_TRUE(response_->complete()); - EXPECT_EQ(response_->headers().getStatusValue(), "200"); - - if (i == 0) { - // Start the gRPC stream to RLQS server & send the initial report. - ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); - ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); - - envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; - ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); - rlqs_stream_->startGrpcStream(); - - // Build the response. - envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; - absl::flat_hash_map custom_headers_cpy = custom_headers; - custom_headers_cpy.insert({"name", "prod"}); - auto* bucket_action = rlqs_response.add_bucket_action(); - - for (const auto& [key, value] : custom_headers_cpy) { - (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); - auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); - quota_assignment->mutable_assignment_time_to_live()->set_seconds(15); - auto* strategy = quota_assignment->mutable_rate_limit_strategy(); - strategy->set_blanket_rule(envoy::type::v3::RateLimitStrategy::DENY_ALL); - } - - // Send the response from RLQS server. - rlqs_stream_->sendGrpcMessage(rlqs_response); - absl::SleepFor(absl::Seconds(1)); - } - } else { - ASSERT_TRUE(response_->waitForEndStream(std::chrono::seconds(5))); - EXPECT_TRUE(response_->complete()); - EXPECT_EQ(response_->headers().getStatusValue(), "429"); - } - - cleanUp(); - } -} - -TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithExpirationWithoutFallback) { - ConfigOption option; - option.no_assignment_blanket_rule = BlanketRule::ALLOW_ALL; - initializeConfig(option); - HttpIntegrationTest::initialize(); - absl::flat_hash_map custom_headers = {{"environment", "staging"}, - {"group", "envoy"}}; - - for (int i = 0; i < 3; ++i) { - // Advance the time to make cached assignment expired. - if (i > 0) { - simTime().advanceTimeWait(std::chrono::seconds(15)); - } - // Send downstream client request to upstream. - sendClientRequest(&custom_headers); - - // Query 1: ALLOW_ALL by default. Query 2: DENY_ALL by assignment. - // Query 3: DENY_ALL by assignment expiration. Query 4: ALLOW_ALL by default. - if (i == 0 || i == 2) { - // Handle the request received by upstream. - ASSERT_TRUE( - fake_upstreams_[0]->waitForHttpConnection(*dispatcher_, fake_upstream_connection_)); - ASSERT_TRUE(fake_upstream_connection_->waitForNewStream(*dispatcher_, upstream_request_)); - ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); - upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false); - upstream_request_->encodeData(100, true); - - // Verify the response to downstream. - ASSERT_TRUE(response_->waitForEndStream()); - EXPECT_TRUE(response_->complete()); - EXPECT_EQ(response_->headers().getStatusValue(), "200"); - - if (i == 0) { - // Start the gRPC stream to RLQS server & send the initial report. - ASSERT_TRUE(grpc_upstreams_[0]->waitForHttpConnection(*dispatcher_, rlqs_connection_)); - ASSERT_TRUE(rlqs_connection_->waitForNewStream(*dispatcher_, rlqs_stream_)); - - envoy::service::rate_limit_quota::v3::RateLimitQuotaUsageReports reports; - ASSERT_TRUE(rlqs_stream_->waitForGrpcMessage(*dispatcher_, reports)); - rlqs_stream_->startGrpcStream(); - - // Build the response. - envoy::service::rate_limit_quota::v3::RateLimitQuotaResponse rlqs_response; - absl::flat_hash_map custom_headers_cpy = custom_headers; - custom_headers_cpy.insert({"name", "prod"}); - auto* bucket_action = rlqs_response.add_bucket_action(); - - for (const auto& [key, value] : custom_headers_cpy) { - (*bucket_action->mutable_bucket_id()->mutable_bucket()).insert({key, value}); - auto* quota_assignment = bucket_action->mutable_quota_assignment_action(); - quota_assignment->mutable_assignment_time_to_live()->set_seconds(15); - auto* strategy = quota_assignment->mutable_rate_limit_strategy(); - strategy->set_blanket_rule(envoy::type::v3::RateLimitStrategy::DENY_ALL); - } - - // Send the response from RLQS server. - rlqs_stream_->sendGrpcMessage(rlqs_response); - absl::SleepFor(absl::Seconds(1)); - } - } else { - ASSERT_TRUE(response_->waitForEndStream(std::chrono::seconds(5))); - EXPECT_TRUE(response_->complete()); - EXPECT_EQ(response_->headers().getStatusValue(), "429"); - } - - cleanUp(); - } -} - TEST_P(RateLimitQuotaIntegrationTest, MultiSameRequestWithAbandonAction) { initializeConfig(); HttpIntegrationTest::initialize(); From 193b5ac83b35af4f7d3480a7fe991196f6d1e2ac Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Mon, 26 Aug 2024 16:38:36 -0500 Subject: [PATCH 45/53] mobile: Update Android proxy tests to not use mocks (#35849) This PR updates the Android proxy tests to not use mocks, which have been causing an issue for me when running the tests locally due to the bytecode mismatch. Using a real object with `shadowOf` is also the recommended approach. This PR also updates the tests to not use a deprecated `sendStickyBroadcast` method. Risk Level: low (tests only) Testing: unit tests Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a Signed-off-by: Fredy Wijaya --- ...oIntentPerformHTTPRequestUsingProxyTest.kt | 28 ++++++++++--------- ...ntentPerformHTTPSRequestBadHostnameTest.kt | 20 +++++++------ ...tPerformHTTPSRequestUsingAsyncProxyTest.kt | 28 ++++++++++--------- ...IntentPerformHTTPSRequestUsingProxyTest.kt | 28 ++++++++++--------- ...oxyPollPerformHTTPRequestUsingProxyTest.kt | 26 +++++++++-------- ...formHTTPRequestWithoutUsingPACProxyTest.kt | 26 +++++++++-------- 6 files changed, 84 insertions(+), 72 deletions(-) diff --git a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPRequestUsingProxyTest.kt b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPRequestUsingProxyTest.kt index 4e5d46c853de..6b9a559598ed 100644 --- a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPRequestUsingProxyTest.kt +++ b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPRequestUsingProxyTest.kt @@ -20,8 +20,8 @@ import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows.shadowOf // ┌──────────────────┐ // │ Envoy Proxy │ @@ -55,18 +55,20 @@ class ProxyInfoIntentPerformHTTPRequestUsingProxyTest { @Test fun `performs an HTTP request through a proxy`() { - val context = Mockito.spy(ApplicationProvider.getApplicationContext()) - val connectivityManager: ConnectivityManager = Mockito.mock(ConnectivityManager::class.java) - Mockito.doReturn(connectivityManager) - .`when`(context) - .getSystemService(Context.CONNECTIVITY_SERVICE) - Mockito.`when`(connectivityManager.defaultProxy) - .thenReturn(ProxyInfo.buildDirectProxy("127.0.0.1", httpProxyTestServer.port)) + val context = ApplicationProvider.getApplicationContext() + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager.bindProcessToNetwork(connectivityManager.activeNetwork) + shadowOf(connectivityManager) + .setProxyForNetwork( + connectivityManager.activeNetwork, + ProxyInfo.buildDirectProxy("127.0.0.1", httpProxyTestServer.port) + ) val onEngineRunningLatch = CountDownLatch(1) - val onRespondeHeadersLatch = CountDownLatch(1) + val onResponseHeadersLatch = CountDownLatch(1) - context.sendStickyBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) + context.sendBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) val builder = AndroidEngineBuilder(context) val engine = @@ -96,13 +98,13 @@ class ProxyInfoIntentPerformHTTPRequestUsingProxyTest { val status = responseHeaders.httpStatus ?: 0L assertThat(status).isEqualTo(301) assertThat(responseHeaders.value("x-proxy-response")).isEqualTo(listOf("true")) - onRespondeHeadersLatch.countDown() + onResponseHeadersLatch.countDown() } .start(Executors.newSingleThreadExecutor()) .sendHeaders(requestHeaders, true) - onRespondeHeadersLatch.await(15, TimeUnit.SECONDS) - assertThat(onRespondeHeadersLatch.count).isEqualTo(0) + onResponseHeadersLatch.await(15, TimeUnit.SECONDS) + assertThat(onResponseHeadersLatch.count).isEqualTo(0) engine.terminate() } diff --git a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestBadHostnameTest.kt b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestBadHostnameTest.kt index 1609e8699035..8cfb4591b1bb 100644 --- a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestBadHostnameTest.kt +++ b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestBadHostnameTest.kt @@ -20,8 +20,8 @@ import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows // ┌──────────────────┐ // │ Envoy Proxy │ @@ -55,18 +55,20 @@ class ProxyInfoIntentPerformHTTPSRequestBadHostnameTest { @Test fun `attempts an HTTPs request through a proxy using an async DNS resolution that fails`() { - val context = Mockito.spy(ApplicationProvider.getApplicationContext()) - val connectivityManager: ConnectivityManager = Mockito.mock(ConnectivityManager::class.java) - Mockito.doReturn(connectivityManager) - .`when`(context) - .getSystemService(Context.CONNECTIVITY_SERVICE) - Mockito.`when`(connectivityManager.defaultProxy) - .thenReturn(ProxyInfo.buildDirectProxy("loopback", httpProxyTestServer.port)) + val context = ApplicationProvider.getApplicationContext() + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager.bindProcessToNetwork(connectivityManager.activeNetwork) + Shadows.shadowOf(connectivityManager) + .setProxyForNetwork( + connectivityManager.activeNetwork, + ProxyInfo.buildDirectProxy("loopback", httpProxyTestServer.port) + ) val onEngineRunningLatch = CountDownLatch(1) val onErrorLatch = CountDownLatch(1) - context.sendStickyBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) + context.sendBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) val builder = AndroidEngineBuilder(context) val engine = diff --git a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingAsyncProxyTest.kt b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingAsyncProxyTest.kt index cfb4e84f1174..4d6b00d91c96 100644 --- a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingAsyncProxyTest.kt +++ b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingAsyncProxyTest.kt @@ -21,8 +21,8 @@ import org.junit.Before import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows // ┌──────────────────┐ // │ Envoy Proxy │ @@ -57,18 +57,20 @@ class ProxyInfoIntentPerformHTTPSRequestUsingAsyncProxyTest { @Ignore("https://github.com/envoyproxy/envoy/issues/33014") @Test fun `performs an HTTPs request through a proxy using async DNS resolution`() { - val context = Mockito.spy(ApplicationProvider.getApplicationContext()) - val connectivityManager: ConnectivityManager = Mockito.mock(ConnectivityManager::class.java) - Mockito.doReturn(connectivityManager) - .`when`(context) - .getSystemService(Context.CONNECTIVITY_SERVICE) - Mockito.`when`(connectivityManager.defaultProxy) - .thenReturn(ProxyInfo.buildDirectProxy("localhost", httpProxyTestServer.port)) + val context = ApplicationProvider.getApplicationContext() + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager.bindProcessToNetwork(connectivityManager.activeNetwork) + Shadows.shadowOf(connectivityManager) + .setProxyForNetwork( + connectivityManager.activeNetwork, + ProxyInfo.buildDirectProxy("localhost", httpProxyTestServer.port) + ) val onEngineRunningLatch = CountDownLatch(1) - val onRespondeHeadersLatch = CountDownLatch(1) + val onResponseHeadersLatch = CountDownLatch(1) - context.sendStickyBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) + context.sendBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) val builder = AndroidEngineBuilder(context) val engine = @@ -98,13 +100,13 @@ class ProxyInfoIntentPerformHTTPSRequestUsingAsyncProxyTest { val status = responseHeaders.httpStatus ?: 0L assertThat(status).isEqualTo(200) assertThat(responseHeaders.value("x-response-header-that-should-be-stripped")).isNull() - onRespondeHeadersLatch.countDown() + onResponseHeadersLatch.countDown() } .start(Executors.newSingleThreadExecutor()) .sendHeaders(requestHeaders, true) - onRespondeHeadersLatch.await(15, TimeUnit.SECONDS) - assertThat(onRespondeHeadersLatch.count).isEqualTo(0) + onResponseHeadersLatch.await(15, TimeUnit.SECONDS) + assertThat(onResponseHeadersLatch.count).isEqualTo(0) engine.terminate() } diff --git a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingProxyTest.kt b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingProxyTest.kt index c86ecc0acdd5..9350b5babd67 100644 --- a/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingProxyTest.kt +++ b/mobile/test/kotlin/integration/proxying/ProxyInfoIntentPerformHTTPSRequestUsingProxyTest.kt @@ -21,8 +21,8 @@ import org.junit.Before import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows // ┌──────────────────┐ // │ Envoy Proxy │ @@ -57,18 +57,20 @@ class ProxyInfoIntentPerformHTTPSRequestUsingProxyTest { @Ignore("https://github.com/envoyproxy/envoy/issues/33014") @Test fun `performs an HTTPs request through a proxy`() { - val context = Mockito.spy(ApplicationProvider.getApplicationContext()) - val connectivityManager: ConnectivityManager = Mockito.mock(ConnectivityManager::class.java) - Mockito.doReturn(connectivityManager) - .`when`(context) - .getSystemService(Context.CONNECTIVITY_SERVICE) - Mockito.`when`(connectivityManager.defaultProxy) - .thenReturn(ProxyInfo.buildDirectProxy("127.0.0.1", httpProxyTestServer.port)) + val context = ApplicationProvider.getApplicationContext() + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager.bindProcessToNetwork(connectivityManager.activeNetwork) + Shadows.shadowOf(connectivityManager) + .setProxyForNetwork( + connectivityManager.activeNetwork, + ProxyInfo.buildDirectProxy("127.0.0.1", httpProxyTestServer.port) + ) val onEngineRunningLatch = CountDownLatch(1) - val onRespondeHeadersLatch = CountDownLatch(1) + val onResponseHeadersLatch = CountDownLatch(1) - context.sendStickyBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) + context.sendBroadcast(Intent(Proxy.PROXY_CHANGE_ACTION)) val builder = AndroidEngineBuilder(context) val engine = @@ -98,13 +100,13 @@ class ProxyInfoIntentPerformHTTPSRequestUsingProxyTest { val status = responseHeaders.httpStatus ?: 0L assertThat(status).isEqualTo(200) assertThat(responseHeaders.value("x-response-header-that-should-be-stripped")).isNull() - onRespondeHeadersLatch.countDown() + onResponseHeadersLatch.countDown() } .start(Executors.newSingleThreadExecutor()) .sendHeaders(requestHeaders, true) - onRespondeHeadersLatch.await(15, TimeUnit.SECONDS) - assertThat(onRespondeHeadersLatch.count).isEqualTo(0) + onResponseHeadersLatch.await(15, TimeUnit.SECONDS) + assertThat(onResponseHeadersLatch.count).isEqualTo(0) engine.terminate() } diff --git a/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestUsingProxyTest.kt b/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestUsingProxyTest.kt index da3b1a7c99aa..b1613d4e11ba 100644 --- a/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestUsingProxyTest.kt +++ b/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestUsingProxyTest.kt @@ -18,8 +18,8 @@ import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows // ┌──────────────────┐ // │ Envoy Proxy │ @@ -53,16 +53,18 @@ class ProxyPollPerformHTTPRequestUsingProxyTest { @Test fun `performs an HTTP request through a proxy`() { - val context = Mockito.spy(ApplicationProvider.getApplicationContext()) - val connectivityManager: ConnectivityManager = Mockito.mock(ConnectivityManager::class.java) - Mockito.doReturn(connectivityManager) - .`when`(context) - .getSystemService(Context.CONNECTIVITY_SERVICE) - Mockito.`when`(connectivityManager.defaultProxy) - .thenReturn(ProxyInfo.buildDirectProxy("127.0.0.1", httpProxyTestServer.port)) + val context = ApplicationProvider.getApplicationContext() + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager.bindProcessToNetwork(connectivityManager.activeNetwork) + Shadows.shadowOf(connectivityManager) + .setProxyForNetwork( + connectivityManager.activeNetwork, + ProxyInfo.buildDirectProxy("127.0.0.1", httpProxyTestServer.port) + ) val onEngineRunningLatch = CountDownLatch(1) - val onRespondeHeadersLatch = CountDownLatch(1) + val onResponseHeadersLatch = CountDownLatch(1) val builder = AndroidEngineBuilder(context) val engine = @@ -92,13 +94,13 @@ class ProxyPollPerformHTTPRequestUsingProxyTest { val status = responseHeaders.httpStatus ?: 0L assertThat(status).isEqualTo(301) assertThat(responseHeaders.value("x-proxy-response")).isEqualTo(listOf("true")) - onRespondeHeadersLatch.countDown() + onResponseHeadersLatch.countDown() } .start(Executors.newSingleThreadExecutor()) .sendHeaders(requestHeaders, true) - onRespondeHeadersLatch.await(15, TimeUnit.SECONDS) - assertThat(onRespondeHeadersLatch.count).isEqualTo(0) + onResponseHeadersLatch.await(15, TimeUnit.SECONDS) + assertThat(onResponseHeadersLatch.count).isEqualTo(0) engine.terminate() } diff --git a/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestWithoutUsingPACProxyTest.kt b/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestWithoutUsingPACProxyTest.kt index 6173ce2df37d..c80206598d84 100644 --- a/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestWithoutUsingPACProxyTest.kt +++ b/mobile/test/kotlin/integration/proxying/ProxyPollPerformHTTPRequestWithoutUsingPACProxyTest.kt @@ -19,8 +19,8 @@ import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows // ┌──────────────────┐ // │ Envoy Proxy │ @@ -56,16 +56,18 @@ class ProxyPollPerformHTTPRequestWithoutUsingPACProxyTest { @Test fun `performs an HTTP request through a proxy`() { - val context = Mockito.spy(ApplicationProvider.getApplicationContext()) - val connectivityManager: ConnectivityManager = Mockito.mock(ConnectivityManager::class.java) - Mockito.doReturn(connectivityManager) - .`when`(context) - .getSystemService(Context.CONNECTIVITY_SERVICE) - Mockito.`when`(connectivityManager.defaultProxy) - .thenReturn(ProxyInfo.buildPacProxy(Uri.parse("https://example.com"))) + val context = ApplicationProvider.getApplicationContext() + val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager.bindProcessToNetwork(connectivityManager.activeNetwork) + Shadows.shadowOf(connectivityManager) + .setProxyForNetwork( + connectivityManager.activeNetwork, + ProxyInfo.buildPacProxy(Uri.parse("https://example.com")) + ) val onEngineRunningLatch = CountDownLatch(1) - val onRespondeHeadersLatch = CountDownLatch(1) + val onResponseHeadersLatch = CountDownLatch(1) val builder = AndroidEngineBuilder(context) val engine = @@ -95,13 +97,13 @@ class ProxyPollPerformHTTPRequestWithoutUsingPACProxyTest { val status = responseHeaders.httpStatus ?: 0L assertThat(status).isEqualTo(301) assertThat(responseHeaders.value("x-proxy-response")).isNull() - onRespondeHeadersLatch.countDown() + onResponseHeadersLatch.countDown() } .start(Executors.newSingleThreadExecutor()) .sendHeaders(requestHeaders, true) - onRespondeHeadersLatch.await(15, TimeUnit.SECONDS) - assertThat(onRespondeHeadersLatch.count).isEqualTo(0) + onResponseHeadersLatch.await(15, TimeUnit.SECONDS) + assertThat(onResponseHeadersLatch.count).isEqualTo(0) engine.terminate() } From 67b69c9038402b88953a2ab171ae38cab5cb23ab Mon Sep 17 00:00:00 2001 From: Diogo Barbosa Date: Tue, 27 Aug 2024 05:11:43 +0200 Subject: [PATCH 46/53] redis_proxy: add support for external authentication (#35643) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit resolves #35673 ## PR overview Redis proxy users may want to create advanced authentication methods. For example, the official [Azure SDK extension for Redis](https://github.com/Azure/Microsoft.Azure.StackExchangeRedis) allows to authenticate to a Redis server using Microsoft Entra ID token-based authentication, by passing a token in the password argument of the `AUTH` command periodically, based on token expiration. This PR introduces a way to support external authentication via a gRPC service with additional support for expiry of such authentication (e.g. for token-based authentication). This way we keep it extensible for **any** advanced authentication methods users might want to develop. ### The reviewer may ask: Why not use the _ext_authz_ filter? The cost/latency impact by using the _ext_authz_ filter is much bigger than the proposed design. That's because instead of being called on every request, the current design only calls the external dependency on **AUTH** commands. Not only that, but also we would have to decode the Redis protocol twice, if we used a separate filter. --- Risk Level: Medium (small optional feature added to existing filter) Testing: ✅ - Unit Tests - Integration Tests - Manual Testing ![image](https://github.com/user-attachments/assets/3caab358-7c37-446d-8e12-bff9c1442948) - Also, we are already using the signed _-dev_ build on a test AKS cluster Docs Changes: ✅ - Proto docs ![image](https://github.com/user-attachments/assets/1432114f-ff93-431a-90ad-1c1262989e8c) - Updated authentication-related information on the Redis protocol page. Release Notes: ✅ --------- Signed-off-by: Diogo Barbosa Signed-off-by: Diogo Barbosa --- api/BUILD | 1 + .../network/redis_proxy/v3/redis_proxy.proto | 31 +- api/envoy/service/redis_auth/v3/BUILD | 10 + .../redis_auth/v3/redis_external_auth.proto | 47 ++ api/versioning/BUILD | 1 + changelogs/current.yaml | 4 + docs/root/api-v3/service/service.rst | 1 + .../arch_overview/other_protocols/redis.rst | 12 +- .../filters/network/redis_proxy/BUILD | 13 + .../filters/network/redis_proxy/config.cc | 32 +- .../network/redis_proxy/external_auth.cc | 109 +++++ .../network/redis_proxy/external_auth.h | 146 +++++++ .../network/redis_proxy/proxy_filter.cc | 93 +++- .../network/redis_proxy/proxy_filter.h | 27 +- .../filters/network/redis_proxy/BUILD | 16 + .../network/redis_proxy/config_test.cc | 30 ++ .../network/redis_proxy/external_auth_test.cc | 199 +++++++++ .../filters/network/redis_proxy/mocks.cc | 9 + .../filters/network/redis_proxy/mocks.h | 34 ++ .../network/redis_proxy/proxy_filter_test.cc | 403 +++++++++++++++++- .../redis_proxy_integration_test.cc | 184 +++++++- 21 files changed, 1369 insertions(+), 33 deletions(-) create mode 100644 api/envoy/service/redis_auth/v3/BUILD create mode 100644 api/envoy/service/redis_auth/v3/redis_external_auth.proto create mode 100644 source/extensions/filters/network/redis_proxy/external_auth.cc create mode 100644 source/extensions/filters/network/redis_proxy/external_auth.h create mode 100644 test/extensions/filters/network/redis_proxy/external_auth_test.cc diff --git a/api/BUILD b/api/BUILD index 931fbea9c428..cae22a8d0918 100644 --- a/api/BUILD +++ b/api/BUILD @@ -360,6 +360,7 @@ proto_library( "//envoy/service/metrics/v3:pkg", "//envoy/service/rate_limit_quota/v3:pkg", "//envoy/service/ratelimit/v3:pkg", + "//envoy/service/redis_auth/v3:pkg", "//envoy/service/route/v3:pkg", "//envoy/service/runtime/v3:pkg", "//envoy/service/secret/v3:pkg", diff --git a/api/envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.proto b/api/envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.proto index 28e351fb0412..19ab3b45325e 100644 --- a/api/envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.proto +++ b/api/envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package envoy.extensions.filters.network.redis_proxy.v3; import "envoy/config/core/v3/base.proto"; +import "envoy/config/core/v3/grpc_service.proto"; import "envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.proto"; import "google/protobuf/duration.proto"; @@ -25,7 +26,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Redis Proxy :ref:`configuration overview `. // [#extension: envoy.filters.network.redis_proxy] -// [#next-free-field: 10] +// [#next-free-field: 11] message RedisProxy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.network.redis_proxy.v2.RedisProxy"; @@ -353,6 +354,15 @@ message RedisProxy { // client. If an AUTH command is received when the password is not set, then an "ERR Client sent // AUTH, but no ACL is set" error will be returned. config.core.v3.DataSource downstream_auth_username = 7 [(udpa.annotations.sensitive) = true]; + + // External authentication configuration. If set, instead of validating username and password against ``downstream_auth_username`` and ``downstream_auth_password``, + // the filter will call an external gRPC service to authenticate the client. + // A typical usage of this feature is for situations where the password is a one-time token that needs to be validated against a remote service, like a sidecar. + // Expiration is also supported, which will disable any further commands from the client after the expiration time, unless a new AUTH command is received and the external auth service returns a new expiration time. + // If the external auth service returns an error, authentication is considered failed. + // If this setting is set together with ``downstream_auth_username`` and ``downstream_auth_password``, the external auth service will be source of truth, but those fields will still be used for downstream authentication to the cluster. + // The API is defined by :ref:`RedisProxyExternalAuthRequest `. + RedisExternalAuthProvider external_auth_provider = 10; } // RedisProtocolOptions specifies Redis upstream protocol options. This object is used in @@ -370,3 +380,22 @@ message RedisProtocolOptions { // ``_ in the server's configuration file. config.core.v3.DataSource auth_username = 2 [(udpa.annotations.sensitive) = true]; } + +// RedisExternalAuthProvider specifies a gRPC service that can be used to authenticate Redis clients. +// This service will be called every time an AUTH command is received from a client. +// If the service returns an error, authentication is considered failed. +// If the service returns a success, the client is considered authenticated. +// The service can also return an expiration timestamp, which will be used to disable any further +// commands from the client after it passes, unless a new AUTH command is received and the +// external auth service returns a new expiration timestamp. +message RedisExternalAuthProvider { + // External auth gRPC service configuration. + // It will be called every time an AUTH command is received from a client. + config.core.v3.GrpcService grpc_service = 1; + + // If set to true, the filter will expect an expiration timestamp in the response from the external + // auth service. This timestamp will be used to disable any further commands from the client after + // the expiration time, unless a new AUTH command is received and the external auth service returns + // a new expiration timestamp. + bool enable_auth_expiration = 2; +} diff --git a/api/envoy/service/redis_auth/v3/BUILD b/api/envoy/service/redis_auth/v3/BUILD new file mode 100644 index 000000000000..1e4f23a124a6 --- /dev/null +++ b/api/envoy/service/redis_auth/v3/BUILD @@ -0,0 +1,10 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + has_services = True, + deps = ["@com_github_cncf_xds//udpa/annotations:pkg"], +) diff --git a/api/envoy/service/redis_auth/v3/redis_external_auth.proto b/api/envoy/service/redis_auth/v3/redis_external_auth.proto new file mode 100644 index 000000000000..52bc3bc03290 --- /dev/null +++ b/api/envoy/service/redis_auth/v3/redis_external_auth.proto @@ -0,0 +1,47 @@ +syntax = "proto3"; + +package envoy.service.redis_auth.v3; + +import "google/protobuf/timestamp.proto"; +import "google/rpc/status.proto"; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.service.redis_auth.v3"; +option java_outer_classname = "RedisExternalAuthProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/service/redis_auth/v3;redis_authv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Redis external authentication service] + +// The messages used by the redis_proxy filter when performing external authentication. + +// A generic interface for performing external password authentication on incoming AUTH commands. +service RedisProxyExternalAuth { + // Performs authentication check based on the data sent with the AUTH request. + // Returns either an OK status or an error status. + rpc Authenticate(RedisProxyExternalAuthRequest) returns (RedisProxyExternalAuthResponse) { + } +} + +message RedisProxyExternalAuthRequest { + // Username, if applicable. Otherwise, empty. + string username = 1; + + // Password sent with the AUTH command. + string password = 2; +} + +message RedisProxyExternalAuthResponse { + // Status of the authentication check. + google.rpc.Status status = 1; + + // Optional expiration time for the authentication. + // If set, the authentication will be valid until this time. + // If not set, the authentication will be valid indefinitely. + google.protobuf.Timestamp expiration = 2; + + // Optional message to be sent back to the client. + string message = 3; +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index ea5e0db90006..bb27ffaea41d 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -299,6 +299,7 @@ proto_library( "//envoy/service/metrics/v3:pkg", "//envoy/service/rate_limit_quota/v3:pkg", "//envoy/service/ratelimit/v3:pkg", + "//envoy/service/redis_auth/v3:pkg", "//envoy/service/route/v3:pkg", "//envoy/service/runtime/v3:pkg", "//envoy/service/secret/v3:pkg", diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 260262fcccb6..93ba386848d8 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -252,5 +252,9 @@ new_features: - area: geoip change: | Added ``envoy.reloadable_features.mmdb_files_reload_enabled`` runtime flag that enables reload of mmdb files by default. +- area: redis_proxy + change: | + Added :ref:`external_auth_provider ` to support + external authentication for redis proxy. deprecated: diff --git a/docs/root/api-v3/service/service.rst b/docs/root/api-v3/service/service.rst index 8752c3242aa6..fde46319f5b7 100644 --- a/docs/root/api-v3/service/service.rst +++ b/docs/root/api-v3/service/service.rst @@ -19,3 +19,4 @@ Services ../config/tap/v3/* tap/v3/* trace/v3/* + redis_auth/v3/* diff --git a/docs/root/intro/arch_overview/other_protocols/redis.rst b/docs/root/intro/arch_overview/other_protocols/redis.rst index 6fb54f1a834b..afe9a50cf66e 100644 --- a/docs/root/intro/arch_overview/other_protocols/redis.rst +++ b/docs/root/intro/arch_overview/other_protocols/redis.rst @@ -130,8 +130,11 @@ Use pipelining wherever possible for the best performance. At the command level, Envoy only supports commands that can be reliably hashed to a server. AUTH, PING and ECHO are the only exceptions. AUTH is processed locally by Envoy if a downstream password has been configured, and no other commands will be processed until authentication is successful when a password has been -configured. Envoy will transparently issue AUTH commands upon connecting to upstream servers, if upstream -authentication passwords are configured for the cluster. Envoy responds to PING immediately with PONG. +configured. If an external authentication provider is set, Envoy will instead send the authentication arguments +to an external service and act according to the authentication response. If a downstream password is set together +with external authentication, the validation will be done still externally and the downstream password used for +upstream authentication. Envoy will transparently issue AUTH commands upon connecting to upstream servers, +if upstream authentication passwords are configured for the cluster. Envoy responds to PING immediately with PONG. Arguments to PING are not allowed. Envoy responds to ECHO immediately with the command argument. All other supported commands must contain a key. Supported commands are functionally identical to the original Redis command except possibly in failure scenarios. @@ -305,10 +308,11 @@ Envoy can also generate its own errors in response to the client. wrong number of arguments for command, "Certain commands check in Envoy that the number of arguments is correct." "NOAUTH Authentication required.", "The command was rejected because a downstream authentication - password has been set and the client has not successfully authenticated." + password or external authentication have been set and the client has not successfully authenticated." ERR invalid password, "The authentication command failed due to an invalid password." + ERR , "The authentication command failed on the external auth provider." "ERR Client sent AUTH, but no password is set", "An authentication command was received, but no - downstream authentication password has been configured." + downstream authentication password or external authentication provider have been configured." In the case of MGET, each individual key that cannot be fetched will generate an error response. diff --git a/source/extensions/filters/network/redis_proxy/BUILD b/source/extensions/filters/network/redis_proxy/BUILD index b75132be1ddc..39d05785bfde 100644 --- a/source/extensions/filters/network/redis_proxy/BUILD +++ b/source/extensions/filters/network/redis_proxy/BUILD @@ -105,12 +105,25 @@ envoy_cc_library( ], ) +envoy_cc_library( + name = "external_auth_lib", + srcs = ["external_auth.cc"], + hdrs = ["external_auth.h"], + deps = [ + ":command_splitter_lib", + "//source/common/grpc:async_client_lib", + "//source/common/grpc:typed_async_client_lib", + "@envoy_api//envoy/service/redis_auth/v3:pkg_cc_proto", + ], +) + envoy_cc_library( name = "proxy_filter_lib", srcs = ["proxy_filter.cc"], hdrs = ["proxy_filter.h"], deps = [ ":command_splitter_interface", + ":external_auth_lib", "//envoy/network:drain_decision_interface", "//envoy/network:filter_interface", "//envoy/upstream:cluster_manager_interface", diff --git a/source/extensions/filters/network/redis_proxy/config.cc b/source/extensions/filters/network/redis_proxy/config.cc index 4cf0ac6c42b4..ebae3bee724a 100644 --- a/source/extensions/filters/network/redis_proxy/config.cc +++ b/source/extensions/filters/network/redis_proxy/config.cc @@ -1,5 +1,6 @@ #include "source/extensions/filters/network/redis_proxy/config.h" +#include "envoy/config/core/v3/grpc_service.pb.h" #include "envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.pb.h" #include "envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.pb.validate.h" @@ -52,7 +53,7 @@ Network::FilterFactoryCb RedisProxyFilterConfigFactory::createFilterFactoryFromP auto filter_config = std::make_shared( proto_config, context.scope(), context.drainDecision(), server_context.runtime(), - server_context.api(), cache_manager_factory); + server_context.api(), context.serverFactoryContext().timeSource(), cache_manager_factory); envoy::extensions::filters::network::redis_proxy::v3::RedisProxy::PrefixRoutes prefix_routes( proto_config.prefix_routes()); @@ -94,11 +95,32 @@ Network::FilterFactoryCb RedisProxyFilterConfigFactory::createFilterFactoryFromP std::make_shared( std::move(router), context.scope(), filter_config->stat_prefix_, server_context.timeSource(), proto_config.latency_in_micros(), std::move(fault_manager)); - return [splitter, filter_config](Network::FilterManager& filter_manager) -> void { - Common::Redis::DecoderFactoryImpl factory; + + auto has_external_auth_provider_ = proto_config.has_external_auth_provider(); + auto grpc_service = proto_config.external_auth_provider().grpc_service(); + auto timeout_ms = PROTOBUF_GET_MS_OR_DEFAULT(grpc_service, timeout, 200); + + return [has_external_auth_provider_, grpc_service, &context, splitter, filter_config, + timeout_ms](Network::FilterManager& filter_manager) -> void { + Common::Redis::DecoderFactoryImpl decoder_factory; + + ExternalAuth::ExternalAuthClientPtr&& auth_client{nullptr}; + if (has_external_auth_provider_) { + auto auth_client_factory_or_error = + context.serverFactoryContext() + .clusterManager() + .grpcAsyncClientManager() + .factoryForGrpcService(grpc_service, context.scope(), true); + THROW_IF_STATUS_NOT_OK(auth_client_factory_or_error, throw); + + auth_client = std::make_unique( + auth_client_factory_or_error.value()->createUncachedRawAsyncClient(), + std::chrono::milliseconds(timeout_ms)); + } + filter_manager.addReadFilter(std::make_shared( - factory, Common::Redis::EncoderPtr{new Common::Redis::EncoderImpl()}, *splitter, - filter_config)); + decoder_factory, Common::Redis::EncoderPtr{new Common::Redis::EncoderImpl()}, *splitter, + filter_config, std::move(auth_client))); }; } diff --git a/source/extensions/filters/network/redis_proxy/external_auth.cc b/source/extensions/filters/network/redis_proxy/external_auth.cc new file mode 100644 index 000000000000..e262893ad238 --- /dev/null +++ b/source/extensions/filters/network/redis_proxy/external_auth.cc @@ -0,0 +1,109 @@ +#include "source/extensions/filters/network/redis_proxy/external_auth.h" + +#include "source/common/grpc/async_client_impl.h" + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace RedisProxy { +namespace ExternalAuth { + +GrpcExternalAuthClient::GrpcExternalAuthClient( + const Grpc::RawAsyncClientSharedPtr& async_client, + const absl::optional& timeout) + : async_client_(async_client), timeout_(timeout), + service_method_(*Protobuf::DescriptorPool::generated_pool()->FindMethodByName( + "envoy.service.redis_auth.v3.RedisProxyExternalAuth.Authenticate")) {} + +// Make sure the request is cancelled when the client is destroyed. +GrpcExternalAuthClient::~GrpcExternalAuthClient() { + ASSERT(!callback_); + ASSERT(!pending_request_); +} + +// Cancel method. Called when a request should be cancelled (e.g. connection was closed). +void GrpcExternalAuthClient::cancel() { + // Make sure the callback and the pending redis request are not null before cancelling the + // request. + ASSERT(callback_ != nullptr); + ASSERT(pending_request_ != nullptr); + request_->cancel(); + callback_ = nullptr; + pending_request_ = nullptr; +} + +// Authenticate method. Called to initiate an asynchronous request to the external authentication +// server. +void GrpcExternalAuthClient::authenticateExternal(AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request, + const StreamInfo::StreamInfo& stream_info, + std::string username, std::string password) { + // Make sure the callback and the pending redis request are null before initiating a new request. + ASSERT(callback_ == nullptr); + ASSERT(pending_request_ == nullptr); + callback_ = &callback; + pending_request_ = &pending_request; + + Http::AsyncClient::RequestOptions options; + options.setTimeout(timeout_); + options.setParentContext(Http::AsyncClient::ParentContext{&stream_info}); + + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest req; + req.set_username(username); + req.set_password(password); + + ENVOY_LOG(trace, "Sending request for external Redis authentication..."); + request_ = + async_client_->send(service_method_, req, *this, Tracing::NullSpan::instance(), options); +} + +// Callback method called when the request is successful. +void GrpcExternalAuthClient::onSuccess( + std::unique_ptr&& response, + Tracing::Span& span) { + ENVOY_LOG(trace, "Received response for external Redis authentication. Status: {}", + response->status().code()); + + AuthenticateResponsePtr auth_response = + std::make_unique(AuthenticateResponse{}); + auth_response->message = response->message(); + if (response->status().code() == Grpc::Status::WellKnownGrpcStatus::Ok) { + span.setTag(TracingConstants::get().TraceStatus, TracingConstants::get().TraceOk); + auth_response->status = AuthenticationRequestStatus::Authorized; + auth_response->expiration = response->expiration(); + } else if (response->status().code() == Grpc::Status::WellKnownGrpcStatus::PermissionDenied || + response->status().code() == Grpc::Status::WellKnownGrpcStatus::Unauthenticated) { + span.setTag(TracingConstants::get().TraceStatus, TracingConstants::get().TraceUnauthorized); + auth_response->status = AuthenticationRequestStatus::Unauthorized; + } else { + span.setTag(TracingConstants::get().TraceStatus, TracingConstants::get().TraceError); + auth_response->status = AuthenticationRequestStatus::Error; + auth_response->message = response->message(); + } + + callback_->onAuthenticateExternal(*pending_request_, std::move(auth_response)); + callback_ = nullptr; + pending_request_ = nullptr; +} + +// Callback method called when the request fails. +void GrpcExternalAuthClient::onFailure(Grpc::Status::GrpcStatus status, const std::string& message, + Tracing::Span& span) { + ENVOY_LOG(trace, "CheckRequest call failed with status: {}", + Grpc::Utility::grpcStatusToString(status)); + ASSERT(status != Grpc::Status::WellKnownGrpcStatus::Ok); + span.setTag(TracingConstants::get().TraceStatus, TracingConstants::get().TraceError); + AuthenticateResponsePtr auth_response = + std::make_unique(AuthenticateResponse{}); + auth_response->status = AuthenticationRequestStatus::Error; + auth_response->message = message; + callback_->onAuthenticateExternal(*pending_request_, std::move(auth_response)); + callback_ = nullptr; + pending_request_ = nullptr; +} + +} // namespace ExternalAuth +} // namespace RedisProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/network/redis_proxy/external_auth.h b/source/extensions/filters/network/redis_proxy/external_auth.h new file mode 100644 index 000000000000..dc37148c360e --- /dev/null +++ b/source/extensions/filters/network/redis_proxy/external_auth.h @@ -0,0 +1,146 @@ +#pragma once + +#include + +#include "envoy/grpc/async_client.h" +#include "envoy/service/redis_auth/v3/redis_external_auth.pb.h" + +#include "source/common/grpc/typed_async_client.h" +#include "source/common/protobuf/protobuf.h" + +#include "command_splitter.h" + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace RedisProxy { +namespace ExternalAuth { + +/** + * Constant values used for tracing metadata. + */ +struct TracingConstantValues { + const std::string TraceStatus = "redis_auth_status"; + const std::string TraceUnauthorized = "redis_auth_unauthorized"; + const std::string TraceOk = "redis_auth_ok"; + const std::string TraceError = "redis_auth_error"; +}; + +using TracingConstants = ConstSingleton; + +/** + * Represents the status of an authentication request. + */ +enum class AuthenticationRequestStatus { + Authorized, + Unauthorized, + Error, +}; + +/** + * Represents the response to an authenticate() call. + */ +struct AuthenticateResponse { + // The status of the authentication request. + AuthenticationRequestStatus status; + + // The message returned by the authentication server. + std::string message; + + // The expiration time of the authentication. + ProtobufWkt::Timestamp expiration; +}; + +using AuthenticateResponsePtr = std::unique_ptr; + +/** + * Async callback for authenticate() calls. + */ +class AuthenticateCallback { +public: + virtual ~AuthenticateCallback() = default; + + /** + * Called when the authenticate request is complete. The resulting AuthenticateResponsePtr is + * supplied. + */ + virtual void onAuthenticateExternal(CommandSplitter::SplitCallbacks& request, + AuthenticateResponsePtr&& response) PURE; +}; + +using GrpcExternalAuthClientAsyncCallbacks = + Grpc::AsyncRequestCallbacks; + +/** + * External authentication client. + */ +class ExternalAuthClient { +public: + virtual ~ExternalAuthClient() = default; + + /** + * Cancel an ongoing request. This is necessary so that we avoid callbacks being called + * after the connection has been closed. + */ + virtual void cancel() PURE; + + /** + * Authenticates a Redis AUTH command. + * @param callback supplies the callback to invoke when the authentication is complete. + * @param pending_request the pending request to respond to. + * @param stream_info supplies the stream info for the request. + * @param username supplies the username. (optional, can be empty) + * @param password supplies the password. + */ + virtual void authenticateExternal(AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request, + const StreamInfo::StreamInfo& stream_info, std::string username, + std::string password) PURE; +}; + +using ExternalAuthClientPtr = std::unique_ptr; + +/** + * External authentication client implementation on gRPC. + */ +class GrpcExternalAuthClient : public GrpcExternalAuthClientAsyncCallbacks, + public Logger::Loggable, + public ExternalAuthClient { +public: + GrpcExternalAuthClient(const Grpc::RawAsyncClientSharedPtr& async_client, + const absl::optional& timeout); + ~GrpcExternalAuthClient() override; + + void cancel() override; + + void authenticateExternal(AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request, + const StreamInfo::StreamInfo& stream_info, std::string username, + std::string password) override; + + // Grpc::AsyncRequestCallbacks + void onCreateInitialMetadata(Http::RequestHeaderMap&) override {} + void onSuccess( + std::unique_ptr&& response, + Tracing::Span& span) override; + void onFailure(Grpc::Status::GrpcStatus status, const std::string& message, + Tracing::Span& span) override; + +private: + Grpc::AsyncClient + async_client_; + Grpc::AsyncRequest* request_{}; + absl::optional timeout_; + AuthenticateCallback* callback_{}; + CommandSplitter::SplitCallbacks* pending_request_{}; + const Protobuf::MethodDescriptor& service_method_; +}; + +using GrpcExternalAuthClientPtr = std::unique_ptr; + +} // namespace ExternalAuth +} // namespace RedisProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/network/redis_proxy/proxy_filter.cc b/source/extensions/filters/network/redis_proxy/proxy_filter.cc index 3426239991cd..1bfa1c07a158 100644 --- a/source/extensions/filters/network/redis_proxy/proxy_filter.cc +++ b/source/extensions/filters/network/redis_proxy/proxy_filter.cc @@ -19,14 +19,18 @@ namespace RedisProxy { ProxyFilterConfig::ProxyFilterConfig( const envoy::extensions::filters::network::redis_proxy::v3::RedisProxy& config, Stats::Scope& scope, const Network::DrainDecision& drain_decision, Runtime::Loader& runtime, - Api::Api& api, + Api::Api& api, TimeSource& time_source, Extensions::Common::DynamicForwardProxy::DnsCacheManagerFactory& cache_manager_factory) : drain_decision_(drain_decision), runtime_(runtime), stat_prefix_(fmt::format("redis.{}.", config.stat_prefix())), stats_(generateStats(stat_prefix_, scope)), downstream_auth_username_(THROW_OR_RETURN_VALUE( Config::DataSource::read(config.downstream_auth_username(), true, api), std::string)), - dns_cache_manager_(cache_manager_factory.get()), dns_cache_(getCache(config)) { + external_auth_enabled_(config.has_external_auth_provider()), + external_auth_expiration_enabled_(external_auth_enabled_ && + config.external_auth_provider().enable_auth_expiration()), + dns_cache_manager_(cache_manager_factory.get()), dns_cache_(getCache(config)), + time_source_(time_source) { if (config.settings().enable_redirection() && !config.settings().has_dns_cache_config()) { ENVOY_LOG(warn, "redirections without DNS lookups enabled might cause client errors, set the " @@ -70,14 +74,20 @@ ProxyStats ProxyFilterConfig::generateStats(const std::string& prefix, Stats::Sc ProxyFilter::ProxyFilter(Common::Redis::DecoderFactory& factory, Common::Redis::EncoderPtr&& encoder, CommandSplitter::Instance& splitter, - ProxyFilterConfigSharedPtr config) + ProxyFilterConfigSharedPtr config, + ExternalAuth::ExternalAuthClientPtr&& auth_client) : decoder_(factory.create(*this)), encoder_(std::move(encoder)), splitter_(splitter), config_(config), transaction_(this) { config_->stats_.downstream_cx_total_.inc(); config_->stats_.downstream_cx_active_.inc(); - connection_allowed_ = - config_->downstream_auth_username_.empty() && config_->downstream_auth_passwords_.empty(); + connection_allowed_ = config_->downstream_auth_username_.empty() && + config_->downstream_auth_passwords_.empty() && + !config_->external_auth_enabled_; connection_quit_ = false; + external_auth_call_status_ = ExternalAuthCallStatus::Ready; + if (auth_client != nullptr) { + auth_client_ = std::move(auth_client); + } } ProxyFilter::~ProxyFilter() { @@ -122,6 +132,10 @@ void ProxyFilter::onEvent(Network::ConnectionEvent event) { pending_requests_.pop_front(); } transaction_.close(); + + if (external_auth_call_status_ == ExternalAuthCallStatus::Pending) { + auth_client_->cancel(); + } } } @@ -133,7 +147,62 @@ void ProxyFilter::onQuit(PendingRequest& request) { request.onResponse(std::move(response)); } +bool ProxyFilter::connectionAllowed() { + // Check for external auth expiration. + if (connection_allowed_ && config_->external_auth_expiration_enabled_) { + const auto now_epoch = config_->timeSource().systemTime().time_since_epoch().count(); + if (now_epoch > external_auth_expiration_epoch_) { + ENVOY_LOG(info, "Redis external authentication expired. Disallowing further commands."); + connection_allowed_ = false; + } + } + + return connection_allowed_; +} + +void ProxyFilter::onAuthenticateExternal(CommandSplitter::SplitCallbacks& request, + ExternalAuth::AuthenticateResponsePtr&& response) { + Common::Redis::RespValuePtr redis_response{new Common::Redis::RespValue()}; + + if (response->status == ExternalAuth::AuthenticationRequestStatus::Authorized) { + redis_response->type(Common::Redis::RespType::SimpleString); + redis_response->asString() = "OK"; + connection_allowed_ = true; + + if (config_->external_auth_expiration_enabled_) { + external_auth_expiration_epoch_ = response->expiration.seconds() * 1000000; + } + } else if (response->status == ExternalAuth::AuthenticationRequestStatus::Unauthorized) { + redis_response->type(Common::Redis::RespType::Error); + std::string message = response->message.empty() ? "unauthorized" : response->message; + redis_response->asString() = fmt::format("ERR {}", message); + connection_allowed_ = false; + } else { + redis_response->type(Common::Redis::RespType::Error); + redis_response->asString() = "ERR external authentication failed"; + ENVOY_LOG(error, "Redis external authentication failed: {}", response->message); + } + + external_auth_call_status_ = ExternalAuthCallStatus::Ready; + + request.onResponse(std::move(redis_response)); +} + void ProxyFilter::onAuth(PendingRequest& request, const std::string& password) { + if (config_->external_auth_enabled_) { + if (external_auth_call_status_ == ExternalAuthCallStatus::Ready) { + auth_client_->authenticateExternal(*this, request, callbacks_->connection().streamInfo(), + EMPTY_STRING, password); + external_auth_call_status_ = ExternalAuthCallStatus::Pending; + } else { + Common::Redis::RespValuePtr response{new Common::Redis::RespValue()}; + response->type(Common::Redis::RespType::Error); + response->asString() = "ERR an existing authentication request is pending"; + request.onResponse(std::move(response)); + } + return; + } + Common::Redis::RespValuePtr response{new Common::Redis::RespValue()}; if (config_->downstream_auth_passwords_.empty()) { response->type(Common::Redis::RespType::Error); @@ -152,6 +221,20 @@ void ProxyFilter::onAuth(PendingRequest& request, const std::string& password) { void ProxyFilter::onAuth(PendingRequest& request, const std::string& username, const std::string& password) { + if (config_->external_auth_enabled_) { + if (external_auth_call_status_ == ExternalAuthCallStatus::Ready) { + auth_client_->authenticateExternal(*this, request, callbacks_->connection().streamInfo(), + username, password); + external_auth_call_status_ = ExternalAuthCallStatus::Pending; + } else { + Common::Redis::RespValuePtr response{new Common::Redis::RespValue()}; + response->type(Common::Redis::RespType::Error); + response->asString() = "ERR an existing authentication request is pending"; + request.onResponse(std::move(response)); + } + return; + } + Common::Redis::RespValuePtr response{new Common::Redis::RespValue()}; if (config_->downstream_auth_username_.empty() && config_->downstream_auth_passwords_.empty()) { response->type(Common::Redis::RespType::Error); diff --git a/source/extensions/filters/network/redis_proxy/proxy_filter.h b/source/extensions/filters/network/redis_proxy/proxy_filter.h index d27968ebbf74..0f9dc8d1369c 100644 --- a/source/extensions/filters/network/redis_proxy/proxy_filter.h +++ b/source/extensions/filters/network/redis_proxy/proxy_filter.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -12,9 +14,11 @@ #include "envoy/upstream/cluster_manager.h" #include "source/common/buffer/buffer_impl.h" +#include "source/common/event/real_time_system.h" #include "source/extensions/common/dynamic_forward_proxy/dns_cache.h" #include "source/extensions/filters/network/common/redis/codec.h" #include "source/extensions/filters/network/redis_proxy/command_splitter.h" +#include "source/extensions/filters/network/redis_proxy/external_auth.h" namespace Envoy { namespace Extensions { @@ -51,7 +55,7 @@ class ProxyFilterConfig : public Logger::Loggable { ProxyFilterConfig( const envoy::extensions::filters::network::redis_proxy::v3::RedisProxy& config, Stats::Scope& scope, const Network::DrainDecision& drain_decision, Runtime::Loader& runtime, - Api::Api& api, + Api::Api& api, TimeSource& time_source, Extensions::Common::DynamicForwardProxy::DnsCacheManagerFactory& cache_manager_factory); const Network::DrainDecision& drain_decision_; @@ -61,6 +65,9 @@ class ProxyFilterConfig : public Logger::Loggable { ProxyStats stats_; const std::string downstream_auth_username_; std::vector downstream_auth_passwords_; + TimeSource& timeSource() const { return time_source_; }; + const bool external_auth_enabled_; + const bool external_auth_expiration_enabled_; // DNS cache used for ASK/MOVED responses. const Extensions::Common::DynamicForwardProxy::DnsCacheManagerSharedPtr dns_cache_manager_; @@ -70,6 +77,7 @@ class ProxyFilterConfig : public Logger::Loggable { static ProxyStats generateStats(const std::string& prefix, Stats::Scope& scope); Extensions::Common::DynamicForwardProxy::DnsCacheSharedPtr getCache(const envoy::extensions::filters::network::redis_proxy::v3::RedisProxy& config); + TimeSource& time_source_; }; using ProxyFilterConfigSharedPtr = std::shared_ptr; @@ -81,10 +89,12 @@ using ProxyFilterConfigSharedPtr = std::shared_ptr; class ProxyFilter : public Network::ReadFilter, public Common::Redis::DecoderCallbacks, public Network::ConnectionCallbacks, - public Logger::Loggable { + public Logger::Loggable, + public ExternalAuth::AuthenticateCallback { public: ProxyFilter(Common::Redis::DecoderFactory& factory, Common::Redis::EncoderPtr&& encoder, - CommandSplitter::Instance& splitter, ProxyFilterConfigSharedPtr config); + CommandSplitter::Instance& splitter, ProxyFilterConfigSharedPtr config, + ExternalAuth::ExternalAuthClientPtr&& auth_client); ~ProxyFilter() override; // Network::ReadFilter @@ -100,13 +110,19 @@ class ProxyFilter : public Network::ReadFilter, // Common::Redis::DecoderCallbacks void onRespValue(Common::Redis::RespValuePtr&& value) override; - bool connectionAllowed() { return connection_allowed_; } + // AuthenticateCallback + void onAuthenticateExternal(CommandSplitter::SplitCallbacks& request, + ExternalAuth::AuthenticateResponsePtr&& response) override; + + bool connectionAllowed(); Common::Redis::Client::Transaction& transaction() { return transaction_; } private: friend class RedisProxyFilterTest; + enum class ExternalAuthCallStatus { Pending, Ready }; + struct PendingRequest : public CommandSplitter::SplitCallbacks { PendingRequest(ProxyFilter& parent); ~PendingRequest() override; @@ -145,6 +161,9 @@ class ProxyFilter : public Network::ReadFilter, bool connection_allowed_; Common::Redis::Client::Transaction transaction_; bool connection_quit_; + ExternalAuth::ExternalAuthClientPtr auth_client_; + ExternalAuthCallStatus external_auth_call_status_; + long external_auth_expiration_epoch_; }; } // namespace RedisProxy diff --git a/test/extensions/filters/network/redis_proxy/BUILD b/test/extensions/filters/network/redis_proxy/BUILD index c746d5a2c426..32c3bd39ed90 100644 --- a/test/extensions/filters/network/redis_proxy/BUILD +++ b/test/extensions/filters/network/redis_proxy/BUILD @@ -82,11 +82,25 @@ envoy_extension_cc_test( "//test/mocks:common_lib", "//test/mocks/api:api_mocks", "//test/mocks/network:network_mocks", + "//test/mocks/server:factory_context_mocks", "//test/test_common:utility_lib", "@envoy_api//envoy/extensions/filters/network/redis_proxy/v3:pkg_cc_proto", ], ) +envoy_extension_cc_test( + name = "external_auth_test", + srcs = ["external_auth_test.cc"], + extension_names = ["envoy.filters.network.redis_proxy"], + deps = [ + ":redis_mocks", + "//source/extensions/filters/network/redis_proxy:external_auth_lib", + "//test/mocks/grpc:grpc_mocks", + "//test/mocks/tracing:tracing_mocks", + "@envoy_api//envoy/service/redis_auth/v3:pkg_cc_proto", + ], +) + envoy_cc_mock( name = "redis_mocks", srcs = ["mocks.cc"], @@ -100,6 +114,7 @@ envoy_cc_mock( "//source/extensions/filters/network/common/redis:fault_interface", "//source/extensions/filters/network/redis_proxy:command_splitter_interface", "//source/extensions/filters/network/redis_proxy:conn_pool_interface", + "//source/extensions/filters/network/redis_proxy:external_auth_lib", "//source/extensions/filters/network/redis_proxy:router_interface", "//test/test_common:printers_lib", ], @@ -170,6 +185,7 @@ envoy_extension_cc_test( "//source/extensions/filters/network/common/redis:fault_lib", "//source/extensions/filters/network/redis_proxy:config", "//test/integration:integration_lib", + "@envoy_api//envoy/service/redis_auth/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/filters/network/redis_proxy/config_test.cc b/test/extensions/filters/network/redis_proxy/config_test.cc index c552b11e6b7e..bea8f4938690 100644 --- a/test/extensions/filters/network/redis_proxy/config_test.cc +++ b/test/extensions/filters/network/redis_proxy/config_test.cc @@ -85,6 +85,7 @@ stat_prefix: foo EXPECT_TRUE(factory.isTerminalFilterByProto(proto_config, context.serverFactoryContext())); Network::MockConnection connection; EXPECT_CALL(connection, addReadFilter(_)); + EXPECT_CALL(context.server_factory_context_.cluster_manager_, grpcAsyncClientManager()).Times(0); cb(connection); } @@ -192,6 +193,35 @@ stat_prefix: foo "ConnectionRateLimitPerSec: value must be greater than 0"); } +// Verify async gRPC client is created if external auth is enabled. +TEST(RedisProxyFilterConfigFactoryTest, ExternalAuthProvider) { + const std::string yaml = R"EOF( +prefix_routes: + catch_all_route: + cluster: fake_cluster +stat_prefix: foo +settings: + op_timeout: 0.02s + connection_rate_limit: + connection_rate_limit_per_sec: 1 +external_auth_provider: + grpc_service: + envoy_grpc: + cluster_name: "external_auth_cluster" + )EOF"; + + envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config; + TestUtility::loadFromYamlAndValidate(yaml, proto_config); + NiceMock context; + RedisProxyFilterConfigFactory factory; + Network::FilterFactoryCb cb = factory.createFilterFactoryFromProto(proto_config, context).value(); + EXPECT_TRUE(factory.isTerminalFilterByProto(proto_config, context.serverFactoryContext())); + Network::MockConnection connection; + EXPECT_CALL(connection, addReadFilter(_)); + EXPECT_CALL(context.server_factory_context_.cluster_manager_, grpcAsyncClientManager()); + cb(connection); +} + } // namespace RedisProxy } // namespace NetworkFilters } // namespace Extensions diff --git a/test/extensions/filters/network/redis_proxy/external_auth_test.cc b/test/extensions/filters/network/redis_proxy/external_auth_test.cc new file mode 100644 index 000000000000..d45e5efe5648 --- /dev/null +++ b/test/extensions/filters/network/redis_proxy/external_auth_test.cc @@ -0,0 +1,199 @@ +#include + +#include "envoy/service/redis_auth/v3/redis_external_auth.pb.h" + +#include "source/extensions/filters/network/redis_proxy/external_auth.h" + +#include "test/extensions/filters/network/redis_proxy/mocks.h" +#include "test/mocks/grpc/mocks.h" +#include "test/mocks/stream_info/mocks.h" +#include "test/mocks/tracing/mocks.h" + +#include "gtest/gtest.h" + +using testing::Eq; +using testing::Ref; + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace RedisProxy { +namespace ExternalAuth { + +class GrpcExternalAuthClientTest : public testing::Test { +public: + GrpcExternalAuthClientTest() : async_client_(new Grpc::MockAsyncClient()), timeout_(10) {} + + void initialize() { + client_ = + std::make_unique(Grpc::RawAsyncClientPtr{async_client_}, timeout_); + } + + void expectCallSend(envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest& request) { + EXPECT_CALL(*async_client_, + sendRaw(_, _, Grpc::ProtoBufferEq(request), Ref(*(client_.get())), _, _)) + .WillOnce( + Invoke([this](absl::string_view service_full_name, absl::string_view method_name, + Buffer::InstancePtr&&, Grpc::RawAsyncRequestCallbacks&, Tracing::Span&, + const Http::AsyncClient::RequestOptions& options) -> Grpc::AsyncRequest* { + EXPECT_EQ("envoy.service.redis_auth.v3.RedisProxyExternalAuth", service_full_name); + EXPECT_EQ("Authenticate", method_name); + EXPECT_EQ(timeout_->count(), options.timeout->count()); + return &async_request_; + })); + } + + Grpc::MockAsyncClient* async_client_; + absl::optional timeout_; + GrpcExternalAuthClientPtr client_; + Grpc::MockAsyncRequest async_request_; + Tracing::MockSpan span_; + MockAuthenticateCallback request_callback_; + NiceMock stream_info_; + CommandSplitter::MockSplitCallbacks pending_request_; +}; + +TEST_F(GrpcExternalAuthClientTest, SuccessOk) { + initialize(); + + auto response = + std::make_unique(); + response->mutable_expiration()->set_seconds(42); + auto status = response->mutable_status(); + status->set_code(Grpc::Status::WellKnownGrpcStatus::Ok); + + auto expected_response = AuthenticateResponse{}; + expected_response.expiration.set_seconds(42); + expected_response.status = AuthenticationRequestStatus::Authorized; + + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest request; + request.set_username("username"); + request.set_password("password"); + expectCallSend(request); + client_->authenticateExternal(request_callback_, pending_request_, stream_info_, "username", + "password"); + + EXPECT_CALL(span_, setTag(Eq("redis_auth_status"), Eq("redis_auth_ok"))); + EXPECT_CALL(request_callback_, onAuthenticateExternal_(_, _)); + client_->onSuccess(std::move(response), span_); +} + +TEST_F(GrpcExternalAuthClientTest, SuccessPermissionDenied) { + initialize(); + + auto response = + std::make_unique(); + response->mutable_expiration()->set_seconds(42); + auto status = response->mutable_status(); + status->set_code(Grpc::Status::WellKnownGrpcStatus::PermissionDenied); + + auto expected_response = AuthenticateResponse{}; + expected_response.expiration.set_seconds(42); + expected_response.status = AuthenticationRequestStatus::Unauthorized; + + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest request; + request.set_username("username"); + request.set_password("password"); + expectCallSend(request); + client_->authenticateExternal(request_callback_, pending_request_, stream_info_, "username", + "password"); + + EXPECT_CALL(span_, setTag(Eq("redis_auth_status"), Eq("redis_auth_unauthorized"))); + EXPECT_CALL(request_callback_, onAuthenticateExternal_(_, _)); + client_->onSuccess(std::move(response), span_); +} + +TEST_F(GrpcExternalAuthClientTest, SuccessUnauthenticated) { + initialize(); + + auto response = + std::make_unique(); + response->mutable_expiration()->set_seconds(42); + auto status = response->mutable_status(); + status->set_code(Grpc::Status::WellKnownGrpcStatus::Unauthenticated); + + auto expected_response = AuthenticateResponse{}; + expected_response.expiration.set_seconds(42); + expected_response.status = AuthenticationRequestStatus::Unauthorized; + + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest request; + request.set_username("username"); + request.set_password("password"); + expectCallSend(request); + client_->authenticateExternal(request_callback_, pending_request_, stream_info_, "username", + "password"); + + EXPECT_CALL(span_, setTag(Eq("redis_auth_status"), Eq("redis_auth_unauthorized"))); + EXPECT_CALL(request_callback_, onAuthenticateExternal_(_, _)); + client_->onSuccess(std::move(response), span_); +} + +TEST_F(GrpcExternalAuthClientTest, SuccessUnknown) { + initialize(); + + auto response = + std::make_unique(); + response->mutable_expiration()->set_seconds(42); + auto status = response->mutable_status(); + status->set_code(Grpc::Status::WellKnownGrpcStatus::Unknown); + response->set_message("oops, unknown"); + + auto expected_response = AuthenticateResponse{}; + expected_response.expiration.set_seconds(42); + expected_response.status = AuthenticationRequestStatus::Error; + expected_response.message = "oops, unknown"; + + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest request; + request.set_username("username"); + request.set_password("password"); + expectCallSend(request); + client_->authenticateExternal(request_callback_, pending_request_, stream_info_, "username", + "password"); + + EXPECT_CALL(span_, setTag(Eq("redis_auth_status"), Eq("redis_auth_error"))); + EXPECT_CALL(request_callback_, onAuthenticateExternal_(_, _)); + client_->onSuccess(std::move(response), span_); +} + +TEST_F(GrpcExternalAuthClientTest, Failure) { + initialize(); + + auto expected_response = AuthenticateResponse{}; + expected_response.status = AuthenticationRequestStatus::Error; + expected_response.message = "error message"; + + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest request; + request.set_username("username"); + request.set_password("password"); + expectCallSend(request); + client_->authenticateExternal(request_callback_, pending_request_, stream_info_, "username", + "password"); + + EXPECT_CALL(span_, setTag(Eq("redis_auth_status"), Eq("redis_auth_error"))); + EXPECT_CALL(request_callback_, onAuthenticateExternal_(_, _)); + client_->onFailure(Grpc::Status::Unknown, "error message", span_); + + // no-op + Http::RequestHeaderMapPtr hm = Http::RequestHeaderMapImpl::create(); + client_->onCreateInitialMetadata(*hm); +} + +TEST_F(GrpcExternalAuthClientTest, Cancel) { + initialize(); + + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest request; + request.set_username("username"); + request.set_password("password"); + expectCallSend(request); + client_->authenticateExternal(request_callback_, pending_request_, stream_info_, "username", + "password"); + + EXPECT_CALL(async_request_, cancel()); + client_->cancel(); +} + +} // namespace ExternalAuth +} // namespace RedisProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/network/redis_proxy/mocks.cc b/test/extensions/filters/network/redis_proxy/mocks.cc index 60c6ac26f9b8..6cfd108e7eef 100644 --- a/test/extensions/filters/network/redis_proxy/mocks.cc +++ b/test/extensions/filters/network/redis_proxy/mocks.cc @@ -52,6 +52,15 @@ MockInstance::MockInstance() = default; MockInstance::~MockInstance() = default; } // namespace CommandSplitter + +namespace ExternalAuth { +MockExternalAuthClient::MockExternalAuthClient() = default; +MockExternalAuthClient::~MockExternalAuthClient() = default; + +MockAuthenticateCallback::MockAuthenticateCallback() = default; +MockAuthenticateCallback::~MockAuthenticateCallback() = default; +} // namespace ExternalAuth + } // namespace RedisProxy } // namespace NetworkFilters } // namespace Extensions diff --git a/test/extensions/filters/network/redis_proxy/mocks.h b/test/extensions/filters/network/redis_proxy/mocks.h index 3d9c96b8f5fe..f1e0c03b8e67 100644 --- a/test/extensions/filters/network/redis_proxy/mocks.h +++ b/test/extensions/filters/network/redis_proxy/mocks.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "envoy/stream_info/stream_info.h" @@ -12,6 +13,7 @@ #include "source/extensions/filters/network/common/redis/fault.h" #include "source/extensions/filters/network/redis_proxy/command_splitter.h" #include "source/extensions/filters/network/redis_proxy/conn_pool.h" +#include "source/extensions/filters/network/redis_proxy/external_auth.h" #include "source/extensions/filters/network/redis_proxy/router.h" #include "test/test_common/printers.h" @@ -140,6 +142,38 @@ class MockInstance : public Instance { }; } // namespace CommandSplitter + +namespace ExternalAuth { + +class MockExternalAuthClient : public ExternalAuthClient { +public: + MockExternalAuthClient(); + ~MockExternalAuthClient() override; + + // ExtAuthz::Client + MOCK_METHOD(void, cancel, ()); + MOCK_METHOD(void, authenticateExternal, + (AuthenticateCallback & callback, CommandSplitter::SplitCallbacks& pending_request, + const StreamInfo::StreamInfo& stream_info, std::string username, + std::string password)); +}; + +class MockAuthenticateCallback : public AuthenticateCallback { +public: + MockAuthenticateCallback(); + ~MockAuthenticateCallback() override; + + void onAuthenticateExternal(CommandSplitter::SplitCallbacks& request, + AuthenticateResponsePtr&& response) override { + onAuthenticateExternal_(request, response); + } + + MOCK_METHOD(void, onAuthenticateExternal_, + (CommandSplitter::SplitCallbacks & request, AuthenticateResponsePtr& response)); +}; + +} // namespace ExternalAuth + } // namespace RedisProxy } // namespace NetworkFilters } // namespace Extensions diff --git a/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc b/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc index 3dd6a6d46177..af7b1a37a788 100644 --- a/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc +++ b/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc @@ -1,8 +1,10 @@ +#include #include #include #include "envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.pb.h" +#include "source/common/protobuf/protobuf.h" #include "source/extensions/filters/network/redis_proxy/proxy_filter.h" #include "test/common/stats/stat_test_utility.h" @@ -12,6 +14,7 @@ #include "test/mocks/api/mocks.h" #include "test/mocks/common.h" #include "test/mocks/network/mocks.h" +#include "test/mocks/server/factory_context.h" #include "test/test_common/printers.h" #include "test/test_common/utility.h" @@ -28,6 +31,7 @@ using testing::NiceMock; using testing::Ref; using testing::Return; using testing::WithArg; +using testing::WithArgs; namespace Envoy { namespace Extensions { @@ -55,6 +59,8 @@ class RedisProxyFilterConfigTest Network::MockDrainDecision drain_decision_; Runtime::MockLoader runtime_; NiceMock api_; + NiceMock context_; + Event::SimulatedTimeSystem time_source_; }; TEST_F(RedisProxyFilterConfigTest, Normal) { @@ -70,7 +76,7 @@ TEST_F(RedisProxyFilterConfigTest, Normal) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, - *this); + time_source_, *this); EXPECT_EQ("redis.foo.", config.stat_prefix_); EXPECT_TRUE(config.downstream_auth_username_.empty()); EXPECT_TRUE(config.downstream_auth_passwords_.empty()); @@ -100,7 +106,7 @@ TEST_F(RedisProxyFilterConfigTest, DownstreamAuthPasswordSet) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, - *this); + time_source_, *this); EXPECT_EQ(config.downstream_auth_passwords_.size(), 1); EXPECT_EQ(config.downstream_auth_passwords_[0], "somepassword"); } @@ -123,7 +129,7 @@ TEST_F(RedisProxyFilterConfigTest, DownstreamMultipleAuthPasswordsSet) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, - *this); + time_source_, *this); EXPECT_EQ(config.downstream_auth_passwords_.size(), 3); EXPECT_EQ(config.downstream_auth_passwords_[0], "somepassword"); EXPECT_EQ(config.downstream_auth_passwords_[1], "newpassword1"); @@ -146,7 +152,7 @@ TEST_F(RedisProxyFilterConfigTest, DownstreamOnlyExraAuthPasswordsSet) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, - *this); + time_source_, *this); EXPECT_EQ(config.downstream_auth_passwords_.size(), 2); EXPECT_EQ(config.downstream_auth_passwords_[0], "newpassword1"); EXPECT_EQ(config.downstream_auth_passwords_[1], "newpassword2"); @@ -169,7 +175,7 @@ TEST_F(RedisProxyFilterConfigTest, DownstreamAuthAclSet) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, - *this); + time_source_, *this); EXPECT_EQ(config.downstream_auth_username_, "someusername"); EXPECT_EQ(config.downstream_auth_passwords_.size(), 1); EXPECT_EQ(config.downstream_auth_passwords_[0], "somepassword"); @@ -195,7 +201,7 @@ TEST_F(RedisProxyFilterConfigTest, DownstreamAuthAclSetWithMultiplePasswords) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, - *this); + time_source_, *this); EXPECT_EQ(config.downstream_auth_username_, "someusername"); EXPECT_EQ(config.downstream_auth_passwords_.size(), 3); EXPECT_EQ(config.downstream_auth_passwords_[0], "somepassword"); @@ -221,13 +227,58 @@ TEST_F(RedisProxyFilterConfigTest, DownstreamAuthAclSetWithOnlyExtraPasswords) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, - *this); + time_source_, *this); EXPECT_EQ(config.downstream_auth_username_, "someusername"); EXPECT_EQ(config.downstream_auth_passwords_.size(), 2); EXPECT_EQ(config.downstream_auth_passwords_[0], "newpassword1"); EXPECT_EQ(config.downstream_auth_passwords_[1], "newpassword2"); } +TEST_F(RedisProxyFilterConfigTest, ExternalAuthBasic) { + const std::string yaml_string = R"EOF( + prefix_routes: + catch_all_route: + cluster: fake_cluster + stat_prefix: foo + settings: + op_timeout: 0.01s + external_auth_provider: + grpc_service: + envoy_grpc: + cluster_name: fake_cluster + )EOF"; + + envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = + parseProtoFromYaml(yaml_string); + ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, + time_source_, *this); + EXPECT_TRUE(config.external_auth_enabled_); + EXPECT_FALSE(config.external_auth_expiration_enabled_); +} + +TEST_F(RedisProxyFilterConfigTest, ExternalAuthWithExpiration) { + const std::string yaml_string = R"EOF( + prefix_routes: + catch_all_route: + cluster: fake_cluster + stat_prefix: foo + settings: + op_timeout: 0.01s + external_auth_provider: + grpc_service: + envoy_grpc: + cluster_name: fake_cluster + enable_auth_expiration: true + )EOF"; + + envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = + parseProtoFromYaml(yaml_string); + ProxyFilterConfig config(proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, + time_source_, *this); + EXPECT_TRUE(config.external_auth_enabled_); + EXPECT_TRUE(config.external_auth_expiration_enabled_); +} + class RedisProxyFilterTest : public testing::Test, public Common::Redis::DecoderFactory, @@ -252,10 +303,19 @@ class RedisProxyFilterTest RedisProxyFilterTest(const std::string& yaml_string) { envoy::extensions::filters::network::redis_proxy::v3::RedisProxy proto_config = parseProtoFromYaml(yaml_string); - config_ = std::make_shared(proto_config, *store_.rootScope(), - drain_decision_, runtime_, api_, *this); - filter_ = std::make_unique(*this, Common::Redis::EncoderPtr{encoder_}, splitter_, - config_); + config_ = std::make_shared( + proto_config, *store_.rootScope(), drain_decision_, runtime_, api_, time_source_, *this); + time_source_.setSystemTime(std::chrono::seconds(0)); + if (config_->external_auth_enabled_) { + external_auth_client_ = new ExternalAuth::MockExternalAuthClient(); + filter_ = std::make_unique( + *this, Common::Redis::EncoderPtr{encoder_}, splitter_, config_, + ExternalAuth::ExternalAuthClientPtr{external_auth_client_}); + } else { + filter_ = std::make_unique(*this, Common::Redis::EncoderPtr{encoder_}, splitter_, + config_, nullptr); + } + filter_->initializeReadFilterCallbacks(filter_callbacks_); EXPECT_EQ(Network::FilterStatus::Continue, filter_->onNewConnection()); EXPECT_EQ(1UL, config_->stats_.downstream_cx_total_.value()); @@ -292,6 +352,9 @@ class RedisProxyFilterTest std::unique_ptr filter_; NiceMock filter_callbacks_; NiceMock api_; + NiceMock context_; + ExternalAuth::MockExternalAuthClient* external_auth_client_; + Event::SimulatedTimeSystem time_source_; }; class RedisProxyFilterTestWithTwoCallbacks : public RedisProxyFilterTest { @@ -930,6 +993,324 @@ TEST_F(RedisProxyFilterWithAuthAclMultiplePasswordsTest, AuthAclPasswordIncorrec EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); } +const std::string external_auth_expiration_config = R"EOF( +prefix_routes: + catch_all_route: + cluster: fake_cluster +stat_prefix: foo +settings: + op_timeout: 0.01s +external_auth_provider: + grpc_service: + envoy_grpc: + cluster_name: fake_cluster + enable_auth_expiration: true +)EOF"; + +class RedisProxyFilterWithExternalAuthAndExpiration : public RedisProxyFilterTest { +public: + RedisProxyFilterWithExternalAuthAndExpiration() + : RedisProxyFilterTest(external_auth_expiration_config) {} +}; + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthPasswordWrong) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, + authenticateExternal(_, _, _, EMPTY_STRING, "wrongpassword")) + .WillOnce(WithArgs<0, 1>( + Invoke([&](ExternalAuth::AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request) -> void { + ExternalAuth::AuthenticateResponsePtr auth_response = + std::make_unique( + ExternalAuth::AuthenticateResponse{}); + auth_response->status = ExternalAuth::AuthenticationRequestStatus::Unauthorized; + auth_response->message = "sorry, invalid password"; + callback.onAuthenticateExternal(pending_request, std::move(auth_response)); + }))); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::Error); + reply->asString() = "ERR sorry, invalid password"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("wrongpassword"); + // callbacks cannot be accessed now. + EXPECT_FALSE(filter_->connectionAllowed()); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthUsernamePasswordWrong) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, + authenticateExternal(_, _, _, "wrongusername", "wrongpassword")) + .WillOnce(WithArgs<0, 1>( + Invoke([&](ExternalAuth::AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request) -> void { + ExternalAuth::AuthenticateResponsePtr auth_response = + std::make_unique( + ExternalAuth::AuthenticateResponse{}); + auth_response->status = ExternalAuth::AuthenticationRequestStatus::Unauthorized; + auth_response->message = "ooops, invalid password and username"; + callback.onAuthenticateExternal(pending_request, std::move(auth_response)); + }))); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::Error); + reply->asString() = "ERR ooops, invalid password and username"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("wrongusername", "wrongpassword"); + // callbacks cannot be accessed now. + EXPECT_FALSE(filter_->connectionAllowed()); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthUsernamePasswordCorrect) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, authenticateExternal(_, _, _, "username", "password")) + .WillOnce(WithArgs<0, 1>( + Invoke([&](ExternalAuth::AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request) -> void { + ExternalAuth::AuthenticateResponsePtr auth_response = + std::make_unique( + ExternalAuth::AuthenticateResponse{}); + auth_response->status = ExternalAuth::AuthenticationRequestStatus::Authorized; + auto time = time_source_.systemTime() + std::chrono::hours(12); + + auth_response->expiration.set_seconds( + duration_cast(time.time_since_epoch()).count()); + callback.onAuthenticateExternal(pending_request, std::move(auth_response)); + }))); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::SimpleString); + reply->asString() = "OK"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("username", "password"); + // callbacks can be accessed now. + EXPECT_TRUE(filter_->connectionAllowed()); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthPasswordCorrect) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, authenticateExternal(_, _, _, EMPTY_STRING, "password")) + .WillOnce(WithArgs<0, 1>( + Invoke([&](ExternalAuth::AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request) -> void { + ExternalAuth::AuthenticateResponsePtr auth_response = + std::make_unique( + ExternalAuth::AuthenticateResponse{}); + auth_response->status = ExternalAuth::AuthenticationRequestStatus::Authorized; + auto time = time_source_.systemTime() + std::chrono::hours(12); + auth_response->expiration.set_seconds( + duration_cast(time.time_since_epoch()).count()); + callback.onAuthenticateExternal(pending_request, std::move(auth_response)); + }))); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::SimpleString); + reply->asString() = "OK"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("password"); + // callbacks can be accessed now. + EXPECT_TRUE(filter_->connectionAllowed()); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthPasswordCorrectButThenExpires) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, authenticateExternal(_, _, _, EMPTY_STRING, "password")) + .WillOnce(WithArgs<0, 1>( + Invoke([&](ExternalAuth::AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request) -> void { + ExternalAuth::AuthenticateResponsePtr auth_response = + std::make_unique( + ExternalAuth::AuthenticateResponse{}); + auth_response->status = ExternalAuth::AuthenticationRequestStatus::Authorized; + auto time = time_source_.systemTime() + std::chrono::hours(1); + auth_response->expiration.set_seconds( + duration_cast(time.time_since_epoch()).count()); + callback.onAuthenticateExternal(pending_request, std::move(auth_response)); + }))); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::SimpleString); + reply->asString() = "OK"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("password"); + // callbacks can be accessed now. + EXPECT_TRUE(filter_->connectionAllowed()); + // but then expiration passes + time_source_.advanceTimeWait(std::chrono::hours(2)); + // and callbacks are not accessible anymore. + EXPECT_FALSE(filter_->connectionAllowed()); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthPendingRequest) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, + authenticateExternal(_, _, _, EMPTY_STRING, "password")); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::Error); + reply->asString() = "ERR an existing authentication request is pending"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("password"); + // Call again (pending request will cause error) + callbacks.onAuth("password"); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthPendingRequestUsername) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, authenticateExternal(_, _, _, "username", "password")); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::Error); + reply->asString() = "ERR an existing authentication request is pending"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("username", "password"); + // Call again (pending request will cause error) + callbacks.onAuth("username", "password"); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + +TEST_F(RedisProxyFilterWithExternalAuthAndExpiration, ExternalAuthError) { + InSequence s; + + Buffer::OwnedImpl fake_data; + Common::Redis::RespValuePtr request(new Common::Redis::RespValue()); + EXPECT_CALL(*decoder_, decode(Ref(fake_data))).WillOnce(Invoke([&](Buffer::Instance&) -> void { + decoder_callbacks_->onRespValue(std::move(request)); + })); + EXPECT_CALL(splitter_, makeRequest_(Ref(*request), _, _, _)) + .WillOnce(Invoke([&](const Common::Redis::RespValue&, + CommandSplitter::SplitCallbacks& callbacks, Event::Dispatcher&, + const StreamInfo::StreamInfo&) -> CommandSplitter::SplitRequest* { + EXPECT_FALSE(callbacks.connectionAllowed()); + EXPECT_CALL(*external_auth_client_, authenticateExternal(_, _, _, EMPTY_STRING, "password")) + .WillOnce(WithArgs<0, 1>( + Invoke([&](ExternalAuth::AuthenticateCallback& callback, + CommandSplitter::SplitCallbacks& pending_request) -> void { + ExternalAuth::AuthenticateResponsePtr auth_response = + std::make_unique( + ExternalAuth::AuthenticateResponse{}); + auth_response->status = ExternalAuth::AuthenticationRequestStatus::Error; + auth_response->message = "sorry, error"; + callback.onAuthenticateExternal(pending_request, std::move(auth_response)); + }))); + Common::Redis::RespValuePtr reply(new Common::Redis::RespValue()); + reply->type(Common::Redis::RespType::Error); + reply->asString() = "ERR external authentication failed"; + EXPECT_CALL(*encoder_, encode(Eq(ByRef(*reply)), _)); + EXPECT_CALL(filter_callbacks_.connection_, write(_, _)); + callbacks.onAuth("password"); + // callbacks cannot be accessed now. + EXPECT_FALSE(filter_->connectionAllowed()); + return nullptr; + })); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(fake_data, false)); +} + } // namespace RedisProxy } // namespace NetworkFilters } // namespace Extensions diff --git a/test/extensions/filters/network/redis_proxy/redis_proxy_integration_test.cc b/test/extensions/filters/network/redis_proxy/redis_proxy_integration_test.cc index 666c66ef120f..d317d58b2338 100644 --- a/test/extensions/filters/network/redis_proxy/redis_proxy_integration_test.cc +++ b/test/extensions/filters/network/redis_proxy/redis_proxy_integration_test.cc @@ -1,11 +1,15 @@ #include #include +#include "envoy/service/redis_auth/v3/redis_external_auth.pb.h" + #include "source/common/common/fmt.h" #include "source/extensions/filters/network/common/redis/fault_impl.h" #include "source/extensions/filters/network/redis_proxy/command_splitter_impl.h" +#include "test/common/grpc/grpc_client_integration.h" #include "test/integration/integration.h" +#include "test/test_common/simulated_time_system.h" #include "gtest/gtest.h" @@ -325,6 +329,15 @@ const std::string CONFIG_WITH_FAULT_INJECTION = CONFIG + R"EOF( - SET )EOF"; +const std::string CONFIG_WITH_EXTERNAL_AUTH = CONFIG + R"EOF( + external_auth_provider: + enable_auth_expiration: true + grpc_service: + timeout: 2s + envoy_grpc: + cluster_name: fake_auth +)EOF"; + // This function encodes commands as an array of bulkstrings as transmitted by Redis clients to // Redis servers, according to the Redis protocol. std::string makeBulkStringArray(std::vector&& command_strings) { @@ -397,6 +410,21 @@ class RedisProxyIntegrationTest : public testing::TestWithParamadd_clusters() = fake_auth_cluster; + }); + + RedisProxyIntegrationTest::initialize(); + } + + void expectExternalAuthRequest(FakeHttpConnectionPtr& fake_upstream_connection, + FakeStreamPtr& auth_request, const std::string password, + const bool existing_connection = false) { + // Connect if not yet. + if (!existing_connection) { + auto result = + fake_upstreams_[2]->waitForHttpConnection(*dispatcher_, fake_upstream_connection); + RELEASE_ASSERT(result, result.message()); + } + + // Receive data. + auto result = fake_upstream_connection->waitForNewStream(*dispatcher_, auth_request); + RELEASE_ASSERT(result, result.message()); + + // Get the gRPC message. Ensure it is a RedisProxyExternalAuthRequest. + envoy::service::redis_auth::v3::RedisProxyExternalAuthRequest received_request; + result = auth_request->waitForGrpcMessage(*dispatcher_, received_request); + RELEASE_ASSERT(result, result.message()); + + // gRPC request expectations. + EXPECT_EQ("POST", auth_request->headers().getMethodValue()); + EXPECT_EQ("/envoy.service.redis_auth.v3.RedisProxyExternalAuth/Authenticate", + auth_request->headers().getPathValue()); + EXPECT_EQ("application/grpc", auth_request->headers().getContentTypeValue()); + + // Check that the received password matches the expected password. + EXPECT_EQ(password, received_request.password()); + + // End the request stream. + result = auth_request->waitForEndStream(*dispatcher_); + RELEASE_ASSERT(result, result.message()); + } + + void sendExternalAuthResponse(FakeStreamPtr& auth_request, const bool authorized, + const int64_t expiration_epoch) { + // Start the stream. + auth_request->startGrpcStream(); + + // Create the response + envoy::service::redis_auth::v3::RedisProxyExternalAuthResponse response; + response.mutable_status()->set_code(authorized + ? Grpc::Status::WellKnownGrpcStatus::Ok + : Grpc::Status::WellKnownGrpcStatus::PermissionDenied); + auto* msg = response.mutable_message(); + *msg = authorized ? "Authorized" : "Unauthorized"; + response.mutable_expiration()->set_seconds(expiration_epoch); + + // Send the response and close stream. + auth_request->sendGrpcMessage(response); + auth_request->finishGrpcStream(Grpc::Status::Ok); + } +}; + INSTANTIATE_TEST_SUITE_P(IpVersions, RedisProxyIntegrationTest, testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), TestUtility::ipTestParamsToString); @@ -564,6 +675,10 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, RedisProxyWithFaultInjectionIntegrationTest testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), TestUtility::ipTestParamsToString); +INSTANTIATE_TEST_SUITE_P(IpVersions, RedisProxyWithExternalAuthIntegrationTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); + void RedisProxyIntegrationTest::initialize() { setUpstreamCount(num_upstreams_); setDeterministicValue(); @@ -631,16 +746,26 @@ void RedisProxyIntegrationTest::simpleRoundtripToUpstream(FakeUpstreamPtr& upstr redis_client->close(); } -void RedisProxyIntegrationTest::proxyResponseStep(const std::string& request, - const std::string& proxy_response, - IntegrationTcpClientPtr& redis_client) { +void RedisProxyIntegrationTest::proxyRequestStep(const std::string& request, + IntegrationTcpClientPtr& redis_client) { redis_client->clearData(); ASSERT_TRUE(redis_client->write(request)); +} + +void RedisProxyIntegrationTest::proxyResponseOnlyStep(const std::string& proxy_response, + IntegrationTcpClientPtr& redis_client) { redis_client->waitForData(proxy_response); // After sending the request to the proxy, the fake redis client should receive proxy_response. EXPECT_EQ(proxy_response, redis_client->data()); } +void RedisProxyIntegrationTest::proxyResponseStep(const std::string& request, + const std::string& proxy_response, + IntegrationTcpClientPtr& redis_client) { + proxyRequestStep(request, redis_client); + proxyResponseOnlyStep(proxy_response, redis_client); +} + void RedisProxyIntegrationTest::simpleProxyResponse(const std::string& request, const std::string& proxy_response) { IntegrationTcpClientPtr redis_client = makeTcpConnection(lookupPort("redis_proxy")); @@ -1419,5 +1544,58 @@ TEST_P(RedisProxyWithCommandStatsIntegrationTest, PipelinedTransactionTest) { // TODO: Add full transaction test. +TEST_P(RedisProxyWithExternalAuthIntegrationTest, ErrorsUntilCorrectPasswordSentExternal) { + initialize(); + + IntegrationTcpClientPtr redis_client = makeTcpConnection(lookupPort("redis_proxy")); + FakeRawConnectionPtr fake_upstream_redis_connection; + FakeHttpConnectionPtr fake_upstream_external_auth; + + // Trying to get a key without authenticating should return NOAUTH error. + proxyResponseStep(makeBulkStringArray({"get", "foo"}), "-NOAUTH Authentication required.\r\n", + redis_client); + + // Sending an AUTH command without a password should return an error. + std::stringstream error_response; + error_response << "-" << RedisCmdSplitter::Response::get().InvalidRequest << "\r\n"; + proxyResponseStep(makeBulkStringArray({"auth"}), error_response.str(), redis_client); + + // Sending an AUTH command with the wrong password should return an error. + proxyRequestStep(makeBulkStringArray({"auth", "wrongpassword"}), redis_client); + FakeStreamPtr auth_request1; + expectExternalAuthRequest(fake_upstream_external_auth, auth_request1, "wrongpassword"); + sendExternalAuthResponse(auth_request1, false, 0); + proxyResponseOnlyStep("-ERR Unauthorized\r\n", redis_client); + + // Sending a command after unsuccessful auth should return NOAUTH error. + proxyResponseStep(makeBulkStringArray({"get", "foo"}), "-NOAUTH Authentication required.\r\n", + redis_client); + + // Sending an AUTH command with the correct password should return OK. + proxyRequestStep(makeBulkStringArray({"auth", "somepassword"}), redis_client); + FakeStreamPtr auth_request2; + expectExternalAuthRequest(fake_upstream_external_auth, auth_request2, "somepassword", true); + auto expiration_time = timeSystem().systemTime() + std::chrono::hours(1); + sendExternalAuthResponse( + auth_request2, true, + duration_cast(expiration_time.time_since_epoch()).count()); + proxyResponseOnlyStep("+OK\r\n", redis_client); + + // Further requests should be successful. + roundtripToUpstreamStep(fake_upstreams_[0], makeBulkStringArray({"get", "foo"}), "$3\r\nbar\r\n", + redis_client, fake_upstream_redis_connection, "", ""); + + // Expiration passes + timeSystem().advanceTimeWait(std::chrono::hours(2)); + + // Sending a command after expiration should return NOAUTH error. + proxyResponseStep(makeBulkStringArray({"get", "foo"}), "-NOAUTH Authentication required.\r\n", + redis_client); + + EXPECT_TRUE(fake_upstream_redis_connection->close()); + EXPECT_TRUE(fake_upstream_external_auth->close()); + redis_client->close(); +} + } // namespace } // namespace Envoy From 8a56de1cb5893d2402f6486b43fcd5e1f794d492 Mon Sep 17 00:00:00 2001 From: code Date: Tue, 27 Aug 2024 15:52:07 +0800 Subject: [PATCH 47/53] tools: update refresh compdb to use build setup (#35811) Commit Message: tools: update refresh compdb to use build setup Additional Description: Finally, I reached here, haha. This PR updated the refresh_compdb.sh to use build_setup.sh. By this way, the refresh_copdb.sh could share some building config with the `ci/do_ci.sh`. (like `--repository_cache`). Risk Level: low. Testing: n/a. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping --- ci/do_ci.sh | 4 ++++ tools/gen_compilation_database.py | 9 ++++----- tools/vscode/refresh_compdb.sh | 5 +---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 1d51f478f15c..4d1b1ea3b172 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -1043,6 +1043,10 @@ case $CI_TARGET in --trigger-inputs="$INPUTS" ;; + refresh_compdb) + "${CURRENT_SCRIPT_DIR}/../tools/vscode/refresh_compdb.sh" + ;; + *) echo "Invalid do_ci.sh target (${CI_TARGET}), see ci/README.md for valid targets." exit 1 diff --git a/tools/gen_compilation_database.py b/tools/gen_compilation_database.py index 5e7fc75d3e13..2dfdaa79fd17 100755 --- a/tools/gen_compilation_database.py +++ b/tools/gen_compilation_database.py @@ -22,14 +22,14 @@ def generate_compilation_database(args): if args.exclude_contrib: source_dir_targets.remove("//contrib/...") - subprocess.check_call([args.bazel, *bazel_startup_options, "build"] + bazel_options + [ + subprocess.check_call(["bazel", *bazel_startup_options, "build"] + bazel_options + [ "--aspects=@bazel_compdb//:aspects.bzl%compilation_database_aspect", "--output_groups=compdb_files,header_files" ] + source_dir_targets) - execroot = subprocess.check_output([ - args.bazel, *bazel_startup_options, "info", *bazel_options, "execution_root", *bazel_options - ]).decode().strip() + execroot = subprocess.check_output( + ["bazel", *bazel_startup_options, "info", *bazel_options, "execution_root", + *bazel_options]).decode().strip() db_entries = [] for db in Path(execroot).glob('**/*.compile_commands.json'): @@ -128,7 +128,6 @@ def fix_compilation_database(args, db): help= 'Use `clang++` instead of the bazel wrapper for commands. This may help if `clangd` cannot find/run the tools.' ) - parser.add_argument('--bazel', default='bazel') parser.add_argument( 'bazel_targets', nargs='*', default=[ "//source/...", diff --git a/tools/vscode/refresh_compdb.sh b/tools/vscode/refresh_compdb.sh index 996a9d576102..da41d6f18356 100755 --- a/tools/vscode/refresh_compdb.sh +++ b/tools/vscode/refresh_compdb.sh @@ -2,10 +2,7 @@ [[ -z "${SKIP_PROTO_FORMAT}" ]] && tools/proto_format/proto_format.sh fix -bazel_or_isk=bazelisk -command -v bazelisk &> /dev/null || bazel_or_isk=bazel - -opts=(--vscode --bazel="$bazel_or_isk") +opts=(--vscode) [[ -z "${EXCLUDE_CONTRIB}" ]] || opts+=(--exclude_contrib) From 5c869d2af7afd3085d1762e7fbecbd6bd8580c12 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:10:58 +0100 Subject: [PATCH 48/53] deps: Bump `rules_foreign_cc` -> 0.12.0 (#35855) Fix #35835 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 28fe370ea400..c598d7c6c66c 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1054,11 +1054,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Rules for using foreign build systems in Bazel", project_desc = "Rules for using foreign build systems in Bazel", project_url = "https://github.com/bazelbuild/rules_foreign_cc", - version = "0.11.1", - sha256 = "4b33d62cf109bcccf286b30ed7121129cc34cf4f4ed9d8a11f38d9108f40ba74", + version = "0.12.0", + sha256 = "a2e6fb56e649c1ee79703e99aa0c9d13c6cc53c8d7a0cbb8797ab2888bbc99a3", strip_prefix = "rules_foreign_cc-{version}", urls = ["https://github.com/bazelbuild/rules_foreign_cc/archive/{version}.tar.gz"], - release_date = "2024-07-03", + release_date = "2024-08-14", use_category = ["build", "dataplane_core", "controlplane"], license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_foreign_cc/blob/{version}/LICENSE", From e326d0be8cc70096ea6c8d36ab319f0ce971567f Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:11:28 +0100 Subject: [PATCH 49/53] deps: Bump `build_bazel_rules_apple` -> 3.8.0 (#35857) Fix #35682 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index c598d7c6c66c..d85b3b58b8e3 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -73,10 +73,10 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Apple Rules for Bazel", project_desc = "Bazel rules for Apple platforms", project_url = "https://github.com/bazelbuild/rules_apple", - version = "3.7.0", - sha256 = "ef90747e779ff13c887f4972579432b25c8378b6954e1ebfca52651b5f2099c1", + version = "3.8.0", + sha256 = "62847b3f444ce514ae386704a119ad7b29fa6dfb65a38bff4ae239f2389a0429", urls = ["https://github.com/bazelbuild/rules_apple/releases/download/{version}/rules_apple.{version}.tar.gz"], - release_date = "2024-07-23", + release_date = "2024-08-12", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_apple/blob/{version}/LICENSE", From 4543a947a8bbf41140ac950c8cf76a98a78baae8 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:12:29 +0100 Subject: [PATCH 50/53] deps/api: Bump `com_github_bufbuild_buf` -> 1.38.0 (#35856) Fix #35819 Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index d7f92d9ff693..ce4554d358b0 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -144,11 +144,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "buf", project_desc = "A new way of working with Protocol Buffers.", # Used for breaking change detection in API protobufs project_url = "https://buf.build", - version = "1.37.0", - sha256 = "a76d94f27f1e1a1b74601bb8b179e170f1138c8692d6ddcfe15ee8b77e5b90a6", + version = "1.38.0", + sha256 = "c091639826cddbbcb55fd6391e21cb1fcf0c82452a7e273b670a0b572ddb3a8c", strip_prefix = "buf", urls = ["https://github.com/bufbuild/buf/releases/download/v{version}/buf-Linux-x86_64.tar.gz"], - release_date = "2024-08-16", + release_date = "2024-08-22", use_category = ["api"], license = "Apache-2.0", license_url = "https://github.com/bufbuild/buf/blob/v{version}/LICENSE", From 1175a4fa68c14cc15371416612dc1d7ec90319c7 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:30:40 +0000 Subject: [PATCH 51/53] deps: Bump `proxy_wasm_cpp_host` -> f199214 (#35859) Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- bazel/external/wasmtime.BUILD | 10 +++++----- bazel/repositories_extra.bzl | 4 ++-- bazel/repository_locations.bzl | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bazel/external/wasmtime.BUILD b/bazel/external/wasmtime.BUILD index 16ba412ef268..879a84bf1846 100644 --- a/bazel/external/wasmtime.BUILD +++ b/bazel/external/wasmtime.BUILD @@ -19,13 +19,13 @@ rust_static_library( crate_root = "crates/c-api/src/lib.rs", edition = "2018", proc_macro_deps = [ - "@proxy_wasm_cpp_host//bazel/cargo/wasmtime:wasmtime_c_api_macros", + "@proxy_wasm_cpp_host//bazel/cargo/wasmtime/remote:wasmtime-c-api-macros", ], deps = [ ":helpers_lib", - "@proxy_wasm_cpp_host//bazel/cargo/wasmtime", - "@proxy_wasm_cpp_host//bazel/cargo/wasmtime:anyhow", - "@proxy_wasm_cpp_host//bazel/cargo/wasmtime:env_logger", - "@proxy_wasm_cpp_host//bazel/cargo/wasmtime:once_cell", + "@proxy_wasm_cpp_host//bazel/cargo/wasmtime/remote:anyhow", + "@proxy_wasm_cpp_host//bazel/cargo/wasmtime/remote:env_logger", + "@proxy_wasm_cpp_host//bazel/cargo/wasmtime/remote:once_cell", + "@proxy_wasm_cpp_host//bazel/cargo/wasmtime/remote:wasmtime", ], ) diff --git a/bazel/repositories_extra.bzl b/bazel/repositories_extra.bzl index 9414073fc7fd..b92dd461ba70 100644 --- a/bazel/repositories_extra.bzl +++ b/bazel/repositories_extra.bzl @@ -1,7 +1,7 @@ load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies") load("@bazel_features//:deps.bzl", "bazel_features_deps") load("@emsdk//:deps.bzl", emsdk_deps = "deps") -load("@proxy_wasm_cpp_host//bazel/cargo/wasmtime:crates.bzl", "wasmtime_fetch_remote_crates") +load("@proxy_wasm_cpp_host//bazel/cargo/wasmtime/remote:crates.bzl", "crate_repositories") load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") load("//bazel/external/cargo:crates.bzl", "raze_fetch_remote_crates") @@ -19,7 +19,7 @@ def envoy_dependencies_extra( bazel_features_deps() emsdk_deps() raze_fetch_remote_crates() - wasmtime_fetch_remote_crates() + crate_repositories() py_repositories() # Registers underscored Python minor version - eg `python3_10` diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index d85b3b58b8e3..4bc96ec4a630 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1412,8 +1412,8 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "WebAssembly for Proxies (C++ host implementation)", project_desc = "WebAssembly for Proxies (C++ host implementation)", project_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-host", - version = "e200fee8af40918c41f3275cff090993e3b26940", - sha256 = "9711411b3b8d48a3ee9278f44824ce569c1fdd491183255f568f2b938360e964", + version = "f199214a43337e115469d9f0dd6b77858746441b", + sha256 = "b06f193324650f80d1d5494046c45941884f4eb66025cff026edf3b506596150", strip_prefix = "proxy-wasm-cpp-host-{version}", urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-host/archive/{version}.tar.gz"], use_category = ["dataplane_ext"], @@ -1428,7 +1428,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( "envoy.wasm.runtime.wamr", "envoy.wasm.runtime.wasmtime", ], - release_date = "2023-12-19", + release_date = "2024-08-19", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-host/blob/{version}/LICENSE", From 16759b97e02131cc9c8ca64d13cf663c75dae047 Mon Sep 17 00:00:00 2001 From: Divya Chakarwarti <138142449+dchakarwarti@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:59:41 +0530 Subject: [PATCH 52/53] Cont. - Add Proto Message Extraction http filter (#35689) The Proto Message Extraction Filter supports extracting gRPC requests/responses (proto messages) as `google.protobuf.Struct` and storing results in the dynamic metadata `envoy.filters.http.proto_message_scrubbing` for later access. --------- Signed-off-by: dchakarwarti@google.com --- CODEOWNERS | 4 +- api/BUILD | 2 +- .../v3/BUILD | 0 .../v3/config.proto | 148 +- api/versioning/BUILD | 2 +- bazel/repository_locations.bzl | 16 +- .../http/http_filters/http_filters.rst | 1 + .../proto_message_extraction_filter.rst | 111 + source/extensions/extensions_build_config.bzl | 3 +- source/extensions/extensions_metadata.yaml | 7 + .../http/proto_message_extraction/BUILD | 90 + .../http/proto_message_extraction/config.cc | 39 + .../http/proto_message_extraction/config.h | 33 + .../extraction_util/BUILD | 63 + .../extraction_util/extraction_util.cc} | 119 +- .../extraction_util/extraction_util.h} | 44 +- .../extraction_util/proto_extractor.cc | 209 ++ .../extraction_util/proto_extractor.h | 70 + .../proto_extractor_interface.h | 51 + .../http/proto_message_extraction/extractor.h | 81 + .../extractor_impl.cc | 125 + .../proto_message_extraction/extractor_impl.h | 85 + .../http/proto_message_extraction/filter.cc | 431 ++++ .../http/proto_message_extraction/filter.h | 94 + .../proto_message_extraction/filter_config.cc | 113 + .../proto_message_extraction/filter_config.h | 53 + .../proto_message_logging/logging_util/BUILD | 41 - .../logging_util/proto_scrubber_interface.h | 54 - .../filters/http/well_known_names.h | 2 + .../http/proto_message_extraction/BUILD | 66 + .../extraction_util}/BUILD | 15 +- .../extraction_util/extraction_util_test.cc} | 382 ++- .../extraction_util_test.yaml} | 8 +- .../filter_config_test.cc | 409 +++ .../proto_message_extraction/filter_test.cc | 2288 +++++++++++++++++ .../integration_test.cc | 279 ++ test/proto/BUILD | 10 +- test/proto/apikeys.proto | 4 +- .../proto/{logging.proto => extraction.proto} | 8 +- tools/code_format/config.yaml | 2 + 40 files changed, 5182 insertions(+), 380 deletions(-) rename api/envoy/extensions/filters/http/{proto_message_logging => proto_message_extraction}/v3/BUILD (100%) rename api/envoy/extensions/filters/http/{proto_message_logging => proto_message_extraction}/v3/config.proto (58%) create mode 100644 docs/root/configuration/http/http_filters/proto_message_extraction_filter.rst create mode 100644 source/extensions/filters/http/proto_message_extraction/BUILD create mode 100644 source/extensions/filters/http/proto_message_extraction/config.cc create mode 100644 source/extensions/filters/http/proto_message_extraction/config.h create mode 100644 source/extensions/filters/http/proto_message_extraction/extraction_util/BUILD rename source/extensions/filters/http/{proto_message_logging/logging_util/logging_util.cc => proto_message_extraction/extraction_util/extraction_util.cc} (79%) rename source/extensions/filters/http/{proto_message_logging/logging_util/logging_util.h => proto_message_extraction/extraction_util/extraction_util.h} (73%) create mode 100644 source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.cc create mode 100644 source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.h create mode 100644 source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h create mode 100644 source/extensions/filters/http/proto_message_extraction/extractor.h create mode 100644 source/extensions/filters/http/proto_message_extraction/extractor_impl.cc create mode 100644 source/extensions/filters/http/proto_message_extraction/extractor_impl.h create mode 100644 source/extensions/filters/http/proto_message_extraction/filter.cc create mode 100644 source/extensions/filters/http/proto_message_extraction/filter.h create mode 100644 source/extensions/filters/http/proto_message_extraction/filter_config.cc create mode 100644 source/extensions/filters/http/proto_message_extraction/filter_config.h delete mode 100644 source/extensions/filters/http/proto_message_logging/logging_util/BUILD delete mode 100644 source/extensions/filters/http/proto_message_logging/logging_util/proto_scrubber_interface.h create mode 100644 test/extensions/filters/http/proto_message_extraction/BUILD rename test/extensions/filters/http/{proto_message_logging/logging_util => proto_message_extraction/extraction_util}/BUILD (67%) rename test/extensions/filters/http/{proto_message_logging/logging_util/logging_util_test.cc => proto_message_extraction/extraction_util/extraction_util_test.cc} (75%) rename test/extensions/filters/http/{proto_message_logging/logging_util/logging_util_test.yaml => proto_message_extraction/extraction_util/extraction_util_test.yaml} (72%) create mode 100644 test/extensions/filters/http/proto_message_extraction/filter_config_test.cc create mode 100644 test/extensions/filters/http/proto_message_extraction/filter_test.cc create mode 100644 test/extensions/filters/http/proto_message_extraction/integration_test.cc rename test/proto/{logging.proto => extraction.proto} (93%) diff --git a/CODEOWNERS b/CODEOWNERS index be38c7a507cd..3a4a6091bc07 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -35,8 +35,8 @@ extensions/filters/common/original_src @klarose @mattklein123 /*/extensions/filters/http/jwt_authn @taoxuy @lizan @tyxia @yanavlasov # grpc_field_extraction http filter extension /*/extensions/filters/http/grpc_field_extraction @taoxuy @nareddyt @yanavlasov -# proto_message_logging http filter extension -/*/extensions/filters/http/proto_message_logging @dchakarwarti @taoxuy @yanavlasov +# proto_message_extraction http filter extension +/*/extensions/filters/http/proto_message_extraction @dchakarwarti @taoxuy @shuoyang2016 @yanavlasov # grpc_http1_reverse_bridge http filter extension /*/extensions/filters/http/grpc_http1_reverse_bridge @zuercher @mattklein123 # alts transport socket extension diff --git a/api/BUILD b/api/BUILD index cae22a8d0918..1fdfbcd1d0a0 100644 --- a/api/BUILD +++ b/api/BUILD @@ -200,7 +200,7 @@ proto_library( "//envoy/extensions/filters/http/oauth2/v3:pkg", "//envoy/extensions/filters/http/on_demand/v3:pkg", "//envoy/extensions/filters/http/original_src/v3:pkg", - "//envoy/extensions/filters/http/proto_message_logging/v3:pkg", + "//envoy/extensions/filters/http/proto_message_extraction/v3:pkg", "//envoy/extensions/filters/http/rate_limit_quota/v3:pkg", "//envoy/extensions/filters/http/ratelimit/v3:pkg", "//envoy/extensions/filters/http/rbac/v3:pkg", diff --git a/api/envoy/extensions/filters/http/proto_message_logging/v3/BUILD b/api/envoy/extensions/filters/http/proto_message_extraction/v3/BUILD similarity index 100% rename from api/envoy/extensions/filters/http/proto_message_logging/v3/BUILD rename to api/envoy/extensions/filters/http/proto_message_extraction/v3/BUILD diff --git a/api/envoy/extensions/filters/http/proto_message_logging/v3/config.proto b/api/envoy/extensions/filters/http/proto_message_extraction/v3/config.proto similarity index 58% rename from api/envoy/extensions/filters/http/proto_message_logging/v3/config.proto rename to api/envoy/extensions/filters/http/proto_message_extraction/v3/config.proto index 5b57e9c7d59a..dc51f9d11411 100644 --- a/api/envoy/extensions/filters/http/proto_message_logging/v3/config.proto +++ b/api/envoy/extensions/filters/http/proto_message_extraction/v3/config.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package envoy.extensions.filters.http.proto_message_logging.v3; +package envoy.extensions.filters.http.proto_message_extraction.v3; import "envoy/config/core/v3/base.proto"; @@ -8,33 +8,39 @@ import "xds/annotations/v3/status.proto"; import "udpa/annotations/status.proto"; -option java_package = "io.envoyproxy.envoy.extensions.filters.http.proto_message_logging.v3"; +option java_package = "io.envoyproxy.envoy.extensions.filters.http.proto_message_extraction.v3"; option java_outer_classname = "ConfigProto"; option java_multiple_files = true; -option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/proto_message_logging/v3;proto_message_loggingv3"; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/proto_message_extraction/v3;proto_message_extractionv3"; option (udpa.annotations.file_status).package_version_status = ACTIVE; option (xds.annotations.v3.file_status).work_in_progress = true; -// [#not-implemented-hide:] -// [#protodoc-title: Proto Message Logging] -// Proto Message Logging :ref:`configuration overview -// `. -// [#extension: envoy.filters.http.proto_message_logging] +// [#protodoc-title: Proto Message Extraction] // -// ProtoMessageLogging filter supports logging scrubbed gRPC requests/responses(proto messages) -// as google.protobuf.Struct and storing results -// in the dynamic metadata `envoy.filters.http.proto_message_logging` for later access. +// [#extension: envoy.filters.http.proto_message_extraction] +// +// Overview +// -------- +// +// ProtoMessageExtraction filter supports extracting gRPC +// requests/responses(proto messages) into google.protobuf.Struct and storing +// results in the dynamic metadata `envoy.filters.http.proto_message_extraction` +// for later access. +// +// Assumptions +// ----------- // -// # Assumptions // This filter assumes it is only applicable for gRPC with Protobuf as payload. // -// # Process Flow +// Process Flow +// ------------ +// // On the request path, it will check // // 1. if the incoming gRPC request is configured, the filter tries to: // // a. buffer the incoming data to complete protobuf messages -// b. log individual protobuf messages according to directives +// b. extract individual protobuf messages according to directives // c. write the result into the dynamic metadata. // d. pass through the request data // @@ -45,50 +51,57 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // 1. if the incoming gRPC request is configured, the filter tries to: // // a. buffer the incoming data to complete protobuf messages -// b. log individual protobuf messages according to directives +// b. extract individual protobuf messages according to directives // c. write the result into the dynamic metadata. // d. pass through the response data // // 2. otherwise, pass through the response. // -// # Config Requirements +// Config Requirements +// ------------------- + // Here are config requirements -// -// 1. the log target field should be among the following primitive types: `string`, `uint32`, `uint64`, `int32`, `int64`, `sint32`, `sint64`, `fixed32`, `fixed64`, `sfixed32`, `sfixed64`, `float`, `double`. -// + +// 1. the extracted target field should be among the following primitive types: +// `string`, `uint32`, `uint64`, `int32`, `int64`, `sint32`, `sint64`, +// `fixed32`, `fixed64`, `sfixed32`, `sfixed64`, `float`, `double`. + // 2. the target field could be repeated. -// + // 3. the intermediate type could also be repeated. -// -// # Output Format -// The logged requests and responses will be will be added in the dynamic ``metadata`` with the same layout of the message. -// + +// Output Format +// ------------- + +// The extracted requests and responses will be will be added in the dynamic +// ``metadata`` with the same layout of the message. + // For the default `FIRST_AND_LAST` mode, it will be like: + +// .. code-block:: json + // { // "requests":{ // "first":{ // "foo": "val_foo1", -// ... // } // "last":{ // "foo": "val_foo3", -// ... // } // }, // "responses":{ // "first":{ // "baz": "val_baz1", -// ... // } // "last":{ // "baz": "val_foo3", -// ... // } // } // } + +// Example for `FIRST_AND_LAST` mode +// --------------------------------- // -// -// # Example for `FIRST_AND_LAST` mode // Let's say we have the following definition for the bi-streaming request // `pkg.svc.Method`. // @@ -111,7 +124,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // // message Msg { // string bar = 1; -// string not_logged = 2; +// string not_extracted = 2; // } // // This is the filter config in JSON. @@ -121,15 +134,15 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // { // "descriptor_set":{}, // "mode": "FIRST_AND_LAST", -// "logging_by_method":{ +// "extraction_by_method":{ // "pkg.svc.Method":{ -// "request_logging_by_field":{ -// "foo":"LOG", -// "nested.doubled_nested.bar":"LOG", -// "redacted":"LOG_REDACT" +// "request_extraction_by_field":{ +// "foo":"EXTRACT", +// "nested.doubled_nested.bar":"EXTRACT", +// "redacted":"EXTRACT_REDACT" // }, -// "response_logging_by_field":{ -// "bar":"LOG", +// "response_extraction_by_field":{ +// "bar":"EXTRACT", // } // } // } @@ -142,18 +155,18 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // // { // "foo": "val_foo1", -// "nested": { "double_nested": {"bar": "val_bar1", "not_logged": "val_not_logged1"}, -// "redacted": { "bar": "val_redacted_bar1"} +// "nested": { "double_nested": {"bar": "val_bar1", "not_extracted": +// "val_not_extracted1"}, "redacted": { "bar": "val_redacted_bar1"} // } // { // "foo": "val_foo2", -// "nested": { "double_nested": {"bar": "val_bar2", "not_logged": "val_not_logged2"}, -// "redacted": { "bar": "val_redacted_bar2"} +// "nested": { "double_nested": {"bar": "val_bar2", "not_extracted": +// "val_not_extracted2"}, "redacted": { "bar": "val_redacted_bar2"} // } // { // "foo": "val_foo3", -// "nested": { "double_nested": {"bar": "val_bar3", "not_logged": "val_not_logged3"}, -// "redacted": { "bar": "val_redacted_bar3"} +// "nested": { "double_nested": {"bar": "val_bar3", "not_extracted": +// "val_not_extracted3"}, "redacted": { "bar": "val_redacted_bar3"} // } // // the filter receives the following `MethodResponse` message in @@ -172,7 +185,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // } // // The filter will write the following dynamic -// metadata(`envoy.filters.http.proto_message_logging`) in JSON. +// metadata(`envoy.filters.http.proto_message_extraction`) in JSON. // // .. code-block:: json // @@ -199,11 +212,11 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // } // } -message ProtoMessageLoggingConfig { - enum LogMode { - LogMode_UNSPECIFIED = 0; +message ProtoMessageExtractionConfig { + enum ExtractMode { + ExtractMode_UNSPECIFIED = 0; - // The filter will log the first and the last message for + // The filter will extract the first and the last message for // for streaming cases, containing // client-side streaming, server-side streaming or bi-directional streaming. FIRST_AND_LAST = 1; @@ -216,40 +229,41 @@ message ProtoMessageLoggingConfig { config.core.v3.DataSource data_source = 1; // Unimplemented, the key of proto descriptor TypedMetadata. - // Among filters depending on the proto descriptor, we can have a TypedMetadata - // for proto descriptors, so that these filters can share one copy of proto - // descriptor in memory. + // Among filters depending on the proto descriptor, we can have a + // TypedMetadata for proto descriptors, so that these filters can share one + // copy of proto descriptor in memory. string proto_descriptor_typed_metadata = 2; } - LogMode mode = 3; + ExtractMode mode = 3; - // Specify the message logging info. + // Specify the message extraction info. // The key is the fully qualified gRPC method name. // ``${package}.${Service}.${Method}``, like // ``endpoints.examples.bookstore.BookStore.GetShelf`` // - // The value is the message logging information for individual gRPC methods. - map logging_by_method = 4; + // The value is the message extraction information for individual gRPC + // methods. + map extraction_by_method = 4; } // This message can be used to support per route config approach later even // though the Istio doesn't support that so far. -message MethodLogging { - enum LogDirective { - LogDirective_UNSPECIFIED = 0; +message MethodExtraction { + enum ExtractDirective { + ExtractDirective_UNSPECIFIED = 0; - // The value of this field will be logged. - LOG = 1; + // The value of this field will be extracted. + EXTRACT = 1; // It should be only annotated on Message type fields so if the field isn't - // empty, an empty Struct will be logged. - LOG_REDACT = 2; + // empty, an empty Struct will be extracted. + EXTRACT_REDACT = 2; } - // The mapping of field path to its LogDirective for request messages - map request_logging_by_field = 2; + // The mapping of field path to its ExtractDirective for request messages + map request_extraction_by_field = 2; - // The mapping of field path to its LogDirective for response messages - map response_logging_by_field = 3; + // The mapping of field path to its ExtractDirective for response messages + map response_extraction_by_field = 3; } diff --git a/api/versioning/BUILD b/api/versioning/BUILD index bb27ffaea41d..98e2ec21f881 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -138,7 +138,7 @@ proto_library( "//envoy/extensions/filters/http/oauth2/v3:pkg", "//envoy/extensions/filters/http/on_demand/v3:pkg", "//envoy/extensions/filters/http/original_src/v3:pkg", - "//envoy/extensions/filters/http/proto_message_logging/v3:pkg", + "//envoy/extensions/filters/http/proto_message_extraction/v3:pkg", "//envoy/extensions/filters/http/rate_limit_quota/v3:pkg", "//envoy/extensions/filters/http/ratelimit/v3:pkg", "//envoy/extensions/filters/http/rbac/v3:pkg", diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 4bc96ec4a630..e3134720dee4 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -966,7 +966,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( strip_prefix = "grpc-httpjson-transcoding-{version}", urls = ["https://github.com/grpc-ecosystem/grpc-httpjson-transcoding/archive/{version}.tar.gz"], use_category = ["dataplane_ext"], - extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction"], + extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction", "envoy.filters.http.proto_message_extraction"], release_date = "2023-06-07", cpe = "N/A", license = "Apache-2.0", @@ -981,7 +981,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( strip_prefix = "proto-converter-{version}", urls = ["https://github.com/grpc-ecosystem/proto-converter/archive/{version}.zip"], use_category = ["dataplane_ext"], - extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction"], + extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction", "envoy.filters.http.proto_message_extraction"], release_date = "2024-06-25", cpe = "N/A", license = "Apache-2.0", @@ -996,7 +996,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( strip_prefix = "proto-field-extraction-{version}", urls = ["https://github.com/grpc-ecosystem/proto-field-extraction/archive/{version}.zip"], use_category = ["dataplane_ext"], - extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction"], + extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction", "envoy.filters.http.proto_message_extraction"], release_date = "2024-07-10", cpe = "N/A", license = "Apache-2.0", @@ -1006,13 +1006,13 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "proto_processing_lib", project_desc = "Library that provides utility functionality for proto field scrubbing", project_url = "https://github.com/grpc-ecosystem/proto_processing_lib", - version = "43bd06909a4ccfa5788dc8bf850e40102166e63f", - sha256 = "8f99bd6f568c6fddcba1ed51290eaa5556a0ad374524ba6f532c6c828a73214b", + version = "967aa1dec2e0aeab83f54b782c9aa3643d376406", + sha256 = "8f27248d90d8e558b85f0730fbb2684828ed1b093f3be692fc0b418e50e4145d", strip_prefix = "proto_processing_lib-{version}", urls = ["https://github.com/grpc-ecosystem/proto_processing_lib/archive/{version}.zip"], use_category = ["dataplane_ext"], - extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction"], - release_date = "2024-08-06", + extensions = ["envoy.filters.http.grpc_json_transcoder", "envoy.filters.http.grpc_field_extraction", "envoy.filters.http.proto_message_extraction"], + release_date = "2024-08-23", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/grpc-ecosystem/proto_processing_lib/blob/{version}/LICENSE", @@ -1026,7 +1026,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( strip_prefix = "ocp-diag-core-{version}/apis/c++", urls = ["https://github.com/opencomputeproject/ocp-diag-core/archive/{version}.zip"], use_category = ["dataplane_ext"], - extensions = ["envoy.filters.http.grpc_field_extraction"], + extensions = ["envoy.filters.http.grpc_field_extraction", "envoy.filters.http.proto_message_extraction"], release_date = "2023-05-05", cpe = "N/A", license = "Apache-2.0", diff --git a/docs/root/configuration/http/http_filters/http_filters.rst b/docs/root/configuration/http/http_filters/http_filters.rst index d9f93e0262f6..ebb07a3fa750 100644 --- a/docs/root/configuration/http/http_filters/http_filters.rst +++ b/docs/root/configuration/http/http_filters/http_filters.rst @@ -52,6 +52,7 @@ HTTP filters oauth2_filter on_demand_updates_filter original_src_filter + proto_message_extraction_filter rate_limit_filter rate_limit_quota_filter rbac_filter diff --git a/docs/root/configuration/http/http_filters/proto_message_extraction_filter.rst b/docs/root/configuration/http/http_filters/proto_message_extraction_filter.rst new file mode 100644 index 000000000000..be8662381b4a --- /dev/null +++ b/docs/root/configuration/http/http_filters/proto_message_extraction_filter.rst @@ -0,0 +1,111 @@ +.. _config_http_filters_proto_message_extraction: + +Proto Message Extraction +======================== + +* gRPC :ref:`architecture overview ` +* This filter should be configured with the type URL ``type.googleapis.com/envoy.extensions.filters.http.proto_message_extraction.v3.ProtoMessageExtractionConfig``. +* :ref:`v3 API reference `. + +ProtoMessageExtraction filter supports extracting gRPC +requests/responses (proto messages) into google.protobuf.Struct and storing +results in the dynamic metadata `envoy.filters.http.proto_message_extraction` +for later access. + +Use Case +-------- + +The ProtoMessageExtraction filter is particularly useful in scenarios where +sensitive or detailed logging of gRPC requests and responses is required. +In Client-Side Streaming or Server-Side Streaming, the filter can store the +first and last messages, which can later be used for logging or for obtaining +a comprehensive view of the data flow. + +Assumptions +----------- + +This filter assumes it is only applicable for gRPC with Protobuf as payload. + +Process Flow +------------ + +On the request and response path, it will check + +1. if the incoming gRPC request/response is configured, the filter tries to: + + a. buffer the incoming data to complete protobuf messages + b. extract individual protobuf messages according to directives + c. write the result into the dynamic metadata + d. pass through the request/response data + +2. otherwise, pass through the request. + +The extraction process in this filter is not on the critical path, as it does not +modify the request or response. The filter extracts the specified fields, +writes them to dynamic metadata, and then passes the request/response +through without modification. + +Config Requirements +------------------- + +Here are config requirements + +1. the extract target field should be among the following primitive types: +`string`, `uint32`, `uint64`, `int32`, `int64`, `sint32`, `sint64`, +`fixed32`, `fixed64`, `sfixed32`, `sfixed64`, `float`, `double`. + +2. the target field could be repeated. + +3. the intermediate type could also be repeated. + +Output Format +------------- + +The extracted requests and responses will be will be added in the dynamic +``metadata`` with the same layout of the message. + +For the default `FIRST_AND_LAST` mode, the output will be like: + +Case: Non-Streaming requests/response + +.. code-block:: json + + { + "requests":{ + "first":{ + "foo": "val_foo1", + } + }, + "responses":{ + "first":{ + "baz": "val_baz1", + } + } + } + + +Case: Streaming requests/response + +.. code-block:: json + + { + "requests":{ + "first":{ + "foo": "val_foo1", + } + "last":{ + "foo": "val_foo3", + } + }, + "responses":{ + "first":{ + "baz": "val_baz1", + } + "last":{ + "baz": "val_foo3", + } + } + } + +For more details, please refer to the +:ref:`v3 API reference `. diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index ee10c1279eac..8c1175d929a7 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -164,7 +164,7 @@ EXTENSIONS = { "envoy.filters.http.header_to_metadata": "//source/extensions/filters/http/header_to_metadata:config", "envoy.filters.http.health_check": "//source/extensions/filters/http/health_check:config", "envoy.filters.http.ip_tagging": "//source/extensions/filters/http/ip_tagging:config", - "envoy.filters.http.json_to_metadata": "//source/extensions/filters/http/json_to_metadata:config", + "envoy.filters.http.json_to_metadata": "//source/extensions/filters/http/json_to_metadata:config", "envoy.filters.http.jwt_authn": "//source/extensions/filters/http/jwt_authn:config", "envoy.filters.http.rate_limit_quota": "//source/extensions/filters/http/rate_limit_quota:config", # Disabled by default. kill_request is not built into most prebuilt images. @@ -176,6 +176,7 @@ EXTENSIONS = { "envoy.filters.http.oauth2": "//source/extensions/filters/http/oauth2:config", "envoy.filters.http.on_demand": "//source/extensions/filters/http/on_demand:config", "envoy.filters.http.original_src": "//source/extensions/filters/http/original_src:config", + "envoy.filters.http.proto_message_extraction": "//source/extensions/filters/http/proto_message_extraction:config", "envoy.filters.http.ratelimit": "//source/extensions/filters/http/ratelimit:config", "envoy.filters.http.rbac": "//source/extensions/filters/http/rbac:config", "envoy.filters.http.router": "//source/extensions/filters/http/router:config", diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 35893425a135..894d9939c149 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -498,6 +498,13 @@ envoy.filters.http.original_src: status: alpha type_urls: - envoy.extensions.filters.http.original_src.v3.OriginalSrc +envoy.filters.http.proto_message_extraction: + categories: + - envoy.filters.http + security_posture: unknown + status: alpha + type_urls: + - envoy.extensions.filters.http.proto_message_extraction.v3.ProtoMessageExtractionConfig envoy.filters.http.ratelimit: categories: - envoy.filters.http diff --git a/source/extensions/filters/http/proto_message_extraction/BUILD b/source/extensions/filters/http/proto_message_extraction/BUILD new file mode 100644 index 000000000000..bc57c1c2cda4 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/BUILD @@ -0,0 +1,90 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_library( + name = "extractor", + hdrs = ["extractor.h"], + external_deps = ["grpc_transcoding"], + deps = [ + "@com_google_absl//absl/status", + "@com_google_protofieldextraction//:all_libs", + "@envoy_api//envoy/extensions/filters/http/proto_message_extraction/v3:pkg_cc_proto", + ], +) + +envoy_cc_library( + name = "extractor_impl", + srcs = ["extractor_impl.cc"], + hdrs = ["extractor_impl.h"], + deps = [ + "extractor", + "//source/common/common:minimal_logger_lib", + "//source/common/protobuf", + "//source/extensions/filters/http/proto_message_extraction/extraction_util:proto_extractor", + "@com_google_absl//absl/base:core_headers", + "@com_google_absl//absl/log", + "@com_google_absl//absl/log:check", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:string_view", + "@com_google_protoconverter//:all", + "@com_google_protofieldextraction//:all_libs", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber:field_mask_path_checker", + "@envoy_api//envoy/extensions/filters/http/proto_message_extraction/v3:pkg_cc_proto", + ], +) + +envoy_cc_extension( + name = "filter_config", + srcs = ["filter_config.cc"], + hdrs = ["filter_config.h"], + deps = [ + ":extractor_impl", + "//source/common/grpc:common_lib", + "//source/extensions/filters/http/common:factory_base_lib", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/log", + "@com_google_absl//absl/strings:string_view", + "@com_google_protoconverter//:all", + "@com_google_protofieldextraction//:all_libs", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber:field_mask_path_checker", + "@envoy_api//envoy/extensions/filters/http/proto_message_extraction/v3:pkg_cc_proto", + ], +) + +envoy_cc_library( + name = "filter", + srcs = ["filter.cc"], + hdrs = ["filter.h"], + deps = [ + "extractor_impl", + "filter_config", + "//source/common/http:codes_lib", + "//source/extensions/filters/http/common:pass_through_filter_lib", + "//source/extensions/filters/http/grpc_field_extraction/message_converter:message_converter_lib", + "@envoy_api//envoy/extensions/filters/http/proto_message_extraction/v3:pkg_cc_proto", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + deps = [ + "extractor_impl", + "filter", + "filter_config", + "@envoy_api//envoy/extensions/filters/http/proto_message_extraction/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/filters/http/proto_message_extraction/config.cc b/source/extensions/filters/http/proto_message_extraction/config.cc new file mode 100644 index 000000000000..bdc5a60606a2 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/config.cc @@ -0,0 +1,39 @@ +#include "source/extensions/filters/http/proto_message_extraction/config.h" + +#include +#include + +#include "envoy/http/filter.h" +#include "envoy/registry/registry.h" + +#include "source/common/http/codes.h" +#include "source/common/http/header_utility.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor_impl.h" +#include "source/extensions/filters/http/proto_message_extraction/filter.h" + +#include "proto_field_extraction/message_data/cord_message_data.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +FilterFactoryCreator::FilterFactoryCreator() : FactoryBase(kFilterName) {} + +Envoy::Http::FilterFactoryCb FilterFactoryCreator::createFilterFactoryFromProtoTyped( + const envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig& proto_config, + const std::string&, Envoy::Server::Configuration::FactoryContext& context) { + auto filter_config = std::make_shared( + proto_config, std::make_unique(), context.serverFactoryContext().api()); + return [filter_config](Envoy::Http::FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamFilter(std::make_shared(*filter_config)); + }; +} + +REGISTER_FACTORY(FilterFactoryCreator, Envoy::Server::Configuration::NamedHttpFilterConfigFactory); + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/config.h b/source/extensions/filters/http/proto_message_extraction/config.h new file mode 100644 index 000000000000..61224df92092 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/config.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.h" +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.validate.h" +#include "envoy/http/filter.h" + +#include "source/extensions/filters/http/common/factory_base.h" +#include "source/extensions/filters/http/proto_message_extraction/filter_config.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +class FilterFactoryCreator : public Envoy::Extensions::HttpFilters::Common::FactoryBase< + envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig> { +public: + FilterFactoryCreator(); + +private: + Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped( + const envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig& proto_config, + const std::string&, Envoy::Server::Configuration::FactoryContext&) override; +}; +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/extraction_util/BUILD b/source/extensions/filters/http/proto_message_extraction/extraction_util/BUILD new file mode 100644 index 000000000000..3e43405088b0 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/extraction_util/BUILD @@ -0,0 +1,63 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_library( + name = "proto_extractor_interface", + hdrs = [ + "proto_extractor_interface.h", + ], + deps = [ + "//source/common/protobuf", + "//source/common/protobuf:cc_wkt_protos", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_protofieldextraction//:all_libs", + ], +) + +envoy_cc_library( + name = "extraction_util", + srcs = [ + "extraction_util.cc", + ], + hdrs = [ + "extraction_util.h", + ], + external_deps = ["grpc_transcoding"], + deps = [ + ":proto_extractor_interface", + "//source/common/common:regex_lib", + "//source/common/protobuf", + "//source/common/protobuf:cc_wkt_protos", + "@com_google_protoconverter//:all", + "@com_google_protofieldextraction//:all_libs", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber", + ], +) + +envoy_cc_library( + name = "proto_extractor", + srcs = [ + "proto_extractor.cc", + ], + hdrs = [ + "proto_extractor.h", + ], + deps = [ + ":extraction_util", + ":proto_extractor_interface", + "//source/common/common:regex_lib", + "//source/common/protobuf", + "//source/common/protobuf:cc_wkt_protos", + "@com_google_protoconverter//:all", + "@com_google_protofieldextraction//:all_libs", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber:field_mask_path_checker", + ], +) diff --git a/source/extensions/filters/http/proto_message_logging/logging_util/logging_util.cc b/source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.cc similarity index 79% rename from source/extensions/filters/http/proto_message_logging/logging_util/logging_util.cc rename to source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.cc index 55abc9b7e8c2..0e27624856b1 100644 --- a/source/extensions/filters/http/proto_message_logging/logging_util/logging_util.cc +++ b/source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.cc @@ -1,4 +1,4 @@ -#include "source/extensions/filters/http/proto_message_logging/logging_util/logging_util.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.h" #include #include @@ -9,6 +9,8 @@ #include #include +#include "source/common/common/logger.h" +#include "source/common/http/status.h" #include "source/common/protobuf/protobuf.h" #include "absl/container/flat_hash_map.h" @@ -22,6 +24,7 @@ #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "absl/types/span.h" +#include "grpc_transcoding/type_helper.h" #include "proto_field_extraction/field_extractor/field_extractor.h" #include "proto_field_extraction/message_data/message_data.h" #include "proto_processing_lib/proto_scrubber/proto_scrubber.h" @@ -39,7 +42,7 @@ namespace Envoy { namespace Extensions { namespace HttpFilters { -namespace ProtoMessageLogging { +namespace ProtoMessageExtraction { namespace { @@ -49,6 +52,7 @@ using ::Envoy::Protobuf::Type; using ::Envoy::Protobuf::field_extraction::FieldExtractor; using ::Envoy::Protobuf::internal::WireFormatLite; using ::Envoy::Protobuf::io::CodedInputStream; +using ::Envoy::Protobuf::io::CodedOutputStream; using ::Envoy::Protobuf::io::CordOutputStream; using ::Envoy::Protobuf::util::JsonParseOptions; using ::Envoy::Protobuf::util::TypeResolver; @@ -57,6 +61,7 @@ using ::Envoy::Protobuf::util::converter::JsonObjectWriter; using ::Envoy::Protobuf::util::converter::ProtoStreamObjectSource; using ::Envoy::ProtobufWkt::Struct; using ::Envoy::ProtobufWkt::Value; +using ::google::grpc::transcoding::TypeHelper; using ::proto_processing_lib::proto_scrubber::ProtoScrubber; std::string kLocationRegionExtractorPattern = R"((?:^|/)(?:locations|regions)/([^/]+))"; @@ -80,16 +85,18 @@ std::string GetLabelName(absl::string_view value) { return absl::StrReplaceAll(value, {{"{", ""}, {"}", ""}}); } -// Singleton mapping of string to AuditDirective. -const absl::flat_hash_map& StringToDirectiveMap() { - static auto* string_to_directive_map = new absl::flat_hash_map({ - {kAuditRedact, AuditDirective::AUDIT_REDACT}, - {kAudit, AuditDirective::AUDIT}, - }); +// Singleton mapping of string to ExtractedMessageDirective. +const absl::flat_hash_map& StringToDirectiveMap() { + static auto* string_to_directive_map = + new absl::flat_hash_map({ + {kExtractRedact, ExtractedMessageDirective::EXTRACT_REDACT}, + {kExtract, ExtractedMessageDirective::EXTRACT}, + }); return *string_to_directive_map; } -absl::optional AuditDirectiveFromString(absl::string_view directive) { +absl::optional +ExtractedMessageDirectiveFromString(absl::string_view directive) { if (StringToDirectiveMap().contains(directive)) { return StringToDirectiveMap().at(directive); } @@ -219,7 +226,7 @@ int64_t ExtractRepeatedFieldSize(const Type& type, return num_response_items; } - // AUDIT_SIZE directive should only be applied to one field. Tools + // SCRUB directive should only be applied to one field. Tools // framework validation should check this case. DCHECK_EQ(1, field_mask->paths_size()); @@ -227,8 +234,8 @@ int64_t ExtractRepeatedFieldSize(const Type& type, absl::StatusOr status_or_size = ExtractRepeatedFieldSizeHelper(field_extractor, field_mask->paths(0), message); if (!status_or_size.ok()) { - LOG(WARNING) << "Failed to extract repeated field size of '" << field_mask->paths(0) - << "' from proto '" << type.name() << "': " << status_or_size.status(); + ENVOY_LOG_MISC(debug, "Failed to extract repeated field size of '{}' from proto '{}': {}", + field_mask->paths(0), type.name(), status_or_size.status()); } else { num_response_items = *status_or_size; } @@ -272,8 +279,6 @@ void RedactPath(std::vector::const_iterator path_begin, return; } - // Fail if trying to redact non-message-type field. - CHECK(field_value.has_struct_value()) << "Cannot redact non-message-type field " << field; RedactPath(path_begin, path_end, field_value.mutable_struct_value()); } @@ -296,7 +301,7 @@ absl::StatusOr FindSingularLastValue(const Field* field, while (FieldExtractor::SearchField(*field, input_stream)) { if (input_stream->CurrentPosition() == position) { return absl::InvalidArgumentError( - "The request message is malformed with endless values for a single field."); + "Malformed request with endless values for a single field."); } position = input_stream->CurrentPosition(); if (field->kind() == Field::TYPE_STRING) { @@ -385,35 +390,69 @@ absl::Status RedactStructRecursively(std::vector::const_iterator pa (*fields)[current_piece].mutable_struct_value()); } -absl::StatusOr -IsMessageFieldPathPresent(const Protobuf::Type& type, - std::function type_finder, - const std::string& path, - const Protobuf::field_extraction::MessageData& message) { - if (path.empty()) { - return absl::InvalidArgumentError("Field path cannot be empty."); +absl::Status ConvertToStruct(const Protobuf::field_extraction::MessageData& message, + const Envoy::ProtobufWkt::Type& type, + ::Envoy::Protobuf::util::TypeResolver* type_resolver, + Struct* message_struct) { + // Convert from message data to JSON using absl::Cord. + auto in_stream = message.CreateCodedInputStreamWrapper(); + ProtoStreamObjectSource os(&in_stream->Get(), type_resolver, type); + os.set_max_recursion_depth(kProtoTranslationMaxRecursionDepth); + + CordOutputStream cord_out_stream; + CodedOutputStream out_stream(&cord_out_stream); + JsonObjectWriter json_object_writer("", &out_stream); + + RETURN_IF_ERROR(os.WriteTo(&json_object_writer)); + out_stream.Trim(); + + // Convert from JSON (in absl::Cord) to Struct. + JsonParseOptions options; + auto status = Protobuf::util::JsonStringToMessage(cord_out_stream.Consume().Flatten(), + message_struct, options); + if (!status.ok()) { + return absl::InternalError(absl::StrCat("Failed to parse Struct from formatted JSON of '", + type.name(), "' message. Status: ", status.ToString())); } - auto extract_func = [](const Type& /*enclosing_type*/, const Field* field, - CodedInputStream* input_stream) -> absl::StatusOr { - if (field->kind() != Field::TYPE_MESSAGE) { - return absl::InvalidArgumentError( - absl::Substitute("Field '$0' is not a message type field.", field->name())); - } else if (field->cardinality() == Field::CARDINALITY_REPEATED) { - return absl::InvalidArgumentError( - absl::Substitute("Field '$0' is not a singular field.", field->name())); - } else { // singular message field - return FieldExtractor::SearchField(*field, input_stream); - } - }; + (*message_struct->mutable_fields())[kTypeProperty].set_string_value( + google::protobuf::util::converter::GetFullTypeWithUrl(type.name())); + return absl::OkStatus(); +} - FieldExtractor field_extractor(&type, std::move(type_finder)); - Protobuf::field_extraction::MessageData& msg( - const_cast(message)); - return field_extractor.ExtractFieldInfo(path, msg.CreateCodedInputStreamWrapper()->Get(), - extract_func); +bool ScrubToStruct(const proto_processing_lib::proto_scrubber::ProtoScrubber* scrubber, + const Envoy::ProtobufWkt::Type& type, + const ::google::grpc::transcoding::TypeHelper& type_helper, + Protobuf::field_extraction::MessageData* message, + Envoy::ProtobufWkt::Struct* message_struct) { + message_struct->Clear(); + + // When scrubber or message is nullptr, it indicates that there's nothing to + // scrub and the whole message should be filtered. + if (scrubber == nullptr || message == nullptr) { + return false; + } + + // Scrub the message. + absl::Status status = scrubber->Scrub(message); + if (!status.ok()) { + ENVOY_LOG_MISC(debug, absl::StrCat("Failed to scrub ", type.name(), + " proto. Status: ", status.ToString())); + return false; + } + + // Convert the scrubbed message to proto. + status = ConvertToStruct(*message, type, type_helper.Resolver(), message_struct); + if (!status.ok()) { + ENVOY_LOG_MISC(debug, absl::StrCat("Failed to convert ", type.name(), + " proto to google.protobuf.Struct: ", status.ToString())); + return false; + } + + return !IsEmptyStruct(*message_struct); } -} // namespace ProtoMessageLogging + +} // namespace ProtoMessageExtraction } // namespace HttpFilters } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_logging/logging_util/logging_util.h b/source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.h similarity index 73% rename from source/extensions/filters/http/proto_message_logging/logging_util/logging_util.h rename to source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.h index d826a3c55cd2..1442657e6183 100644 --- a/source/extensions/filters/http/proto_message_logging/logging_util/logging_util.h +++ b/source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.h @@ -7,7 +7,7 @@ #include #include "source/common/protobuf/protobuf.h" -#include "source/extensions/filters/http/proto_message_logging/logging_util/proto_scrubber_interface.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" #include "absl/base/attributes.h" #include "absl/container/flat_hash_map.h" @@ -18,6 +18,7 @@ #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "google/api/monitored_resource.pb.h" +#include "grpc_transcoding/type_helper.h" #include "proto_field_extraction/field_extractor/field_extractor.h" #include "proto_field_extraction/message_data/message_data.h" #include "proto_processing_lib/proto_scrubber/proto_scrubber.h" @@ -26,16 +27,16 @@ namespace Envoy { namespace Extensions { namespace HttpFilters { -namespace ProtoMessageLogging { +namespace ProtoMessageExtraction { // The type property value that will be included into the converted Struct. constexpr char kTypeProperty[] = "@type"; ABSL_CONST_INIT const char* const kTypeServiceBaseUrl = "type.googleapis.com"; -constexpr char kAuditRedact[] = "AUDIT_REDACT"; +constexpr char kExtractRedact[] = "EXTRACT_REDACT"; -constexpr char kAudit[] = "AUDIT"; +constexpr char kExtract[] = "EXTRACT"; constexpr int kMaxRedactedPathDepth = 10; @@ -43,8 +44,6 @@ constexpr int kProtoTranslationMaxRecursionDepth = 64; ABSL_CONST_INIT const char* const kStructTypeUrl = "type.googleapis.com/google.protobuf.Struct"; -// class proto_processing_lib::proto_scrubber::ProtoScrubber; - bool IsEmptyStruct(const ProtobufWkt::Struct& message_struct); bool IsLabelName(absl::string_view value); @@ -54,10 +53,11 @@ bool IsLabelName(absl::string_view value); // name, we just remove the brackets. std::string GetLabelName(absl::string_view value); -// Singleton mapping of string to AuditDirective. -const absl::flat_hash_map& StringToDirectiveMap(); +// Singleton mapping of string to ExtractedMessageDirective. +const absl::flat_hash_map& StringToDirectiveMap(); -absl::optional AuditDirectiveFromString(absl::string_view directive); +absl::optional +ExtractedMessageDirectiveFromString(absl::string_view directive); // Returns a mapping of monitored resource label keys to their values. void GetMonitoredResourceLabels(absl::string_view label_extractor, @@ -118,13 +118,27 @@ absl::Status RedactStructRecursively(std::vector::const_iterator pa std::vector::const_iterator path_pieces_end, ProtobufWkt::Struct* message_struct); -absl::StatusOr -IsMessageFieldPathPresent(const Protobuf::Type& type, - std::function type_finder, - const std::string& path, - const Protobuf::field_extraction::MessageData& message); +// Converts given proto message to Struct. It also adds +// a "@type" property with proto type url to the generated Struct. Expects the +// TypeResolver to handle types prefixed with "type.googleapis.com/". +absl::Status ConvertToStruct(const Protobuf::field_extraction::MessageData& message, + const Envoy::ProtobufWkt::Type& type, + ::Envoy::Protobuf::util::TypeResolver* type_resolver, + ::Envoy::ProtobufWkt::Struct* message_struct); -} // namespace ProtoMessageLogging +// Extracts given proto message and convert the extracted proto to Struct. +// +// Returns true if succeeds, otherwise, returns false in case of +// (1) `scrubber` is nullptr; +// (2) error during scrubbing/converting; +// (3) the message is empty after scrubbing; +bool ScrubToStruct(const proto_processing_lib::proto_scrubber::ProtoScrubber* scrubber, + const Envoy::ProtobufWkt::Type& type, + const ::google::grpc::transcoding::TypeHelper& type_helper, + Protobuf::field_extraction::MessageData* message, + Envoy::ProtobufWkt::Struct* message_struct); + +} // namespace ProtoMessageExtraction } // namespace HttpFilters } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.cc b/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.cc new file mode 100644 index 000000000000..10b3c4bc35ca --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.cc @@ -0,0 +1,209 @@ +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.h" + +#include +#include +#include +#include +#include +#include + +#include "source/common/common/logger.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" + +#include "absl/log/check.h" +#include "absl/log/log.h" +#include "absl/memory/memory.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "absl/types/span.h" +#include "google/protobuf/util/converter/json_objectwriter.h" +#include "google/protobuf/util/converter/protostream_objectsource.h" +#include "google/protobuf/util/converter/utility.h" +#include "grpc_transcoding/type_helper.h" +#include "proto_field_extraction/message_data/cord_message_data.h" +#include "proto_field_extraction/message_data/message_data.h" +#include "proto_processing_lib/proto_scrubber/field_checker_interface.h" +#include "proto_processing_lib/proto_scrubber/field_mask_path_checker.h" +#include "proto_processing_lib/proto_scrubber/proto_scrubber.h" +#include "proto_processing_lib/proto_scrubber/proto_scrubber_enums.h" +#include "proto_processing_lib/proto_scrubber/unknown_field_checker.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +using ::Envoy::Protobuf::FieldMask; +using ::Envoy::Protobuf::util::JsonParseOptions; +using ::Envoy::ProtobufUtil::FieldMaskUtil; +using ::Envoy::ProtobufWkt::Struct; +using ::Envoy::ProtobufWkt::Type; +using ::google::grpc::transcoding::TypeHelper; +using ::google::protobuf::util::converter::JsonObjectWriter; +using ::google::protobuf::util::converter::ProtoStreamObjectSource; +using ::google::protobuf::util::converter::TypeInfo; +using ::proto_processing_lib::proto_scrubber::FieldCheckerInterface; +using ::proto_processing_lib::proto_scrubber::FieldMaskPathChecker; +using ::proto_processing_lib::proto_scrubber::ScrubberContext; +using ::proto_processing_lib::proto_scrubber::UnknownFieldChecker; + +const google::protobuf::FieldMask& +ProtoExtractor::FindWithDefault(ExtractedMessageDirective directive) { + static const google::protobuf::FieldMask default_field_mask; + + auto it = directives_mapping_.find(directive); + if (it != directives_mapping_.end()) { + return it->second; + } else { + return default_field_mask; + } +} + +ProtoExtractor::ProtoExtractor(ScrubberContext scrubber_context, const TypeHelper* type_helper, + const Type* message_type, + const FieldPathToExtractType& field_policies) { + type_helper_ = type_helper; + message_type_ = message_type; + for (const auto& field_policy : field_policies) { + for (const auto& directive : field_policy.second) { + directives_mapping_[directive].add_paths(field_policy.first); + } + } + + // Initialize type finder. + type_finder_ = [&](const std::string& type_url) { + const Type* result = nullptr; + absl::StatusOr type = type_helper_->Info()->GetTypeByTypeUrl(type_url); + if (type.ok()) { + result = *type; + } + return result; + }; + + for (const auto& directive : directives_mapping_) { + ENVOY_LOG_MISC(debug, "Extraction Directive: {}: {}", static_cast(directive.first), + directive.second.DebugString()); + } + + // Initialize proto scrubber that retains fields annotated with EXTRACT and + // EXTRACT_REDACT. Fields that are EXTRACT_REDACT will be redacted after + // extraction. + Protobuf::FieldMask extracted_message_field_mask; + FieldMaskUtil::Union(FindWithDefault(ExtractedMessageDirective::EXTRACT), + FindWithDefault(ExtractedMessageDirective::EXTRACT_REDACT), + &extracted_message_field_mask); + + // Only create the scrubber if there are fields to retain. + if (!extracted_message_field_mask.paths().empty()) { + field_checker_ = std::make_unique(message_type_, type_finder_); + + if (!extracted_message_field_mask.paths().empty()) { + absl::Status status = field_checker_->AddOrIntersectFieldPaths( + std::vector(extracted_message_field_mask.paths().begin(), + extracted_message_field_mask.paths().end())); + if (!status.ok()) { + ENVOY_LOG_MISC(debug, "Failed to create proto scrubber. Status: {}", status); + } + } + scrubber_ = std::make_unique( + message_type_, type_finder_, + std::vector{field_checker_.get(), + UnknownFieldChecker::GetDefault()}, + scrubber_context); + } +} + +std::unique_ptr +ProtoExtractor::Create(ScrubberContext scrubber_context, const TypeHelper* type_helper, + const Type* message_type, const FieldPathToExtractType& field_policies) { + return absl::WrapUnique( + new ProtoExtractor(scrubber_context, type_helper, message_type, field_policies)); +} + +ExtractedMessageMetadata +ProtoExtractor::ExtractMessage(const Protobuf::field_extraction::MessageData& raw_message) const { + Protobuf::field_extraction::CordMessageData message_copy(raw_message.ToCord()); + + ExtractedMessageMetadata extracted_message_metadata; + + // Populate extracted message metadata before extracting message. + for (const auto& directive : directives_mapping_) { + const Protobuf::FieldMask& field_mask = directive.second; + switch (directive.first) { + case ExtractedMessageDirective::EXTRACT: + + GetTargetResourceOrTargetResourceCallback(field_mask, message_copy, /*callback=*/false, + &extracted_message_metadata); + + GetTargetResourceOrTargetResourceCallback(field_mask, message_copy, /*callback=*/true, + &extracted_message_metadata); + break; + default: + // No need to handle EXTRACT_REDACT, and method level directives. + break; + } + } + + // If there are no fields to retain, no need to scrub and only populate @type + // property. + if (scrubber_ == nullptr) { + (*extracted_message_metadata.extracted_message.mutable_fields())[kTypeProperty] + .set_string_value( + google::protobuf::util::converter::GetFullTypeWithUrl(message_type_->name())); + return extracted_message_metadata; + } + + bool success = ScrubToStruct(scrubber_.get(), *message_type_, *type_helper_, &message_copy, + &extracted_message_metadata.extracted_message); + + if (!success) { + ENVOY_LOG_MISC(debug, "Failed to extract message."); + } + + // Handle redacted fields. + auto redact_field_mask = directives_mapping_.find(ExtractedMessageDirective::EXTRACT_REDACT); + if (redact_field_mask != directives_mapping_.end()) { + // Convert the paths to be redacted into camel case first, since the + // resulting proto struct keys are in camel case. + std::vector redact_paths_camel_case; + for (const std::string& path : redact_field_mask->second.paths()) { + redact_paths_camel_case.push_back(google::protobuf::util::converter::ToCamelCase(path)); + } + RedactPaths(redact_paths_camel_case, &extracted_message_metadata.extracted_message); + } + return extracted_message_metadata; +} + +void ProtoExtractor::GetTargetResourceOrTargetResourceCallback( + const Protobuf::FieldMask& field_mask, const Protobuf::field_extraction::MessageData& message, + bool callback, ExtractedMessageMetadata* extracted_message_metadata) const { + // There should be only one target resource; this is checked at config + // compile time. + if (field_mask.paths().empty()) { + return; + } + + // The extraction can success but the string can be empty. + absl::StatusOr status_or_target_resource = + ExtractStringFieldValue(*message_type_, type_finder_, field_mask.paths(0), message); + if (!status_or_target_resource.ok()) { + ENVOY_LOG_MISC(debug, "Unable to extract target resource: {}", + status_or_target_resource.status()); + return; + } + + // Only set up the target resource callback if there is a non empty extracted + // value. + if (callback && !status_or_target_resource.value().empty()) { + extracted_message_metadata->target_resource_callback.emplace(*status_or_target_resource); + } else { + extracted_message_metadata->target_resource.emplace(*status_or_target_resource); + } +} + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.h b/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.h new file mode 100644 index 000000000000..82e37cccd4d2 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include +#include + +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" + +#include "absl/strings/string_view.h" +#include "grpc_transcoding/type_helper.h" +#include "proto_field_extraction/message_data/message_data.h" +#include "proto_processing_lib/proto_scrubber/field_mask_path_checker.h" +#include "proto_processing_lib/proto_scrubber/proto_scrubber.h" +#include "proto_processing_lib/proto_scrubber/proto_scrubber_enums.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +// An implementation of ProtoExtractorInterface for extraction +// using proto_processing_lib::proto_scrubber::ProtoScrubber. +class ProtoExtractor : public ProtoExtractorInterface { +public: + static std::unique_ptr + Create(proto_processing_lib::proto_scrubber::ScrubberContext scrubber_context, + const google::grpc::transcoding::TypeHelper* type_helper, + const ::Envoy::ProtobufWkt::Type* message_type, + const FieldPathToExtractType& field_policies); + + // Input message must be a message data. + ExtractedMessageMetadata + ExtractMessage(const Protobuf::field_extraction::MessageData& message) const override; + +private: + // Initializes an instance of ProtoExtractor using FieldPolicies. + ProtoExtractor(proto_processing_lib::proto_scrubber::ScrubberContext scrubber_context, + const google::grpc::transcoding::TypeHelper* type_helper, + const ::Envoy::ProtobufWkt::Type* message_type, + const FieldPathToExtractType& field_policies); + + // Populate the target resource or the target resource callback in the extracted message + // metadata. + void GetTargetResourceOrTargetResourceCallback( + const Protobuf::FieldMask& field_mask, const Protobuf::field_extraction::MessageData& message, + bool callback, ExtractedMessageMetadata* extracted_message_metadata) const; + + // Function to get the value associated with a key + const ProtobufWkt::FieldMask& FindWithDefault(ExtractedMessageDirective directive); + + const google::grpc::transcoding::TypeHelper* type_helper_; + const ::Envoy::ProtobufWkt::Type* message_type_; + // We use std::map instead of absl::flat_hash_map because of flat_hash_map's + // rehash behavior. + std::map directives_mapping_; + std::function type_finder_; + std::unique_ptr field_checker_; + std::unique_ptr scrubber_; + // A field path for 'location_selector' associated with the field marked as + // 'EXTRACT_TARGET_RESOURCE', or 'EXTRACT_TARGET_RESOURCE_CALLBACK' or empty value + // if not available. + std::string target_resource_location_selector_; +}; + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h b/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h new file mode 100644 index 000000000000..9c9e680501cc --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +#include "source/common/protobuf/protobuf.h" + +#include "absl/container/flat_hash_map.h" +#include "proto_field_extraction/message_data/message_data.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +// All valid field extraction directives. +enum class ExtractedMessageDirective { + EXTRACT_REDACT, + EXTRACT, +}; + +using FieldPathToExtractType = + absl::flat_hash_map>; + +// Metadata that can be captured during message extraction. +struct ExtractedMessageMetadata { + absl::optional num_response_items; + absl::optional target_resource; + absl::optional target_resource_callback; + absl::optional resource_location; + ProtobufWkt::Struct extracted_message; +}; + +// A proto-extraction interface for extracting that converts a source message +// to a proto Struct. +class ProtoExtractorInterface { +public: + // Extracts the message, then populates and returns ExtractedMessageMetadata + // that contains the extracted message and other extracted message metadata obtained during + // extraction. + virtual ExtractedMessageMetadata + ExtractMessage(const Protobuf::field_extraction::MessageData& message) const = 0; + + virtual ~ProtoExtractorInterface() = default; +}; + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/extractor.h b/source/extensions/filters/http/proto_message_extraction/extractor.h new file mode 100644 index 000000000000..8c1c9a95789c --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/extractor.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include +#include +#include + +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.h" +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.validate.h" + +#include "source/common/protobuf/protobuf.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "grpc_transcoding/type_helper.h" +#include "proto_field_extraction/message_data/message_data.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +using ::Envoy::Protobuf::Type; + +using TypeFinder = std::function; + +struct ExtractedMessageResult { + const TypeFinder* type_finder; + + std::vector<::Envoy::Extensions::HttpFilters::ProtoMessageExtraction::ExtractedMessageMetadata> + request_data; + std::vector<::Envoy::Extensions::HttpFilters::ProtoMessageExtraction::ExtractedMessageMetadata> + response_data; + + // Extracted struct with a "@type" field. + ProtobufWkt::Struct request_type_struct; + ProtobufWkt::Struct response_type_struct; +}; + +class Extractor { +public: + virtual ~Extractor() = default; + + // Extract EXTRACT fields on a request message. + // It only needs to be called for the first request message and the last + // for a client streaming call. + // It can be called on every message too if callers don't know which one + // is the last message. It only keeps the result from the first and the last. + virtual void processRequest(Protobuf::field_extraction::MessageData& message) = 0; + + // Extract EXTRACT fields on a response message. + // It only needs to be called for the first response message and the last + // for a server streaming call. + // It can be called on every message too if callers don't know which one + // is the last message. It only keeps the result from the first one the last. + virtual void processResponse(Protobuf::field_extraction::MessageData& message) = 0; + + virtual const ExtractedMessageResult& GetResult() const = 0; +}; + +using ExtractorPtr = std::unique_ptr; + +class ExtractorFactory { +public: + virtual ~ExtractorFactory() = default; + + virtual absl::StatusOr createExtractor( + const google::grpc::transcoding::TypeHelper& type_helper, const TypeFinder& type_finder, + std::string request_type_url, std::string response_type_url, + const envoy::extensions::filters::http::proto_message_extraction::v3::MethodExtraction& + method_extraction) const = 0; +}; + +using ExtractorFactoryPtr = std::unique_ptr; + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/extractor_impl.cc b/source/extensions/filters/http/proto_message_extraction/extractor_impl.cc new file mode 100644 index 000000000000..ad98b9177be9 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/extractor_impl.cc @@ -0,0 +1,125 @@ +#include "source/extensions/filters/http/proto_message_extraction/extractor_impl.h" + +#include +#include + +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.h" +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.validate.h" + +#include "source/common/common/logger.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor.h" + +#include "absl/base/attributes.h" +#include "absl/log/check.h" +#include "absl/log/log.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "grpc_transcoding/type_helper.h" +#include "proto_field_extraction/field_value_extractor/field_value_extractor_factory.h" +#include "proto_field_extraction/field_value_extractor/field_value_extractor_interface.h" +#include "proto_field_extraction/message_data/message_data.h" +#include "proto_processing_lib/proto_scrubber/proto_scrubber_enums.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { +namespace { + +using ::envoy::extensions::filters::http::proto_message_extraction::v3::MethodExtraction; +using ::Envoy::Extensions::HttpFilters::ProtoMessageExtraction::ExtractedMessageDirective; +using ::Envoy::Extensions::HttpFilters::ProtoMessageExtraction::ExtractedMessageMetadata; +using ::google::grpc::transcoding::TypeHelper; +using ::proto_processing_lib::proto_scrubber::ScrubberContext; +using Protobuf::field_extraction::FieldValueExtractorFactory; + +// The type property value that will be included into the converted Struct. +constexpr char kTypeProperty[] = "@type"; + +ABSL_CONST_INIT const char* const kTypeServiceBaseUrl = "type.googleapis.com"; + +void Extract(ProtoExtractorInterface& extractor, Protobuf::field_extraction::MessageData& message, + std::vector& vect) { + ExtractedMessageMetadata data = extractor.ExtractMessage(message); + ENVOY_LOG_MISC(debug, "Extracted fields: {}", data.extracted_message.DebugString()); + + // Only need to keep the result from the first and the last. + // Always overwrite the 2nd result as the last one. + if (vect.size() < 2) { + vect.push_back(data); + } else { + // copy and override the second one as the last one. + vect[1] = data; + } +} + +std::string GetFullTypeWithUrl(absl::string_view simple_type) { + return absl::StrCat(kTypeServiceBaseUrl, "/", simple_type); +} + +void FillStructWithType(const ::Envoy::ProtobufWkt::Type& type, ::Envoy::ProtobufWkt::Struct& out) { + (*out.mutable_fields())[kTypeProperty].set_string_value(GetFullTypeWithUrl(type.name())); +} + +ExtractedMessageDirective TypeMapping(const MethodExtraction::ExtractDirective& type) { + switch (type) { + case MethodExtraction::EXTRACT: + return ExtractedMessageDirective::EXTRACT; + case MethodExtraction::EXTRACT_REDACT: + return ExtractedMessageDirective::EXTRACT_REDACT; + case MethodExtraction::ExtractDirective_UNSPECIFIED: + return ExtractedMessageDirective::EXTRACT; + default: + return ExtractedMessageDirective::EXTRACT; + } +} + +} // namespace + +absl::Status ExtractorImpl::init() { + FieldValueExtractorFactory extractor_factory(type_finder_); + for (const auto& it : method_extraction_.request_extraction_by_field()) { + auto extractor = extractor_factory.Create(request_type_url_, it.first); + if (!extractor.ok()) { + ENVOY_LOG_MISC(debug, "Extractor status not healthy: Status: {}", extractor.status()); + return extractor.status(); + } + + request_field_path_to_extract_type_[it.first].push_back(TypeMapping(it.second)); + } + + for (const auto& it : method_extraction_.response_extraction_by_field()) { + auto extractor = extractor_factory.Create(response_type_url_, it.first); + if (!extractor.ok()) { + return extractor.status(); + } + + response_field_path_to_extract_type_[it.first].push_back(TypeMapping(it.second)); + } + + request_extractor_ = + ProtoExtractor::Create(ScrubberContext::kRequestScrubbing, &type_helper_, + type_finder_(request_type_url_), request_field_path_to_extract_type_); + + response_extractor_ = ProtoExtractor::Create(ScrubberContext::kResponseScrubbing, &type_helper_, + type_finder_(response_type_url_), + response_field_path_to_extract_type_); + + FillStructWithType(*type_finder_(request_type_url_), result_.request_type_struct); + FillStructWithType(*type_finder_(response_type_url_), result_.response_type_struct); + return absl::OkStatus(); +} + +void ExtractorImpl::processRequest(Protobuf::field_extraction::MessageData& message) { + Extract(*request_extractor_, message, result_.request_data); +} + +void ExtractorImpl::processResponse(Protobuf::field_extraction::MessageData& message) { + Extract(*response_extractor_, message, result_.response_data); +} +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/extractor_impl.h b/source/extensions/filters/http/proto_message_extraction/extractor_impl.h new file mode 100644 index 000000000000..0285dc8345f4 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/extractor_impl.h @@ -0,0 +1,85 @@ +#pragma once + +#include +#include + +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.h" +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.validate.h" + +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor.h" + +#include "absl/status/statusor.h" +#include "grpc_transcoding/type_helper.h" +#include "proto_field_extraction/message_data/message_data.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +class ExtractorImpl : public Extractor { +public: + ExtractorImpl( + const TypeFinder& type_finder, const google::grpc::transcoding::TypeHelper& type_helper, + absl::string_view request_type_url, absl::string_view response_type_url, + // const Envoy::ProtobufWkt::Type* request_type, + // const Envoy::ProtobufWkt::Type* response_type, + const envoy::extensions::filters::http::proto_message_extraction::v3::MethodExtraction& + method_extraction) + : method_extraction_(method_extraction), request_type_url_(request_type_url), + response_type_url_(response_type_url), type_finder_(type_finder), + type_helper_(type_helper) {} + + // The init method should be invoked right after the constructor has been + // called. + absl::Status init(); + + void processRequest(Protobuf::field_extraction::MessageData& message) override; + + void processResponse(Protobuf::field_extraction::MessageData& message) override; + + const ExtractedMessageResult& GetResult() const override { return result_; } + +private: + const envoy::extensions::filters::http::proto_message_extraction::v3::MethodExtraction& + method_extraction_; + + std::string request_type_url_; + std::string response_type_url_; + + const TypeFinder& type_finder_; + const google::grpc::transcoding::TypeHelper& type_helper_; + + FieldPathToExtractType request_field_path_to_extract_type_; + + FieldPathToExtractType response_field_path_to_extract_type_; + + ExtractedMessageResult result_; + std::unique_ptr request_extractor_; + std::unique_ptr response_extractor_; +}; + +class ExtractorFactoryImpl : public ExtractorFactory { +public: + absl::StatusOr createExtractor( + const google::grpc::transcoding::TypeHelper& type_helper, const TypeFinder& type_finder, + std::string request_type_url, std::string response_type_url, + const envoy::extensions::filters::http::proto_message_extraction::v3::MethodExtraction& + method_extraction) const override { + auto extractor = std::make_unique(type_finder, type_helper, request_type_url, + response_type_url, method_extraction); + auto status = extractor->init(); + if (!status.ok()) { + return status; + } + + return extractor; + } +}; + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/filter.cc b/source/extensions/filters/http/proto_message_extraction/filter.cc new file mode 100644 index 000000000000..f93d051eda6a --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/filter.cc @@ -0,0 +1,431 @@ +#include "source/extensions/filters/http/proto_message_extraction/filter.h" + +#include +#include +#include +#include +#include +#include + +#include "envoy/http/filter.h" +#include "envoy/http/header_map.h" +#include "envoy/registry/registry.h" +#include "envoy/stream_info/filter_state.h" + +#include "source/common/buffer/zero_copy_input_stream_impl.h" +#include "source/common/common/assert.h" +#include "source/common/common/base64.h" +#include "source/common/common/empty_string.h" +#include "source/common/common/logger.h" +#include "source/common/grpc/common.h" +#include "source/common/grpc/status.h" +#include "source/common/http/codes.h" +#include "source/common/http/header_map_impl.h" +#include "source/common/http/header_utility.h" +#include "source/common/http/headers.h" +#include "source/common/http/utility.h" +#include "source/common/protobuf/protobuf.h" +#include "source/extensions/filters/http/grpc_field_extraction/message_converter/message_converter.h" +#include "source/extensions/filters/http/grpc_field_extraction/message_converter/message_converter_utility.h" +#include "source/extensions/filters/http/grpc_field_extraction/message_converter/stream_message.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor.h" + +#include "absl/log/check.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" +#include "proto_field_extraction/message_data/cord_message_data.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { +namespace { + +using ::Envoy::Extensions::HttpFilters::GrpcFieldExtraction::CreateMessageDataFunc; +using ::Envoy::Extensions::HttpFilters::GrpcFieldExtraction::MessageConverter; +using ::Envoy::Extensions::HttpFilters::GrpcFieldExtraction::StreamMessage; +using ::Envoy::Grpc::Status; +using ::Envoy::Grpc::Utility; + +// The filter prefixes. +const char kRcDetailFilterProtoMessageExtraction[] = "proto_message_extraction"; + +const char kRcDetailErrorTypeBadRequest[] = "BAD_REQUEST"; + +const char kRcDetailErrorRequestOutOfData[] = "REQUEST_OUT_OF_DATA"; + +const char kRcDetailErrorResponseOutOfData[] = "RESPONSE_OUT_OF_DATA"; + +const char kRcDetailErrorRequestBufferConversion[] = "REQUEST_BUFFER_CONVERSION_FAIL"; + +const char kRcDetailErrorResponseBufferConversion[] = "RESPONSE_BUFFER_CONVERSION_FAIL"; + +// Turns a '/package.service/method' to 'package.service.method' which is +// the form suitable for the proto db lookup. +absl::StatusOr grpcPathToProtoPath(absl::string_view grpc_path) { + if (grpc_path.empty() || grpc_path.at(0) != '/' || + std::count(grpc_path.begin(), grpc_path.end(), '/') != 2) { + return absl::InvalidArgumentError( + absl::StrFormat(":path `%s` should be in form of `/package.service/method`", grpc_path)); + } + + std::string clean_input = std::string(grpc_path.substr(1)); + std::replace(clean_input.begin(), clean_input.end(), '/', '.'); + return clean_input; +} + +std::string generateRcDetails(absl::string_view filter_name, absl::string_view error_type, + absl::string_view error_detail) { + return absl::StrCat(filter_name, "_", error_type, "{", error_detail, "}"); +} +} // namespace + +void Filter::rejectRequest(Envoy::Grpc::Status::GrpcStatus grpc_status, absl::string_view error_msg, + absl::string_view rc_detail) { + ENVOY_STREAM_LOG(debug, "Rejecting request: grpcStatus={}, message={}", *decoder_callbacks_, + grpc_status, error_msg); + decoder_callbacks_->sendLocalReply( + static_cast(Utility::grpcToHttpStatus(grpc_status)), error_msg, nullptr, + grpc_status, rc_detail); +} + +void Filter::rejectResponse(Status::GrpcStatus grpc_status, absl::string_view error_msg, + absl::string_view rc_detail) { + ENVOY_STREAM_LOG(debug, "Rejecting response grpcStatus={}, message={}", *encoder_callbacks_, + grpc_status, error_msg); + + encoder_callbacks_->sendLocalReply( + static_cast(Utility::grpcToHttpStatus(grpc_status)), error_msg, nullptr, + grpc_status, rc_detail); + + encoder_callbacks_->streamInfo().setResponseFlag( + Envoy::StreamInfo::CoreResponseFlag::UnauthorizedExternalService); +} + +Envoy::Http::FilterHeadersStatus Filter::decodeHeaders(Envoy::Http::RequestHeaderMap& headers, + bool) { + ENVOY_STREAM_LOG(debug, "Called Proto Message Extraction Filter : {}", *decoder_callbacks_, + __func__); + + if (!Envoy::Grpc::Common::isGrpcRequestHeaders(headers)) { + ENVOY_STREAM_LOG(debug, + "Request isn't gRPC as its headers don't have " + "application/grpc content-type. " + "Passed through the request " + "without extraction.", + *decoder_callbacks_); + return Envoy::Http::FilterHeadersStatus::Continue; + } + + // Grpc::Common::isGrpcRequestHeaders above already ensures the existence of + // ":path" header. + auto proto_path = grpcPathToProtoPath(headers.Path()->value().getStringView()); + if (!proto_path.ok()) { + ENVOY_STREAM_LOG(info, "failed to convert gRPC path to protobuf path: {}", *decoder_callbacks_, + proto_path.status().ToString()); + + auto& status = proto_path.status(); + rejectRequest(status.raw_code(), status.message(), + generateRcDetails(kRcDetailFilterProtoMessageExtraction, + absl::StatusCodeToString(status.code()), + kRcDetailErrorTypeBadRequest)); + return Envoy::Http::FilterHeadersStatus::StopIteration; + } + + const auto* extractor = filter_config_.findExtractor(*proto_path); + if (!extractor) { + ENVOY_STREAM_LOG(debug, + "gRPC method `{}` isn't configured for Proto Message Extraction filter ", + *decoder_callbacks_, *proto_path); + return Envoy::Http::FilterHeadersStatus::Continue; + } + + // Cast away const for necessary modifications in a controlled context. + extractor_ = const_cast(extractor); + auto cord_message_data_factory = std::make_unique( + []() { return std::make_unique(); }); + + request_msg_converter_ = std::make_unique( + std::move(cord_message_data_factory), decoder_callbacks_->decoderBufferLimit()); + + return Envoy::Http::FilterHeadersStatus::StopIteration; +} + +Envoy::Http::FilterDataStatus Filter::decodeData(Envoy::Buffer::Instance& data, bool end_stream) { + ENVOY_STREAM_LOG(debug, "decodeData: data size={} end_stream={}", *decoder_callbacks_, + data.length(), end_stream); + + if (!extractor_) { + return Envoy::Http::FilterDataStatus::Continue; + } + + if (auto status = handleDecodeData(data, end_stream); !status.got_messages) { + return status.filter_status; + } + + return Envoy::Http::FilterDataStatus::Continue; +} + +Filter::HandleDataStatus Filter::handleDecodeData(Envoy::Buffer::Instance& data, bool end_stream) { + RELEASE_ASSERT(extractor_ && request_msg_converter_, + "`extractor_` and request_msg_converter_ both should be " + "initiated when extracting proto messages"); + + auto buffering = request_msg_converter_->accumulateMessages(data, end_stream); + if (!buffering.ok()) { + const absl::Status& status = buffering.status(); + rejectRequest(status.raw_code(), status.message(), + generateRcDetails(kRcDetailFilterProtoMessageExtraction, + absl::StatusCodeToString(status.code()), + kRcDetailErrorRequestBufferConversion)); + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + + if (buffering->empty()) { + ENVOY_STREAM_LOG(debug, "not a complete msg", *decoder_callbacks_); + // Not a complete message. + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + + // Buffering returns a list of messages. + for (size_t msg_idx = 0; msg_idx < buffering->size(); ++msg_idx) { + std::unique_ptr message_data = std::move(buffering->at(msg_idx)); + + // MessageConverter uses an empty StreamMessage to denote the end. + if (message_data->message() == nullptr) { + RELEASE_ASSERT(end_stream, "expect end_stream=true as when the MessageConverter " + "signals an stream end"); + RELEASE_ASSERT(message_data->isFinalMessage(), + "expect message_data->isFinalMessage()=true when the " + "MessageConverter signals " + "an stream end"); + // This is the last one in the vector. + RELEASE_ASSERT(msg_idx == buffering->size() - 1, + "expect message_data is the last element in the vector when the " + "MessageConverter signals an stream end"); + // Skip the empty message + continue; + } + // Set the request_extraction_done_ to true since we have received a message for extraction. + request_extraction_done_ = true; + + extractor_->processRequest(*message_data->message()); + + ExtractedMessageResult result = extractor_->GetResult(); + + if (result.request_data.empty()) { + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + handleRequestExtractionResult(result.request_data); + + auto buf_convert_status = request_msg_converter_->convertBackToBuffer(std::move(message_data)); + // The message_data is not modified, ConvertBack should return OK. + RELEASE_ASSERT(buf_convert_status.ok(), "request message convert back should work"); + + data.move(*buf_convert_status.value()); + ENVOY_STREAM_LOG(debug, "decodeData: convert back data size={}", *decoder_callbacks_, + data.length()); + } + + // Reject the request if extraction is required but could not + // buffer up any messages. + if (!request_extraction_done_) { + rejectRequest(Status::WellKnownGrpcStatus::InvalidArgument, + "did not receive enough data to form a message.", + generateRcDetails(kRcDetailFilterProtoMessageExtraction, + absl::StatusCodeToString(absl::StatusCode::kInvalidArgument), + kRcDetailErrorRequestOutOfData)); + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + return HandleDataStatus(Envoy::Http::FilterDataStatus::Continue); +} + +Envoy::Http::FilterHeadersStatus Filter::encodeHeaders(Envoy::Http::ResponseHeaderMap& headers, + bool end_stream) { + ENVOY_STREAM_LOG(debug, "Called Proto Message Extraction Filter : {}", *encoder_callbacks_, + __func__); + + if (!Envoy::Grpc::Common::isGrpcResponseHeaders(headers, end_stream)) { + ENVOY_STREAM_LOG( + debug, + "Response headers is NOT application/grpc content-type. Response is passed through " + "without message extraction.", + *encoder_callbacks_); + return Envoy::Http::FilterHeadersStatus::Continue; + } + + if (!extractor_) { + return Envoy::Http::FilterHeadersStatus::Continue; + } + + // Create response_msg_converter to convert response body. + auto cord_message_data_factory = std::make_unique( + []() { return std::make_unique(); }); + + response_msg_converter_ = std::make_unique( + std::move(cord_message_data_factory), encoder_callbacks_->encoderBufferLimit()); + + return Http::FilterHeadersStatus::StopIteration; +} + +Envoy::Http::FilterDataStatus Filter::encodeData(Envoy::Buffer::Instance& data, bool end_stream) { + ENVOY_STREAM_LOG(debug, "encodeData: data size={} end_stream={}", *decoder_callbacks_, + data.length(), end_stream); + + if (!response_msg_converter_ || !extractor_) { + return Envoy::Http::FilterDataStatus::Continue; + } + + if (auto status = handleEncodeData(data, end_stream); !status.got_messages) { + return status.filter_status; + } + + return Envoy::Http::FilterDataStatus::Continue; +} + +Filter::HandleDataStatus Filter::handleEncodeData(Envoy::Buffer::Instance& data, bool end_stream) { + RELEASE_ASSERT(extractor_ && response_msg_converter_, + "`extractor_` and response_msg_converter_ both should be " + "initiated when extracting proto messages"); + + auto buffering = response_msg_converter_->accumulateMessages(data, end_stream); + + if (!buffering.ok()) { + const absl::Status& status = buffering.status(); + rejectResponse(status.raw_code(), status.message(), + generateRcDetails(kRcDetailFilterProtoMessageExtraction, + absl::StatusCodeToString(status.code()), + kRcDetailErrorResponseBufferConversion)); + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + + if (buffering->empty()) { + ENVOY_STREAM_LOG(debug, "not a complete msg", *encoder_callbacks_); + // Not a complete message. + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + + // Buffering returns a list of messages. + for (size_t msg_idx = 0; msg_idx < buffering->size(); ++msg_idx) { + std::unique_ptr stream_message = std::move(buffering->at(msg_idx)); + + // The converter returns an empty stream_message for the last empty + // buffer. + if (stream_message->message() == nullptr) { + DCHECK(end_stream); + DCHECK(stream_message->isFinalMessage()); + // This is the last one in the vector. + DCHECK(msg_idx == buffering->size() - 1); + continue; + } + + // Set the response_extraction_done_ to true since we have received a message for extraction. + response_extraction_done_ = true; + + extractor_->processResponse(*stream_message->message()); + + ExtractedMessageResult result = extractor_->GetResult(); + + if (result.response_data.empty()) { + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + handleResponseExtractionResult(result.response_data); + + auto buf_convert_status = + response_msg_converter_->convertBackToBuffer(std::move(stream_message)); + + // The stream_message is not modified, ConvertBack should NOT fail. + RELEASE_ASSERT(buf_convert_status.ok(), "response message convert back should work"); + + data.move(*buf_convert_status.value()); + } + + // Reject the response if extraction is required but could not + // buffer up any messages. + if (!response_extraction_done_) { + rejectResponse(Status::WellKnownGrpcStatus::InvalidArgument, + "did not receive enough data to form a message.", + generateRcDetails(kRcDetailFilterProtoMessageExtraction, + absl::StatusCodeToString(absl::StatusCode::kInvalidArgument), + kRcDetailErrorResponseOutOfData)); + return HandleDataStatus(Envoy::Http::FilterDataStatus::StopIterationNoBuffer); + } + return HandleDataStatus(Envoy::Http::FilterDataStatus::Continue); +} + +void Filter::handleRequestExtractionResult(const std::vector& result) { + RELEASE_ASSERT(extractor_, "`extractor_` should be initialized when extracting fields"); + + Envoy::ProtobufWkt::Struct dest_metadata; + + auto addResultToMetadata = [&](const std::string& category, const std::string& key, + const ExtractedMessageMetadata& metadata) { + RELEASE_ASSERT(metadata.extracted_message.IsInitialized(), + "`extracted_message` should be initialized"); + + auto* category_field = (*dest_metadata.mutable_fields())[category].mutable_struct_value(); + + auto* key_field = (*category_field->mutable_fields())[key].mutable_struct_value(); + + for (const auto& field : metadata.extracted_message.fields()) { + (*key_field->mutable_fields())[field.first] = field.second; + } + }; + + const auto& first_metadata = result[0]; + addResultToMetadata("requests", "first", first_metadata); + + if (result.size() == 2) { + const auto& last_metadata = result[1]; + addResultToMetadata("requests", "last", last_metadata); + } + + if (dest_metadata.fields_size() > 0) { + ENVOY_STREAM_LOG(debug, "Injected request dynamic metadata `{}` with `{}`", *decoder_callbacks_, + kFilterName, dest_metadata.DebugString()); + decoder_callbacks_->streamInfo().setDynamicMetadata(kFilterName, dest_metadata); + } +} + +void Filter::handleResponseExtractionResult(const std::vector& result) { + RELEASE_ASSERT(extractor_, "`extractor_` should be initialized when extracting fields"); + + Envoy::ProtobufWkt::Struct dest_metadata; + + auto addResultToMetadata = [&](const std::string& category, const std::string& key, + const ExtractedMessageMetadata& metadata) { + RELEASE_ASSERT(metadata.extracted_message.IsInitialized(), + "`extracted_message` should be initialized"); + + auto* category_field = (*dest_metadata.mutable_fields())[category].mutable_struct_value(); + + auto* key_field = (*category_field->mutable_fields())[key].mutable_struct_value(); + + for (const auto& field : metadata.extracted_message.fields()) { + (*key_field->mutable_fields())[field.first] = field.second; + } + }; + + const auto& first_metadata = result[0]; + addResultToMetadata("responses", "first", first_metadata); + + if (result.size() == 2) { + const auto& last_metadata = result[1]; + addResultToMetadata("responses", "last", last_metadata); + } + + if (dest_metadata.fields_size() > 0) { + ENVOY_STREAM_LOG(debug, "Injected response dynamic metadata `{}` with `{}`", + *decoder_callbacks_, kFilterName, dest_metadata.DebugString()); + encoder_callbacks_->streamInfo().setDynamicMetadata(kFilterName, dest_metadata); + } +} + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/filter.h b/source/extensions/filters/http/proto_message_extraction/filter.h new file mode 100644 index 000000000000..93d6930faa92 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/filter.h @@ -0,0 +1,94 @@ +#pragma once + +#include +#include + +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.h" +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.validate.h" +#include "envoy/http/filter.h" + +#include "source/extensions/filters/http/common/factory_base.h" +#include "source/extensions/filters/http/common/pass_through_filter.h" +#include "source/extensions/filters/http/grpc_field_extraction/message_converter/message_converter.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/proto_extractor_interface.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor.h" +#include "source/extensions/filters/http/proto_message_extraction/filter_config.h" + +#include "absl/strings/string_view.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +inline constexpr const char kFilterName[] = "envoy.filters.http.proto_message_extraction"; + +class Filter : public Envoy::Http::PassThroughFilter, + Envoy::Logger::Loggable { +public: + explicit Filter(FilterConfig& config) : filter_config_(config) {} + + Envoy::Http::FilterHeadersStatus decodeHeaders(Envoy::Http::RequestHeaderMap& headers, + bool end_stream) override; + + Envoy::Http::FilterDataStatus decodeData(Envoy::Buffer::Instance& data, bool end_stream) override; + + Envoy::Http::FilterHeadersStatus encodeHeaders(Envoy::Http::ResponseHeaderMap& headers, + bool end_stream) override; + + Envoy::Http::FilterDataStatus encodeData(Envoy::Buffer::Instance& data, bool end_stream) override; + +private: + struct HandleDataStatus { + explicit HandleDataStatus(Envoy::Http::FilterDataStatus status) + : got_messages(false), filter_status(status) {} + + // If true, the function has processed at least one message. + bool got_messages; + + // If "got_message" is false, return this filter_status. + Envoy::Http::FilterDataStatus filter_status; + }; + + HandleDataStatus handleDecodeData(Envoy::Buffer::Instance& data, bool end_stream); + + HandleDataStatus handleEncodeData(Envoy::Buffer::Instance& data, bool end_stream); + + void handleRequestExtractionResult(const std::vector& result); + + void handleResponseExtractionResult(const std::vector& result); + + void rejectRequest(Envoy::Grpc::Status::GrpcStatus grpc_status, absl::string_view error_msg, + absl::string_view rc_detail); + + void rejectResponse(Envoy::Grpc::Status::GrpcStatus grpc_status, absl::string_view error_msg, + absl::string_view rc_detail); + + const FilterConfig& filter_config_; + + Extractor* extractor_ = nullptr; + + Envoy::Extensions::HttpFilters::GrpcFieldExtraction::MessageConverterPtr request_msg_converter_ = + nullptr; + + Envoy::Extensions::HttpFilters::GrpcFieldExtraction::MessageConverterPtr response_msg_converter_ = + nullptr; + + bool request_extraction_done_ = false; + + bool response_extraction_done_ = false; +}; + +class FilterFactory : public Envoy::Extensions::HttpFilters::Common::FactoryBase< + envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig> { +private: + Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped( + const envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig& proto_config, + const std::string&, Envoy::Server::Configuration::FactoryContext&) override; +}; +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/filter_config.cc b/source/extensions/filters/http/proto_message_extraction/filter_config.cc new file mode 100644 index 000000000000..4b102de64636 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/filter_config.cc @@ -0,0 +1,113 @@ +#include "source/extensions/filters/http/proto_message_extraction/filter_config.h" + +#include +#include + +#include "envoy/api/api.h" + +#include "source/common/common/logger.h" +#include "source/common/grpc/common.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor.h" + +#include "absl/log/log.h" +#include "absl/strings/string_view.h" +#include "grpc_transcoding/type_helper.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { +namespace { + +using ::envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig; +using ::google::grpc::transcoding::TypeHelper; +} // namespace + +FilterConfig::FilterConfig(const ProtoMessageExtractionConfig& proto_config, + std::unique_ptr extractor_factory, Api::Api& api) + : proto_config_(proto_config) { + initDescriptorPool(api); + + type_helper_ = + std::make_unique(Envoy::Protobuf::util::NewTypeResolverForDescriptorPool( + Envoy::Grpc::Common::typeUrlPrefix(), descriptor_pool_.get())); + + type_finder_ = std::make_unique( + [this](absl::string_view type_url) -> const ::Envoy::ProtobufWkt::Type* { + return type_helper_->Info()->GetTypeByTypeUrl(type_url); + }); + + initExtractors(*extractor_factory); +} + +const Extractor* FilterConfig::findExtractor(absl::string_view proto_path) const { + if (!proto_path_to_extractor_.contains(proto_path)) { + return nullptr; + } + return proto_path_to_extractor_.find(proto_path)->second.get(); +} + +void FilterConfig::initExtractors(ExtractorFactory& extractor_factory) { + for (const auto& it : proto_config_.extraction_by_method()) { + auto* method = descriptor_pool_->FindMethodByName(it.first); + + if (method == nullptr) { + throw EnvoyException(fmt::format( + "couldn't find the gRPC method `{}` defined in the proto descriptor", it.first)); + } + + auto extractor = extractor_factory.createExtractor( + *type_helper_, *type_finder_, + Envoy::Grpc::Common::typeUrlPrefix() + "/" + method->input_type()->full_name(), + Envoy::Grpc::Common::typeUrlPrefix() + "/" + method->output_type()->full_name(), it.second); + if (!extractor.ok()) { + throw EnvoyException(fmt::format("couldn't init extractor for method `{}`: {}", it.first, + extractor.status().message())); + } + + ENVOY_LOG_MISC(debug, "registered field extraction for gRPC method `{}`", it.first); + proto_path_to_extractor_.emplace(it.first, std::move(extractor.value())); + } +} + +void FilterConfig::initDescriptorPool(Api::Api& api) { + Envoy::Protobuf::FileDescriptorSet descriptor_set; + const ::envoy::config::core::v3::DataSource& descriptor_config = proto_config_.data_source(); + + auto pool = std::make_unique(); + + switch (descriptor_config.specifier_case()) { + case envoy::config::core::v3::DataSource::SpecifierCase::kFilename: { + auto file_or_error = api.fileSystem().fileReadToEnd(descriptor_config.filename()); + if (!file_or_error.status().ok() || !descriptor_set.ParseFromString(file_or_error.value())) { + throw Envoy::EnvoyException(fmt::format("unable to parse proto descriptor from file `{}`", + descriptor_config.filename())); + } + break; + } + case envoy::config::core::v3::DataSource::SpecifierCase::kInlineBytes: { + if (!descriptor_set.ParseFromString(descriptor_config.inline_bytes())) { + throw Envoy::EnvoyException( + fmt::format("unable to parse proto descriptor from inline bytes: {}", + descriptor_config.inline_bytes())); + } + break; + } + default: { + throw Envoy::EnvoyException( + fmt::format("unsupported DataSource case `{}` for configuring `descriptor_set`", + descriptor_config.specifier_case())); + } + } + + for (const auto& file : descriptor_set.file()) { + pool->BuildFile(file); + } + descriptor_pool_ = std::move(pool); +} + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_extraction/filter_config.h b/source/extensions/filters/http/proto_message_extraction/filter_config.h new file mode 100644 index 000000000000..2c13cd4822c2 --- /dev/null +++ b/source/extensions/filters/http/proto_message_extraction/filter_config.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include + +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.h" +#include "envoy/extensions/filters/http/proto_message_extraction/v3/config.pb.validate.h" +#include "envoy/server/filter_config.h" + +#include "source/common/common/logger.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor.h" + +#include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" +#include "grpc_transcoding/type_helper.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +// The config for Proto Message Extraction filter. As a thread-safe class, it +// should be constructed only once and shared among filters for better +// performance. +class FilterConfig : public Envoy::Logger::Loggable { +public: + explicit FilterConfig(const envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig& proto_config, + std::unique_ptr extractor_factory, Api::Api& api); + + const Extractor* findExtractor(absl::string_view proto_path) const; + +private: + void initDescriptorPool(Api::Api& api); + + void initExtractors(ExtractorFactory& extractor_factory); + + const envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig& proto_config_; + + absl::flat_hash_map> proto_path_to_extractor_; + + std::unique_ptr descriptor_pool_; + std::unique_ptr type_helper_; + std::unique_ptr type_finder_; +}; + +using FilterConfigSharedPtr = std::shared_ptr; + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/proto_message_logging/logging_util/BUILD b/source/extensions/filters/http/proto_message_logging/logging_util/BUILD deleted file mode 100644 index 6396b1a4d572..000000000000 --- a/source/extensions/filters/http/proto_message_logging/logging_util/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -load( - "//bazel:envoy_build_system.bzl", - "envoy_cc_library", - "envoy_extension_package", -) - -licenses(["notice"]) # Apache 2 - -envoy_extension_package() - -envoy_cc_library( - name = "proto_scrubber_interface", - hdrs = [ - "proto_scrubber_interface.h", - ], - deps = [ - "//source/common/protobuf", - "//source/common/protobuf:cc_wkt_protos", - "@com_google_absl//absl/container:flat_hash_map", - "@com_google_protofieldextraction//:all_libs", - ], -) - -envoy_cc_library( - name = "logging_util", - srcs = [ - "logging_util.cc", - ], - hdrs = [ - "logging_util.h", - ], - deps = [ - ":proto_scrubber_interface", - "//source/common/common:regex_lib", - "//source/common/protobuf", - "//source/common/protobuf:cc_wkt_protos", - "@com_google_protoconverter//:all", - "@com_google_protofieldextraction//:all_libs", - "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber", - ], -) diff --git a/source/extensions/filters/http/proto_message_logging/logging_util/proto_scrubber_interface.h b/source/extensions/filters/http/proto_message_logging/logging_util/proto_scrubber_interface.h deleted file mode 100644 index cb890634c1bf..000000000000 --- a/source/extensions/filters/http/proto_message_logging/logging_util/proto_scrubber_interface.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "source/common/protobuf/protobuf.h" - -#include "absl/container/flat_hash_map.h" -#include "proto_field_extraction/message_data/message_data.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace ProtoMessageLogging { - -// All valid field auditing directives for Cloud Audit Logging. -enum class AuditDirective { - AUDIT_REDACT, - AUDIT, -}; - -using FieldPathToScrubType = absl::flat_hash_map>; - -// Metadata that can be captured during message scrubbing. -struct AuditMetadata { - absl::optional num_response_items; - absl::optional target_resource; - absl::optional target_resource_callback; - absl::optional resource_location; - ProtobufWkt::Struct scrubbed_message; -}; - -// A proto-scrubbing interface for audit logging that converts a source message -// to a proto Struct. -class ProtoScrubberInterface { -public: - // Scrubs the message for auditing, then populates and returns AuditMetadata - // that contains the scrubbed message and other audit metadata obtained during - // scrubbing. - virtual AuditMetadata - ScrubMessage(const Protobuf::field_extraction::MessageData& message) const = 0; - - // Returns the message type this scrubber will handle, without the - // type url prefix "type.googleapis.com". - virtual const std::string& MessageType() const = 0; - - virtual ~ProtoScrubberInterface() = default; -}; - -} // namespace ProtoMessageLogging -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/source/extensions/filters/http/well_known_names.h b/source/extensions/filters/http/well_known_names.h index 1eadb54ee047..2f5fa0049a02 100644 --- a/source/extensions/filters/http/well_known_names.h +++ b/source/extensions/filters/http/well_known_names.h @@ -50,6 +50,8 @@ class HttpFilterNameValues { const std::string GrpcWeb = "envoy.filters.http.grpc_web"; // GRPC Field Extraction filter const std::string GrpcFieldExtraction = "envoy.filters.http.grpc_field_extraction"; + // Proto Message Extraction filter + const std::string ProtoMessageExtraction = "envoy.filters.http.proto_message_extraction"; // GRPC http1 reverse bridge filter const std::string GrpcHttp1ReverseBridge = "envoy.filters.http.grpc_http1_reverse_bridge"; // GRPC telemetry diff --git a/test/extensions/filters/http/proto_message_extraction/BUILD b/test/extensions/filters/http/proto_message_extraction/BUILD new file mode 100644 index 000000000000..77099dca0a2e --- /dev/null +++ b/test/extensions/filters/http/proto_message_extraction/BUILD @@ -0,0 +1,66 @@ +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( + name = "filter_test", + srcs = ["filter_test.cc"], + data = ["//test/proto:apikeys_proto_descriptor"], + deps = [ + "//source/extensions/filters/http/proto_message_extraction:extractor", + "//source/extensions/filters/http/proto_message_extraction:filter", + "//test/extensions/filters/http/grpc_field_extraction/message_converter:message_converter_test_lib", + "//test/mocks/http:http_mocks", + "//test/proto:apikeys_proto_cc_proto", + "//test/proto:bookstore_proto_cc_proto", + "//test/test_common:environment_lib", + "//test/test_common:utility_lib", + ], +) + +envoy_cc_test( + name = "filter_config_test", + srcs = ["filter_config_test.cc"], + data = [ + "//test/config/integration/certs", + "//test/proto:apikeys_proto_descriptor", + ], + deps = [ + "//source/extensions/filters/http/proto_message_extraction:config", + "//source/extensions/filters/http/proto_message_extraction:extractor", + "//source/extensions/filters/http/proto_message_extraction:extractor_impl", + "//source/extensions/filters/http/proto_message_extraction:filter_config", + "//test/mocks/http:http_mocks", + "//test/proto:apikeys_proto_cc_proto", + "//test/proto:bookstore_proto_cc_proto", + "//test/test_common:environment_lib", + "//test/test_common:utility_lib", + ], +) + +envoy_extension_cc_test( + name = "integration_test", + size = "large", + srcs = [ + "integration_test.cc", + ], + data = ["//test/proto:apikeys_proto_descriptor"], + extension_names = ["envoy.filters.http.proto_message_extraction"], + deps = [ + "//source/extensions/filters/http/proto_message_extraction:config", + "//test/extensions/filters/http/grpc_field_extraction/message_converter:message_converter_test_lib", + "//test/integration:http_protocol_integration_lib", + "//test/proto:apikeys_proto_cc_proto", + "@com_google_absl//absl/strings:str_format", + ], +) diff --git a/test/extensions/filters/http/proto_message_logging/logging_util/BUILD b/test/extensions/filters/http/proto_message_extraction/extraction_util/BUILD similarity index 67% rename from test/extensions/filters/http/proto_message_logging/logging_util/BUILD rename to test/extensions/filters/http/proto_message_extraction/extraction_util/BUILD index d23ca6e27937..e6b9a2049391 100644 --- a/test/extensions/filters/http/proto_message_logging/logging_util/BUILD +++ b/test/extensions/filters/http/proto_message_extraction/extraction_util/BUILD @@ -9,15 +9,15 @@ licenses(["notice"]) # Apache 2 envoy_package() envoy_cc_test( - name = "logging_util_test", - srcs = ["logging_util_test.cc"], + name = "extraction_util_test", + srcs = ["extraction_util_test.cc"], data = [ - "//test/proto:logging.proto", - "//test/proto:logging_proto_descriptor", + "//test/proto:extraction.proto", + "//test/proto:extraction_proto_descriptor", ], deps = [ - "//source/extensions/filters/http/proto_message_logging/logging_util", - "//test/proto:logging_proto_cc_proto", + "//source/extensions/filters/http/proto_message_extraction/extraction_util", + "//test/proto:extraction_proto_cc_proto", "//test/test_common:environment_lib", "//test/test_common:status_utility_lib", "@com_google_absl//absl/log:check", @@ -28,7 +28,8 @@ envoy_cc_test( "@com_google_protoconverter//:all", "@com_google_protofieldextraction//:all_libs", "@com_google_protofieldextraction//proto_field_extraction/test_utils:utils", - "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber:cloud_audit_log_field_checker", + "@com_google_protoprocessinglib//proto_processing_lib/proto_scrubber:field_mask_path_checker", + "@ocp//ocpdiag/core/testing:parse_text_proto", "@ocp//ocpdiag/core/testing:status_matchers", ], ) diff --git a/test/extensions/filters/http/proto_message_logging/logging_util/logging_util_test.cc b/test/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util_test.cc similarity index 75% rename from test/extensions/filters/http/proto_message_logging/logging_util/logging_util_test.cc rename to test/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util_test.cc index c315fb2f2a8e..91cd161f50d5 100644 --- a/test/extensions/filters/http/proto_message_logging/logging_util/logging_util_test.cc +++ b/test/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util_test.cc @@ -1,12 +1,13 @@ +#include #include #include #include #include #include -#include "source/extensions/filters/http/proto_message_logging/logging_util/logging_util.h" +#include "source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.h" -#include "test/proto/logging.pb.h" +#include "test/proto/extraction.pb.h" #include "test/test_common/environment.h" #include "test/test_common/logging.h" #include "test/test_common/status_utility.h" @@ -18,10 +19,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "ocpdiag/core/compat/status_macros.h" +#include "ocpdiag/core/testing/parse_text_proto.h" #include "ocpdiag/core/testing/status_matchers.h" #include "proto_field_extraction/message_data/cord_message_data.h" #include "proto_field_extraction/test_utils/utils.h" -#include "proto_processing_lib/proto_scrubber/cloud_audit_log_field_checker.h" +#include "proto_processing_lib/proto_scrubber/field_mask_path_checker.h" #include "proto_processing_lib/proto_scrubber/proto_scrubber.h" #include "proto_processing_lib/proto_scrubber/proto_scrubber_enums.h" #include "proto_processing_lib/proto_scrubber/utility.h" @@ -30,21 +32,22 @@ namespace Envoy { namespace Extensions { namespace HttpFilters { -namespace ProtoMessageLogging { +namespace ProtoMessageExtraction { namespace { using ::Envoy::Protobuf::Field; using ::Envoy::Protobuf::FieldMask; +using Envoy::Protobuf::FileDescriptorSet; using ::Envoy::Protobuf::Type; using ::Envoy::Protobuf::field_extraction::CordMessageData; -using ::Envoy::Protobuf::field_extraction::testing::TypeHelper; using ::Envoy::Protobuf::io::CodedInputStream; using ::Envoy::ProtobufWkt::Struct; using ::Envoy::StatusHelpers::IsOkAndHolds; using ::Envoy::StatusHelpers::StatusIs; -using ::logging::TestRequest; -using ::logging::TestResponse; -using ::proto_processing_lib::proto_scrubber::CloudAuditLogFieldChecker; +using ::extraction::TestRequest; +using ::extraction::TestResponse; +using ::google::grpc::transcoding::TypeHelper; +using ::proto_processing_lib::proto_scrubber::FieldMaskPathChecker; using ::proto_processing_lib::proto_scrubber::ProtoScrubber; using ::proto_processing_lib::proto_scrubber::ScrubberContext; using ::testing::ValuesIn; @@ -122,11 +125,11 @@ const char kTestResponse[] = R"pb( sub_message { bucket_present { name: "bucket_present" } } )pb"; -class AuditLoggingUtilTest : public ::testing::Test { +class ExtractionUtilTest : public ::testing::Test { protected: - AuditLoggingUtilTest() = default; + ExtractionUtilTest() = default; const Protobuf::Type* FindType(const std::string& type_url) { - absl::StatusOr result = type_helper_->ResolveTypeUrl(type_url); + absl::StatusOr result = type_helper_->Info()->ResolveTypeUrl(type_url); if (!result.ok()) { return nullptr; } @@ -135,25 +138,49 @@ class AuditLoggingUtilTest : public ::testing::Test { void SetUp() override { const std::string descriptor_path = - TestEnvironment::runfilesPath("test/proto/logging.descriptor"); - absl::StatusOr> status = TypeHelper::Create(descriptor_path); - type_helper_ = std::move(status.value()); + TestEnvironment::runfilesPath("test/proto/extraction.descriptor"); - type_finder_ = std::bind_front(&AuditLoggingUtilTest::FindType, this); + // Create an input file stream + std::ifstream file(descriptor_path, std::ios::in | std::ios::binary); + if (!file) { + LOG(ERROR) << "Failed to open the file: " << descriptor_path << std::endl; + } + + // Read the file contents into a stringstream + std::stringstream buffer; + buffer << file.rdbuf(); + std::string file_contents = buffer.str(); + + FileDescriptorSet descriptor_set; + if (!descriptor_set.ParseFromString(file_contents)) { + LOG(ERROR) << "Unable to parse proto descriptor from file " << descriptor_path; + } + + for (const auto& file : descriptor_set.file()) { + if (descriptor_pool_->BuildFile(file) == nullptr) { + LOG(ERROR) << "Unable to build proto descriptor pool"; + } + } + + type_helper_ = std::make_unique( + Protobuf::util::NewTypeResolverForDescriptorPool("type.googleapis.com", + descriptor_pool_.get())); + + type_finder_ = std::bind_front(&ExtractionUtilTest::FindType, this); if (!Protobuf::TextFormat::ParseFromString(kTestRequest, &test_request_proto_)) { LOG(ERROR) << "Failed to parse textproto: " << kTestRequest; } test_request_raw_proto_ = CordMessageData(test_request_proto_.SerializeAsCord()); request_type_ = type_finder_("type.googleapis.com/" - "logging.TestRequest"); + "extraction.TestRequest"); if (!Protobuf::TextFormat::ParseFromString(kTestResponse, &test_response_proto_)) { LOG(ERROR) << "Failed to parse textproto: " << kTestResponse; } test_response_raw_proto_ = CordMessageData(test_response_proto_.SerializeAsCord()); response_type_ = type_finder_("type.googleapis.com/" - "logging.TestResponse"); + "extraction.TestResponse"); labels_.clear(); } @@ -179,6 +206,9 @@ class AuditLoggingUtilTest : public ::testing::Test { // A TypeHelper for testing. std::unique_ptr type_helper_ = nullptr; + std::unique_ptr descriptor_pool_ = + std::make_unique(); + std::function type_finder_; TestRequest test_request_proto_; @@ -194,34 +224,32 @@ class AuditLoggingUtilTest : public ::testing::Test { Envoy::Protobuf::Map labels_; }; -TEST_F(AuditLoggingUtilTest, IsEmptyStruct_EmptyStruct) { +TEST_F(ExtractionUtilTest, IsEmptyStruct_EmptyStruct) { ProtobufWkt::Struct message_struct; message_struct.mutable_fields()->insert({kTypeProperty, ProtobufWkt::Value()}); EXPECT_TRUE(IsEmptyStruct(message_struct)); } -TEST_F(AuditLoggingUtilTest, IsEmptyStruct_NonEmptyStruct) { +TEST_F(ExtractionUtilTest, IsEmptyStruct_NonEmptyStruct) { ProtobufWkt::Struct message_struct; message_struct.mutable_fields()->insert({kTypeProperty, ProtobufWkt::Value()}); message_struct.mutable_fields()->insert({"another_field", ProtobufWkt::Value()}); EXPECT_FALSE(IsEmptyStruct(message_struct)); } -TEST_F(AuditLoggingUtilTest, IsLabelName_ValidLabel) { EXPECT_TRUE(IsLabelName("{label}")); } +TEST_F(ExtractionUtilTest, IsLabelName_ValidLabel) { EXPECT_TRUE(IsLabelName("{label}")); } -TEST_F(AuditLoggingUtilTest, IsLabelName_EmptyString) { EXPECT_FALSE(IsLabelName("")); } +TEST_F(ExtractionUtilTest, IsLabelName_EmptyString) { EXPECT_FALSE(IsLabelName("")); } -TEST_F(AuditLoggingUtilTest, GetLabelName_RemovesCurlyBraces) { +TEST_F(ExtractionUtilTest, GetLabelName_RemovesCurlyBraces) { EXPECT_EQ(GetLabelName("{test}"), "test"); } -TEST_F(AuditLoggingUtilTest, GetLabelName_NoCurlyBraces) { - EXPECT_EQ(GetLabelName("test"), "test"); -} +TEST_F(ExtractionUtilTest, GetLabelName_NoCurlyBraces) { EXPECT_EQ(GetLabelName("test"), "test"); } -TEST_F(AuditLoggingUtilTest, GetLabelName_EmptyString) { EXPECT_EQ(GetLabelName(""), ""); } +TEST_F(ExtractionUtilTest, GetLabelName_EmptyString) { EXPECT_EQ(GetLabelName(""), ""); } -TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_BasicExtraction) { +TEST_F(ExtractionUtilTest, GetMonitoredResourceLabels_BasicExtraction) { GetMonitoredResourceLabels("project/*/bucket/{bucket}/object/{object}", "project/myproject/bucket/mybucket/object/myobject", &labels_); @@ -230,30 +258,30 @@ TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_BasicExtraction) { EXPECT_EQ(labels_["object"], "myobject"); } -TEST_F(AuditLoggingUtilTest, StringToDirectiveMap_CorrectMapping) { +TEST_F(ExtractionUtilTest, StringToDirectiveMap_CorrectMapping) { const auto& map = StringToDirectiveMap(); EXPECT_EQ(map.size(), 2); - EXPECT_EQ(map.at(kAuditRedact), AuditDirective::AUDIT_REDACT); - EXPECT_EQ(map.at(kAudit), AuditDirective::AUDIT); + EXPECT_EQ(map.at(kExtractRedact), ExtractedMessageDirective::EXTRACT_REDACT); + EXPECT_EQ(map.at(kExtract), ExtractedMessageDirective::EXTRACT); } -TEST_F(AuditLoggingUtilTest, AuditDirectiveFromString_ValidDirective) { - auto directive = AuditDirectiveFromString(kAuditRedact); +TEST_F(ExtractionUtilTest, ExtractedMessageDirectiveFromString_ValidDirective) { + auto directive = ExtractedMessageDirectiveFromString(kExtractRedact); ASSERT_TRUE(directive.has_value()); - EXPECT_EQ(directive.value(), AuditDirective::AUDIT_REDACT); + EXPECT_EQ(directive.value(), ExtractedMessageDirective::EXTRACT_REDACT); - directive = AuditDirectiveFromString(kAudit); + directive = ExtractedMessageDirectiveFromString(kExtract); ASSERT_TRUE(directive.has_value()); - EXPECT_EQ(directive.value(), AuditDirective::AUDIT); + EXPECT_EQ(directive.value(), ExtractedMessageDirective::EXTRACT); } -TEST_F(AuditLoggingUtilTest, AuditDirectiveFromString_InvalidDirective) { - auto directive = AuditDirectiveFromString("invalid_directive"); +TEST_F(ExtractionUtilTest, ExtractedMessageDirectiveFromString_InvalidDirective) { + auto directive = ExtractedMessageDirectiveFromString("invalid_directive"); EXPECT_FALSE(directive.has_value()); } -TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_MissingLabelsInResource) { +TEST_F(ExtractionUtilTest, GetMonitoredResourceLabels_MissingLabelsInResource) { GetMonitoredResourceLabels("project/*/bucket/{bucket}/object/{object}", "project/myproject/bucket/mybucket", &labels_); @@ -262,7 +290,7 @@ TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_MissingLabelsInResource) EXPECT_EQ(labels_.find("object"), labels_.end()); } -TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_ExtraSegmentsInResource) { +TEST_F(ExtractionUtilTest, GetMonitoredResourceLabels_ExtraSegmentsInResource) { GetMonitoredResourceLabels("project/*/bucket/{bucket}/object/{object}", "project/myproject/bucket/mybucket/object/myobject/extra", &labels_); @@ -271,25 +299,50 @@ TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_ExtraSegmentsInResource) EXPECT_EQ(labels_["object"], "myobject"); } -TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_WithNoLabels) { +TEST_F(ExtractionUtilTest, GetMonitoredResourceLabels_WithNoLabels) { GetMonitoredResourceLabels("project/*/bucket/*/object/*", "project/myproject/bucket/mybucket/object/myobject", &labels_); EXPECT_EQ(labels_.size(), 0); } -TEST_F(AuditLoggingUtilTest, GetMonitoredResourceLabels_EmptyLabelExtractor) { +TEST_F(ExtractionUtilTest, GetMonitoredResourceLabels_EmptyLabelExtractor) { GetMonitoredResourceLabels("", "project/myproject/bucket/mybucket/object/myobject", &labels_); EXPECT_EQ(labels_.size(), 0); } -TEST_F(AuditLoggingUtilTest, RedactStructRecursively_EmptyPath) { +TEST_F(ExtractionUtilTest, SingularFieldUseLastValue_EmptyLastValue) { + Field field; + field.set_name("id"); + field.set_number(1); + field.set_kind(Field::TYPE_INT64); + + absl::StatusOr st = SingularFieldUseLastValue( + "first_value", &field, &test_request_raw_proto_.CreateCodedInputStreamWrapper()->Get()); + EXPECT_TRUE(st.ok()); + EXPECT_EQ(st.value(), "first_value"); +} + +TEST_F(ExtractionUtilTest, SingularFieldUseLastValue_NonEmptyLastValue) { + Field field; + field.set_name("repeated_strings"); + field.set_number(3); + field.set_kind(Field::TYPE_STRING); + field.set_cardinality(Field::CARDINALITY_REPEATED); + + absl::StatusOr st = SingularFieldUseLastValue( + "", &field, &test_request_raw_proto_.CreateCodedInputStreamWrapper()->Get()); + EXPECT_TRUE(st.ok()); + EXPECT_EQ(st.value(), "repeated-string-0"); +} + +TEST_F(ExtractionUtilTest, RedactStructRecursively_EmptyPath) { Struct message_struct = CreateNestedStruct({"level1", "level2"}, "value"); EXPECT_TRUE(RedactStructRecursively({}, {}, &message_struct).ok()); } -TEST_F(AuditLoggingUtilTest, RedactStructRecursively_InvalidPath) { +TEST_F(ExtractionUtilTest, RedactStructRecursively_InvalidPath) { Struct message_struct = CreateNestedStruct({"level1", "level2"}, "value"); std::vector path_pieces = {"invalid", "path_end"}; EXPECT_TRUE( @@ -302,7 +355,7 @@ TEST_F(AuditLoggingUtilTest, RedactStructRecursively_InvalidPath) { EXPECT_TRUE(level2_field.has_struct_value()); } -TEST_F(AuditLoggingUtilTest, RedactStructRecursively_ValidPath) { +TEST_F(ExtractionUtilTest, RedactStructRecursively_ValidPath) { Struct message_struct = CreateNestedStruct({"level1", "level2"}, "value"); std::vector path_pieces = {"level1", "level2"}; EXPECT_TRUE( @@ -315,7 +368,7 @@ TEST_F(AuditLoggingUtilTest, RedactStructRecursively_ValidPath) { EXPECT_TRUE(level2_field.has_struct_value()); } -TEST_F(AuditLoggingUtilTest, RedactStructRecursively_MissingIntermediateField) { +TEST_F(ExtractionUtilTest, RedactStructRecursively_MissingIntermediateField) { Struct message_struct = CreateNestedStruct({"level1"}, "value"); std::vector path_pieces = {"level1", "level2"}; EXPECT_TRUE( @@ -328,94 +381,56 @@ TEST_F(AuditLoggingUtilTest, RedactStructRecursively_MissingIntermediateField) { EXPECT_TRUE(level2_field.has_struct_value()); } -TEST_F(AuditLoggingUtilTest, RedactStructRecursively_EmptyPathPiece) { +TEST_F(ExtractionUtilTest, RedactStructRecursively_EmptyPathPiece) { Struct message_struct = CreateNestedStruct({"level1", "level2"}, "value"); std::vector path_pieces = {"level1", ""}; EXPECT_EQ(RedactStructRecursively(path_pieces.cbegin(), path_pieces.cend(), &message_struct), absl::InvalidArgumentError("path piece cannot be empty.")); } -TEST_F(AuditLoggingUtilTest, RedactStructRecursively_NullptrMessageStruct) { +TEST_F(ExtractionUtilTest, RedactStructRecursively_NullptrMessageStruct) { std::vector path_pieces = {"level1"}; EXPECT_EQ(RedactStructRecursively(path_pieces.cbegin(), path_pieces.cend(), nullptr), absl::InvalidArgumentError("message_struct cannot be nullptr.")); } -TEST_F(AuditLoggingUtilTest, IsMessageFieldPathPresent_EmptyPath) { - EXPECT_EQ( - IsMessageFieldPathPresent(*request_type_, type_finder_, "", test_request_raw_proto_).status(), - absl::InvalidArgumentError("Field path cannot be empty.")); -} - -TEST_F(AuditLoggingUtilTest, IsMessageFieldPathPresent_EmptyType) { - Type empty_type; - EXPECT_EQ( - IsMessageFieldPathPresent(empty_type, type_finder_, "id", test_request_raw_proto_).status(), - absl::InvalidArgumentError("Cannot find field 'id' in '' message.")); -} - -TEST_F(AuditLoggingUtilTest, IsMessageFieldPathPresent_InvalidPath) { - EXPECT_EQ(IsMessageFieldPathPresent(*request_type_, type_finder_, "invalid_path", - test_request_raw_proto_) - .status(), - absl::InvalidArgumentError( - "Cannot find field 'invalid_path' in 'logging.TestRequest' message.")); -} - -TEST_F(AuditLoggingUtilTest, IsMessageFieldPathPresent_ValidPath) { - EXPECT_TRUE( - IsMessageFieldPathPresent(*request_type_, type_finder_, "bucket", test_request_raw_proto_) - .status() - .ok()); -} - -TEST_F(AuditLoggingUtilTest, IsMessageFieldPathPresent_NotMessageField) { - EXPECT_EQ(IsMessageFieldPathPresent(*request_type_, type_finder_, "repeated_strings", - test_request_raw_proto_) - .status(), - absl::InvalidArgumentError("Field 'repeated_strings' is not a message type field.")); -} - -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_bytes) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_bytes) { EXPECT_EQ(3, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("bucket.objects"), test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, FindSingularLastValue_SingleStringField) { +TEST_F(ExtractionUtilTest, FindSingularLastValue_SingleStringField) { Field field; field.set_name("id"); field.set_number(1); field.set_kind(Field::TYPE_INT64); - std::string data = "123445"; auto result = FindSingularLastValue( &field, &test_request_raw_proto_.CreateCodedInputStreamWrapper()->Get()); ASSERT_TRUE(result.ok()); EXPECT_EQ(result.value(), ""); } -TEST_F(AuditLoggingUtilTest, FindSingularLastValue_RepeatedStringField) { +TEST_F(ExtractionUtilTest, FindSingularLastValue_RepeatedStringField) { Field field; field.set_name("repeated_strings"); field.set_number(3); field.set_kind(Field::TYPE_STRING); field.set_cardinality(Field::CARDINALITY_REPEATED); - std::string data = "repeated-string-0"; auto result = FindSingularLastValue( &field, &test_request_raw_proto_.CreateCodedInputStreamWrapper()->Get()); EXPECT_TRUE(result.ok()); EXPECT_EQ(result.value(), "repeated-string-0"); } -TEST_F(AuditLoggingUtilTest, FindSingularLastValue_RepeatedMessageField) { +TEST_F(ExtractionUtilTest, FindSingularLastValue_RepeatedMessageField) { Field field; field.set_name("bucket"); field.set_number(2); field.set_kind(Field::TYPE_STRING); - std::string data = "test-bucket"; auto result = FindSingularLastValue( &field, &test_request_raw_proto_.CreateCodedInputStreamWrapper()->Get()); ASSERT_TRUE(result.ok()); @@ -424,7 +439,7 @@ TEST_F(AuditLoggingUtilTest, FindSingularLastValue_RepeatedMessageField) { "\n\vtest-bucket\x15\xCD\xCCL?\x1A\rtest-object-1\x1A\rtest-object-2\x1A\rtest-object-3"); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_string) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_string) { EXPECT_EQ(1, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_strings"), test_request_raw_proto_)); @@ -433,17 +448,17 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_string) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_message) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_message) { EXPECT_EQ(2, ExtractRepeatedFieldSize(*response_type_, type_finder_, GetFieldMaskWith("buckets"), test_response_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_map) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_map) { EXPECT_EQ(2, ExtractRepeatedFieldSize(*response_type_, type_finder_, GetFieldMaskWith("sub_buckets"), test_response_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_enum) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_enum) { EXPECT_EQ(4, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_enum"), test_request_raw_proto_)); @@ -452,7 +467,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_enum) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_double) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_double) { EXPECT_EQ(1, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_double"), test_request_raw_proto_)); @@ -461,7 +476,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_double) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_float) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_float) { EXPECT_EQ(2, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_float"), test_request_raw_proto_)); @@ -470,7 +485,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_float) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_int64) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_int64) { EXPECT_EQ(3, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_int64"), test_request_raw_proto_)); @@ -479,7 +494,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_int64) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_uint64) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_uint64) { EXPECT_EQ(4, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_uint64"), test_request_raw_proto_)); @@ -488,7 +503,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_uint64) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_int32) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_int32) { EXPECT_EQ(5, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_int32"), test_request_raw_proto_)); @@ -497,7 +512,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_int32) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_fixed64) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_fixed64) { EXPECT_EQ(6, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_fixed64"), test_request_raw_proto_)); @@ -506,7 +521,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_fixed64) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_fixed32) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_fixed32) { EXPECT_EQ(7, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_fixed32"), test_request_raw_proto_)); @@ -515,7 +530,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_fixed32) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_bool) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_bool) { EXPECT_EQ(5, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_bool"), test_request_raw_proto_)); @@ -525,7 +540,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_bool) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_uint32) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_uint32) { EXPECT_EQ(8, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_uint32"), test_request_raw_proto_)); @@ -534,7 +549,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_uint32) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sfixed64) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_sfixed64) { EXPECT_EQ(6, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_sfixed64"), test_request_raw_proto_)); @@ -543,7 +558,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sfixed64) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sfixed32) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_sfixed32) { EXPECT_EQ(7, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_sfixed32"), test_request_raw_proto_)); @@ -552,7 +567,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sfixed32) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sint32) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_sint32) { EXPECT_EQ(5, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_sint32"), test_request_raw_proto_)); @@ -561,7 +576,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sint32) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sint64) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_sint64) { EXPECT_EQ(6, ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("repeated_sint64"), test_request_raw_proto_)); @@ -570,7 +585,7 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_sint64) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_DefaultValue) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_OK_DefaultValue) { test_request_proto_.clear_repeated_strings(); test_request_raw_proto_ = CordMessageData(test_request_proto_.SerializeAsCord()); EXPECT_EQ(0, ExtractRepeatedFieldSize(*request_type_, type_finder_, @@ -578,19 +593,19 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_OK_DefaultValue) { test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_EmptyPath) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_Error_EmptyPath) { EXPECT_LT(ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith(""), test_request_raw_proto_), 0); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_NonRepeatedField) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_Error_NonRepeatedField) { EXPECT_LT(ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("bucket.ratio"), test_request_raw_proto_), 0); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_UnknownField) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_Error_UnknownField) { EXPECT_LT(ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("bucket.unknown"), test_request_raw_proto_), 0); @@ -603,21 +618,21 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_UnknownField) { 0); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_NonLeafPrimitiveTypeField) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_Error_NonLeafPrimitiveTypeField) { EXPECT_LT(ExtractRepeatedFieldSize(*request_type_, type_finder_, GetFieldMaskWith("bucket.name.unknown"), test_request_raw_proto_), 0); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_NonLeafMapField) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_Error_NonLeafMapField) { EXPECT_LT(ExtractRepeatedFieldSize(*response_type_, type_finder_, GetFieldMaskWith("sub_buckets.objects"), test_response_raw_proto_), 0); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_NonLeafRepeatedField) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_Error_NonLeafRepeatedField) { EXPECT_LT(ExtractRepeatedFieldSize(*response_type_, type_finder_, GetFieldMaskWith("buckets.name"), test_response_raw_proto_), 0); @@ -626,24 +641,24 @@ TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_NonLeafRepeatedField 0); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_Error_NullptrFieldMask) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_Error_NullptrFieldMask) { EXPECT_GT( 0, ExtractRepeatedFieldSize(*request_type_, type_finder_, nullptr, test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractRepeatedFieldSize_EmptyFieldMask) { +TEST_F(ExtractionUtilTest, ExtractRepeatedFieldSize_EmptyFieldMask) { FieldMask field_mask; EXPECT_GT(0, ExtractRepeatedFieldSize(*request_type_, type_finder_, &field_mask_, test_request_raw_proto_)); } -TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_OK) { +TEST_F(ExtractionUtilTest, ExtractStringFieldValue_OK) { EXPECT_THAT( ExtractStringFieldValue(*request_type_, type_finder_, "bucket.name", test_request_raw_proto_), IsOkAndHolds("test-bucket")); } -TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_OK_DefaultValue) { +TEST_F(ExtractionUtilTest, ExtractStringFieldValue_OK_DefaultValue) { test_request_proto_.mutable_bucket()->clear_name(); test_request_raw_proto_ = CordMessageData(test_request_proto_.SerializeAsCord()); EXPECT_THAT( @@ -657,12 +672,12 @@ TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_OK_DefaultValue) { IsOkAndHolds("")); } -TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_EmptyPath) { +TEST_F(ExtractionUtilTest, ExtractStringFieldValue_Error_EmptyPath) { EXPECT_THAT(ExtractStringFieldValue(*request_type_, type_finder_, "", test_request_raw_proto_), StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_UnknownField) { +TEST_F(ExtractionUtilTest, ExtractStringFieldValue_Error_UnknownField) { EXPECT_THAT(ExtractStringFieldValue(*request_type_, type_finder_, "bucket.unknown", test_request_raw_proto_), StatusIs(absl::StatusCode::kInvalidArgument)); @@ -676,13 +691,13 @@ TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_UnknownField) { StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_RepeatedStringLeafNode) { +TEST_F(ExtractionUtilTest, ExtractStringFieldValue_Error_RepeatedStringLeafNode) { EXPECT_THAT(ExtractStringFieldValue(*request_type_, type_finder_, "repeated_strings", test_request_raw_proto_), StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_NonStringLeafNode) { +TEST_F(ExtractionUtilTest, ExtractStringFieldValue_Error_NonStringLeafNode) { EXPECT_THAT(ExtractStringFieldValue(*request_type_, type_finder_, "bucket.ratio", test_request_raw_proto_), StatusIs(absl::StatusCode::kInvalidArgument)); @@ -692,7 +707,7 @@ TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_NonStringLeafNode) { StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_InvalidTypeFinder) { +TEST_F(ExtractionUtilTest, ExtractStringFieldValue_Error_InvalidTypeFinder) { auto invalid_type_finder = [](absl::string_view /*type_url*/) { return nullptr; }; EXPECT_THAT(ExtractStringFieldValue(*request_type_, invalid_type_finder, "bucket.ratio", @@ -700,7 +715,120 @@ TEST_F(AuditLoggingUtilTest, ExtractStringFieldValue_Error_InvalidTypeFinder) { StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST(StructUtilTest, RedactPaths_Basic) { +TEST_F(ExtractionUtilTest, ScrubToStruct_Success) { + TestRequest expected_proto = ::ocpdiag::testing::ParseTextProtoOrDie(R"pb( + id: 123445 + bucket { + ratio: 0.8 + objects: "test-object-1" + objects: "test-object-2" + objects: "test-object-3" + } + )pb"); + + std::vector paths = {"bucket.name", "bucket.ratio"}; + + FieldMaskPathChecker field_checker(request_type_, type_finder_); + ASSERT_OK(field_checker.AddOrIntersectFieldPaths(paths)); + ProtoScrubber proto_scrubber(request_type_, type_finder_, {&field_checker}, + ScrubberContext::kTestScrubbing); + + CordMessageData raw_proto = CordMessageData(expected_proto.SerializeAsCord()); + Struct actual_struct; + + EXPECT_TRUE( + ScrubToStruct(&proto_scrubber, *request_type_, *type_helper_, &raw_proto, &actual_struct)); +} + +TEST_F(ExtractionUtilTest, ScrubToStruct_NullptrScrubber) { + TestRequest expected_proto = ::ocpdiag::testing::ParseTextProtoOrDie(R"pb( + id: 123445 + bucket { + ratio: 0.8 + objects: "test-object-1" + objects: "test-object-2" + objects: "test-object-3" + } + )pb"); + + CordMessageData raw_proto = CordMessageData(expected_proto.SerializeAsCord()); + Struct actual_struct; + + EXPECT_FALSE(ScrubToStruct(nullptr /*scrubber*/, *request_type_, *type_helper_, &raw_proto, + &actual_struct)); +} + +TEST_F(ExtractionUtilTest, ScrubToStruct_InvalidMessageData) { + std::vector paths = {"bucket.name", "bucket.ratio"}; + + FieldMaskPathChecker field_checker(request_type_, type_finder_); + ASSERT_OK(field_checker.AddOrIntersectFieldPaths(paths)); + ProtoScrubber proto_scrubber(request_type_, type_finder_, {&field_checker}, + ScrubberContext::kTestScrubbing); + + absl::Cord cord("some_data"); + CordMessageData raw_proto = CordMessageData(cord); + Struct actual_struct; + + EXPECT_FALSE( + ScrubToStruct(&proto_scrubber, *request_type_, *type_helper_, &raw_proto, &actual_struct)); +} + +TEST_F(ExtractionUtilTest, ScrubToStruct_Failure) { + TestRequest expected_proto = ::ocpdiag::testing::ParseTextProtoOrDie(R"pb( + id: 123445 + bucket { + ratio: 0.8 + objects: "test-object-1" + objects: "test-object-2" + objects: "test-object-3" + } + )pb"); + + std::vector paths = {"bucket.ratio"}; + + FieldMaskPathChecker field_checker(request_type_, type_finder_); + ASSERT_OK(field_checker.AddOrIntersectFieldPaths(paths)); + + ProtoScrubber proto_scrubber(response_type_, type_finder_, {&field_checker}, + ScrubberContext::kTestScrubbing); + + CordMessageData raw_proto = CordMessageData(expected_proto.SerializeAsCord()); + Struct actual_struct; + + EXPECT_FALSE( + ScrubToStruct(&proto_scrubber, *request_type_, *type_helper_, &raw_proto, &actual_struct)); +} + +TEST_F(ExtractionUtilTest, ScrubToStruct_InvalidTypeHelper) { + TestRequest expected_proto = ::ocpdiag::testing::ParseTextProtoOrDie(R"pb( + id: 123445 + bucket { + ratio: 0.8 + objects: "test-object-1" + objects: "test-object-2" + objects: "test-object-3" + } + )pb"); + + std::vector paths = {"bucket.name", "bucket.ratio"}; + + FieldMaskPathChecker field_checker(request_type_, type_finder_); + ASSERT_OK(field_checker.AddOrIntersectFieldPaths(paths)); + ProtoScrubber proto_scrubber(request_type_, type_finder_, {&field_checker}, + ScrubberContext::kTestScrubbing); + + CordMessageData raw_proto = CordMessageData(expected_proto.SerializeAsCord()); + Struct actual_struct; + + std::unique_ptr type_helper = std::make_unique( + Protobuf::util::NewTypeResolverForDescriptorPool("", descriptor_pool_.get())); + + EXPECT_FALSE( + ScrubToStruct(&proto_scrubber, *request_type_, *type_helper, &raw_proto, &actual_struct)); +} + +TEST(ExtractUtilTest, RedactPaths_Basic) { std::string proto_struct_string = "fields {" " key: \"nested\"" " value {" @@ -745,7 +873,7 @@ TEST(StructUtilTest, RedactPaths_Basic) { EXPECT_TRUE(Protobuf::util::MessageDifferencer::Equals(expected_struct, proto_struct)); } -TEST(StructUtilTest, RedactPaths_HandlesOneOfFields) { +TEST(ExtractUtilTest, RedactPaths_HandlesOneOfFields) { std::string proto_struct_string = "fields {" " key: \"nested_value\"" " value {" @@ -776,7 +904,7 @@ TEST(StructUtilTest, RedactPaths_HandlesOneOfFields) { EXPECT_TRUE(Protobuf::util::MessageDifferencer::Equals(expected_struct, proto_struct)); } -TEST(StructUtilTest, RedactPaths_AllowsRepeatedLeafMessageType) { +TEST(ExtractUtilTest, RedactPaths_AllowsRepeatedLeafMessageType) { std::string proto_struct_string = "fields {" " key: \"repeated_message_field\"" " value {" @@ -828,7 +956,7 @@ TEST(StructUtilTest, RedactPaths_AllowsRepeatedLeafMessageType) { EXPECT_TRUE(Protobuf::util::MessageDifferencer::Equals(expected_struct, proto_struct)); } -TEST(StructUtilTest, RedactPaths_AllowsRepeatedNonLeafMessageType) { +TEST(ExtractUtilTest, RedactPaths_AllowsRepeatedNonLeafMessageType) { std::string proto_struct_string = "fields {" " key: \"repeated_message_field\"" " value {" @@ -955,7 +1083,7 @@ INSTANTIATE_TEST_SUITE_P( }); } // namespace -} // namespace ProtoMessageLogging +} // namespace ProtoMessageExtraction } // namespace HttpFilters } // namespace Extensions } // namespace Envoy diff --git a/test/extensions/filters/http/proto_message_logging/logging_util/logging_util_test.yaml b/test/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util_test.yaml similarity index 72% rename from test/extensions/filters/http/proto_message_logging/logging_util/logging_util_test.yaml rename to test/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util_test.yaml index f8c0fac6402b..4611d090d981 100644 --- a/test/extensions/filters/http/proto_message_logging/logging_util/logging_util_test.yaml +++ b/test/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util_test.yaml @@ -1,9 +1,9 @@ type: google.api.Service config_version: 3 -name: audit_logging_util_test.googleapis.com -title: Audit Logging Util Test API +name: extraction_util_test.googleapis.com +title: Extraction Util Test API apis: -- name: proto_processing_lib.proto_scrubber.testing.AuditLoggingUtilTestService +- name: ExtractionUtilTestService documentation: overview: | @@ -15,7 +15,7 @@ documentation: (== suppress_warning legacy-contacts ==) (== suppress_warning versioning-config ==) summary: - Audit Logging Util Test + Extraction Util Test backend: rules: diff --git a/test/extensions/filters/http/proto_message_extraction/filter_config_test.cc b/test/extensions/filters/http/proto_message_extraction/filter_config_test.cc new file mode 100644 index 000000000000..b4f441ad667f --- /dev/null +++ b/test/extensions/filters/http/proto_message_extraction/filter_config_test.cc @@ -0,0 +1,409 @@ +#include "source/extensions/filters/http/proto_message_extraction/config.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor.h" +#include "source/extensions/filters/http/proto_message_extraction/extractor_impl.h" +#include "source/extensions/filters/http/proto_message_extraction/filter_config.h" + +#include "test/mocks/http/mocks.h" +#include "test/proto/apikeys.pb.h" +#include "test/test_common/environment.h" +#include "test/test_common/printers.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { + +namespace { + +using ::envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig; +using ::Envoy::Http::TestRequestTrailerMapImpl; + +class FilterConfigTestBase : public ::testing::Test { +protected: + FilterConfigTestBase() : api_(Api::createApiForTest()) {} + + void parseConfigProto(absl::string_view str = R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: EXTRACT } + request_extraction_by_field: { key: "key.name" value: EXTRACT } + response_extraction_by_field: { key: "name" value: EXTRACT } + } + })pb") { + ASSERT_TRUE(Protobuf::TextFormat::ParseFromString(str, &proto_config_)); + } + + Api::ApiPtr api_; + ProtoMessageExtractionConfig proto_config_; + std::unique_ptr filter_config_; +}; + +using FilterConfigTestOk = FilterConfigTestBase; + +TEST_F(FilterConfigTestOk, DescriptorInline) { + parseConfigProto(); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + filter_config_ = std::make_unique(proto_config_, + std::make_unique(), *api_); + EXPECT_EQ(filter_config_->findExtractor("undefined"), nullptr); + EXPECT_NE(filter_config_->findExtractor("apikeys.ApiKeys.CreateApiKey"), nullptr); +} + +TEST_F(FilterConfigTestOk, ExtractDirectiveUnspecified) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: ExtractDirective_UNSPECIFIED } + request_extraction_by_field: { key: "key.name" value: ExtractDirective_UNSPECIFIED } + response_extraction_by_field: { key: "name" value: ExtractDirective_UNSPECIFIED } + } + })pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + filter_config_ = std::make_unique(proto_config_, + std::make_unique(), *api_); + EXPECT_EQ(filter_config_->findExtractor("undefined"), nullptr); + EXPECT_NE(filter_config_->findExtractor("apikeys.ApiKeys.CreateApiKey"), nullptr); +} + +TEST_F(FilterConfigTestOk, ExtractModeUnspecified) { + parseConfigProto(R"pb( + mode: ExtractMode_UNSPECIFIED + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: EXTRACT } + request_extraction_by_field: { key: "key.name" value: EXTRACT } + response_extraction_by_field: { key: "name" value: EXTRACT } + } + })pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + filter_config_ = std::make_unique(proto_config_, + std::make_unique(), *api_); + EXPECT_EQ(filter_config_->findExtractor("undefined"), nullptr); + EXPECT_NE(filter_config_->findExtractor("apikeys.ApiKeys.CreateApiKey"), nullptr); +} + +TEST_F(FilterConfigTestOk, DescriptorFromFile) { + parseConfigProto(); + *proto_config_.mutable_data_source()->mutable_filename() = + TestEnvironment::runfilesPath("test/proto/apikeys.descriptor"); + filter_config_ = std::make_unique(proto_config_, + std::make_unique(), *api_); + EXPECT_EQ(filter_config_->findExtractor("undefined"), nullptr); + EXPECT_NE(filter_config_->findExtractor("apikeys.ApiKeys.CreateApiKey"), nullptr); +} + +TEST_F(FilterConfigTestOk, AllSupportedTypes) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "supported_types.string" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.uint32" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.uint64" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.int32" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.int64" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.sint32" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.sint64" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.fixed32" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.fixed64" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.float" value: EXTRACT } + request_extraction_by_field: { key: "supported_types.double" value: EXTRACT } + } + })pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + filter_config_ = std::make_unique(proto_config_, + std::make_unique(), *api_); + EXPECT_EQ(filter_config_->findExtractor("undefined"), nullptr); + EXPECT_NE(filter_config_->findExtractor("apikeys.ApiKeys.CreateApiKey"), nullptr); +} + +TEST_F(FilterConfigTestOk, RepeatedField) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { + key: "repeated_supported_types.string" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.uint32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.uint64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.int32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.int64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.sint32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.sint64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.fixed32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.fixed64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.float" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.double" + value: EXTRACT + } + } + })pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + filter_config_ = std::make_unique(proto_config_, + std::make_unique(), *api_); + EXPECT_EQ(filter_config_->findExtractor("undefined"), nullptr); + EXPECT_NE(filter_config_->findExtractor("apikeys.ApiKeys.CreateApiKey"), nullptr); +} + +TEST_F(FilterConfigTestOk, ExtractRedact) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { + key: "repeated_supported_types.string" + value: EXTRACT_REDACT + } + response_extraction_by_field: { + key: "name" + value: EXTRACT_REDACT + } + } + })pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + filter_config_ = std::make_unique(proto_config_, + std::make_unique(), *api_); + EXPECT_EQ(filter_config_->findExtractor("undefined"), nullptr); + EXPECT_NE(filter_config_->findExtractor("apikeys.ApiKeys.CreateApiKey"), nullptr); +} + +using FilterConfigTestException = FilterConfigTestBase; +TEST_F(FilterConfigTestException, ErrorParsingDescriptorInline) { + parseConfigProto(); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = "123"; + EXPECT_THAT_THROWS_MESSAGE( + std::make_unique(proto_config_, std::make_unique(), + *api_), + EnvoyException, testing::HasSubstr("unable to parse proto descriptor from inline bytes:")); +} + +TEST_F(FilterConfigTestException, ErrorParsingDescriptorFromFile) { + parseConfigProto(); + *proto_config_.mutable_data_source()->mutable_filename() = + TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcacert.pem"); + EXPECT_THAT_THROWS_MESSAGE(std::make_unique( + proto_config_, std::make_unique(), *api_), + EnvoyException, + testing::HasSubstr("unable to parse proto descriptor from file")); +} + +TEST_F(FilterConfigTestException, UnsupportedDescriptorSourceType) { + parseConfigProto(); + *proto_config_.mutable_data_source()->mutable_inline_string() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + EXPECT_THAT_THROWS_MESSAGE( + std::make_unique(proto_config_, std::make_unique(), + *api_), + EnvoyException, + testing::HasSubstr("unsupported DataSource case `3` for configuring `descriptor_set`")); +} + +TEST_F(FilterConfigTestException, GrpcMethodNotFoundInProtoDescriptor) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "not-found-in-proto-descriptor" + value: { request_extraction_by_field: { key: "parent" value: EXTRACT } } + } + )pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + + EXPECT_THAT_THROWS_MESSAGE(std::make_unique( + proto_config_, std::make_unique(), *api_), + EnvoyException, + testing::HasSubstr("couldn't find the gRPC method " + "`not-found-in-proto-descriptor` defined in " + "the proto descriptor")); +} + +TEST_F(FilterConfigTestException, UndefinedPathInRequest) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { request_extraction_by_field: { key: "undefined-path" value: EXTRACT } } + } + )pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + + EXPECT_THAT_THROWS_MESSAGE( + std::make_unique(proto_config_, std::make_unique(), + *api_), + EnvoyException, + testing::HasSubstr( + R"(couldn't init extractor for method `apikeys.ApiKeys.CreateApiKey`: Invalid fieldPath (undefined-path): no 'undefined-path' field in 'type.googleapis.com/apikeys.CreateApiKeyRequest' message)")); +} + +TEST_F(FilterConfigTestException, UndefinedPathInResponse) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: EXTRACT } + response_extraction_by_field: { key: "undefined-path" value: EXTRACT } + } + } + )pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + + EXPECT_THAT_THROWS_MESSAGE( + std::make_unique(proto_config_, std::make_unique(), + *api_), + EnvoyException, + testing::HasSubstr( + R"(couldn't init extractor for method `apikeys.ApiKeys.CreateApiKey`: Invalid fieldPath (undefined-path): no 'undefined-path' field in 'type.googleapis.com/apikeys.ApiKey' message)")); +} + +TEST_F(FilterConfigTestException, UnsupportedTypeBool) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "unsupported_types.bool" value: EXTRACT } + } + } + )pb"); + *proto_config_.mutable_data_source()->mutable_filename() = + TestEnvironment::runfilesPath("test/proto/apikeys.descriptor"); + + EXPECT_THAT_THROWS_MESSAGE( + std::make_unique(proto_config_, std::make_unique(), + *api_), + EnvoyException, + testing::HasSubstr( + R"(couldn't init extractor for method `apikeys.ApiKeys.CreateApiKey`: leaf node 'bool' must be numerical/string)")); +} + +TEST_F(FilterConfigTestException, UnsupportedTypeMessage) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { + key: "unsupported_types.message" + value: EXTRACT + } + } + } + )pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + + EXPECT_THAT_THROWS_MESSAGE( + std::make_unique(proto_config_, std::make_unique(), + *api_), + EnvoyException, + testing::HasSubstr( + R"(couldn't init extractor for method `apikeys.ApiKeys.CreateApiKey`: leaf node 'message' must be numerical/string)")); +} + +TEST_F(FilterConfigTestException, RedactNonLeafField) { + parseConfigProto(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "key" value: EXTRACT_REDACT } + } + })pb"); + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + + EXPECT_THAT_THROWS_MESSAGE( + std::make_unique(proto_config_, std::make_unique(), + *api_), + EnvoyException, + testing::HasSubstr( + R"(couldn't init extractor for method `apikeys.ApiKeys.CreateApiKey`: leaf node 'key' must be numerical/string or timestamp type)")); +} + +TEST(FilterFactoryCreatorTest, Constructor) { + FilterFactoryCreator factory; + EXPECT_EQ(factory.name(), "envoy.filters.http.proto_message_extraction"); +} + +} // namespace + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/http/proto_message_extraction/filter_test.cc b/test/extensions/filters/http/proto_message_extraction/filter_test.cc new file mode 100644 index 000000000000..579a4bb11372 --- /dev/null +++ b/test/extensions/filters/http/proto_message_extraction/filter_test.cc @@ -0,0 +1,2288 @@ +#include +#include +#include + +#include "source/extensions/filters/http/proto_message_extraction/extractor_impl.h" +#include "source/extensions/filters/http/proto_message_extraction/filter.h" +#include "source/extensions/filters/http/proto_message_extraction/filter_config.h" + +#include "test/extensions/filters/http/grpc_field_extraction/message_converter/message_converter_test_lib.h" +#include "test/mocks/http/mocks.h" +#include "test/proto/apikeys.pb.h" +#include "test/test_common/environment.h" +#include "test/test_common/utility.h" + +#include "absl/log/log.h" +#include "absl/strings/string_view.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { +namespace { + +using ::apikeys::ApiKey; +using ::apikeys::CreateApiKeyRequest; +using ::envoy::extensions::filters::http::proto_message_extraction::v3:: + ProtoMessageExtractionConfig; +using ::Envoy::Extensions::HttpFilters::GrpcFieldExtraction::checkSerializedData; +using ::Envoy::Http::MockStreamDecoderFilterCallbacks; +using ::Envoy::Http::MockStreamEncoderFilterCallbacks; +using ::Envoy::Http::TestRequestHeaderMapImpl; +using ::Envoy::Http::TestResponseHeaderMapImpl; +using ::Envoy::ProtobufWkt::Struct; +using ::testing::Eq; + +constexpr absl::string_view kFilterName = "envoy.filters.http.proto_message_extraction"; + +constexpr absl::string_view kExpectedRequestExtractedResult = R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "parent" + value { + string_value: "project-id" + } + } + } + } + } + } + } +} +)pb"; + +constexpr absl::string_view kExpectedResponseExtractedResult = R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "name" + value { + string_value: "apikey-name" + } + } + } + } + } + } + } +} +)pb"; + +void checkProtoStruct(Envoy::ProtobufWkt::Struct got, absl::string_view expected_in_pbtext) { + Envoy::ProtobufWkt::Struct expected; + ASSERT_THAT(Envoy::Protobuf::TextFormat::ParseFromString(expected_in_pbtext, &expected), true); + EXPECT_THAT(Envoy::TestUtility::protoEqual(got, expected, true), true) + << "got:\n" + << got.DebugString() << "expected:\n" + << expected_in_pbtext; +} + +void splitBuffer(Envoy::Buffer::InstancePtr& data, uint32_t start_size, uint32_t middle_size, + Envoy::Buffer::OwnedImpl& start, Envoy::Buffer::OwnedImpl& middle, + Envoy::Buffer::OwnedImpl& end) { + start.move(*data, start_size); + middle.move(*data, middle_size); + end.move(*data); + EXPECT_EQ(data->length(), 0); +} + +class FilterTestBase : public ::testing::Test { +protected: + FilterTestBase() : api_(Envoy::Api::createApiForTest()) {} + + void setUp(absl::string_view config = "") { + ASSERT_THAT(Envoy::Protobuf::TextFormat::ParseFromString( + config.empty() ? protoConfig() : config, &proto_config_), + true); + + *proto_config_.mutable_data_source()->mutable_inline_bytes() = + api_->fileSystem() + .fileReadToEnd(Envoy::TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")) + .value(); + + ON_CALL(mock_decoder_callbacks_, decoderBufferLimit()) + .WillByDefault(testing::Return(UINT32_MAX)); + + ON_CALL(mock_encoder_callbacks_, encoderBufferLimit()) + .WillByDefault(testing::Return(UINT32_MAX)); + + filter_config_ = std::make_unique( + proto_config_, std::make_unique(), *api_); + + filter_ = std::make_unique(*filter_config_); + filter_->setDecoderFilterCallbacks(mock_decoder_callbacks_); + filter_->setEncoderFilterCallbacks(mock_encoder_callbacks_); + } + + void TearDown() override { + // Test onDestroy doesn't crash. + filter_->PassThroughDecoderFilter::onDestroy(); + filter_->PassThroughEncoderFilter::onDestroy(); + } + + virtual std::string protoConfig() { + return R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: EXTRACT } + response_extraction_by_field: { key: "name" value: EXTRACT } + } + } + )pb"; + } + + Envoy::Api::ApiPtr api_; + std::string config_; + ProtoMessageExtractionConfig proto_config_; + std::unique_ptr filter_config_; + testing::NiceMock mock_decoder_callbacks_; + testing::NiceMock mock_encoder_callbacks_; + std::unique_ptr filter_; +}; + +apikeys::CreateApiKeyRequest makeCreateApiKeyRequest(absl::string_view pb = R"pb( + parent: "project-id" + key: { + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } + } + )pb") { + apikeys::CreateApiKeyRequest request; + Envoy::Protobuf::TextFormat::ParseFromString(pb, &request); + return request; +} + +apikeys::ApiKey makeCreateApiKeyResponse(absl::string_view pb = R"pb( + name: "apikey-name" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb") { + apikeys::ApiKey response; + Envoy::Protobuf::TextFormat::ParseFromString(pb, &response); + return response; +} + +using FilterTestExtractOk = FilterTestBase; + +TEST_F(FilterTestExtractOk, UnarySingleBuffer) { + setUp(); + + Envoy::Http::TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedRequestExtractedResult); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedResponseExtractedResult); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +TEST_F(FilterTestExtractOk, UnarySingleBufferWithMultipleFields) { + setUp(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: EXTRACT } + request_extraction_by_field: { key: "key.display_name" value: EXTRACT } + request_extraction_by_field: { key: "key.current_key" value: EXTRACT } + response_extraction_by_field: { key: "name" value: EXTRACT } + response_extraction_by_field: { key: "display_name" value: EXTRACT } + response_extraction_by_field: { key: "current_key" value: EXTRACT } + } + } + )pb"); + + Envoy::Http::TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "key" + value { + struct_value { + fields { + key: "currentKey" + value { + string_value: "current-key" + } + } + fields { + key: "displayName" + value { + string_value: "Display Name" + } + } + } + } + } + fields { + key: "parent" + value { + string_value: "project-id" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "currentKey" + value { + string_value: "current-key" + } + } + fields { + key: "displayName" + value { + string_value: "Display Name" + } + } + fields { + key: "name" + value { + string_value: "apikey-name" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +TEST_F(FilterTestExtractOk, UnarySingleBufferWithMultipleFieldsforResponseOnly) { + setUp(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + response_extraction_by_field: { key: "name" value: EXTRACT } + response_extraction_by_field: { key: "display_name" value: EXTRACT } + response_extraction_by_field: { key: "current_key" value: EXTRACT } + } + } + )pb"); + Envoy::Http::TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "currentKey" + value { + string_value: "current-key" + } + } + fields { + key: "displayName" + value { + string_value: "Display Name" + } + } + fields { + key: "name" + value { + string_value: "apikey-name" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +TEST_F(FilterTestExtractOk, EmptyFields) { + setUp(); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(""); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + } + } + } + } + } +} +)pb"); + })); + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(""); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +TEST_F(FilterTestExtractOk, UnaryMultipeBuffers) { + setUp(); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + const uint32_t req_start_data_size = 3; + const uint32_t req_middle_data_size = 4; + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl start_request_data; + Envoy::Buffer::OwnedImpl middle_request_data; + Envoy::Buffer::OwnedImpl end_request_data; + splitBuffer(request_data, req_start_data_size, req_middle_data_size, start_request_data, + middle_request_data, end_request_data); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, + filter_->decodeData(start_request_data, false)); + EXPECT_EQ(start_request_data.length(), 0); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, + filter_->decodeData(middle_request_data, false)); + EXPECT_EQ(middle_request_data.length(), 0); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedRequestExtractedResult); + })); + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(end_request_data, true)); + + // Inject data back and no data modification. + checkSerializedData(end_request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, true)); + + const uint32_t resp_start_data_size = 1; + const uint32_t resp_middle_data_size = 2; + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl start_response_data; + Envoy::Buffer::OwnedImpl middle_response_data; + Envoy::Buffer::OwnedImpl end_response_data; + splitBuffer(response_data, resp_start_data_size, resp_middle_data_size, start_response_data, + middle_response_data, end_response_data); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, + filter_->encodeData(start_response_data, false)); + EXPECT_EQ(start_response_data.length(), 0); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, + filter_->encodeData(middle_response_data, false)); + EXPECT_EQ(middle_response_data.length(), 0); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedResponseExtractedResult); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(end_response_data, true)); + + // No data modification. + checkSerializedData(end_response_data, {response}); +} + +TEST_F(FilterTestExtractOk, StreamingMultipleMessageSingleBuffer) { + setUp(R"pb( +mode: FIRST_AND_LAST +extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKeyInStream" + value: { + request_extraction_by_field: { + key: "parent" + value: EXTRACT + } + response_extraction_by_field: { + key: "name" + value: EXTRACT + } + } +} + )pb"); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKeyInStream"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + CreateApiKeyRequest request1 = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data1 = Envoy::Grpc::Common::serializeToGrpcFrame(request1); + CreateApiKeyRequest request2 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req2" +)pb"); + Envoy::Buffer::InstancePtr request_data2 = Envoy::Grpc::Common::serializeToGrpcFrame(request2); + CreateApiKeyRequest request3 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req3" +)pb"); + Envoy::Buffer::InstancePtr request_data3 = Envoy::Grpc::Common::serializeToGrpcFrame(request3); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl request_data; + request_data.move(*request_data1); + request_data.move(*request_data2); + request_data.move(*request_data3); + EXPECT_EQ(request_data1->length(), 0); + EXPECT_EQ(request_data2->length(), 0); + EXPECT_EQ(request_data3->length(), 0); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(request_data, false)); + + // Inject data back and no data modification. + checkSerializedData(request_data, {request1, request2, request3}); + + // No op for the following messages. + CreateApiKeyRequest request4 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req4" +)pb"); + Envoy::Buffer::InstancePtr request_data4 = Envoy::Grpc::Common::serializeToGrpcFrame(request4); + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, "envoy.filters.http.proto_message_extraction"); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "parent" + value { + string_value: "project-id" + } + } + } + } + } + fields { + key: "last" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "parent" + value { + string_value: "from-req4" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data4, true)); + + // No data modification. + checkSerializedData(*request_data4, {request4}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, true)); + + apikeys::ApiKey response1 = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data1 = Envoy::Grpc::Common::serializeToGrpcFrame(response1); + apikeys::ApiKey response2 = makeCreateApiKeyResponse( + R"pb( + name: "apikey-name-2" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb"); + Envoy::Buffer::InstancePtr response_data2 = Envoy::Grpc::Common::serializeToGrpcFrame(response2); + apikeys::ApiKey response3 = makeCreateApiKeyResponse( + R"pb( + name: "apikey-name-3" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb"); + Envoy::Buffer::InstancePtr response_data3 = Envoy::Grpc::Common::serializeToGrpcFrame(response3); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl response_data; + response_data.move(*response_data1); + response_data.move(*response_data2); + response_data.move(*response_data3); + EXPECT_EQ(response_data1->length(), 0); + EXPECT_EQ(response_data2->length(), 0); + EXPECT_EQ(response_data3->length(), 0); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(response_data, false)); + + // Inject data back and no data modification. + checkSerializedData(response_data, {response1, response2, response3}); + + apikeys::ApiKey response4 = makeCreateApiKeyResponse( + R"pb( + name: "last-apikey-name" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb"); + Envoy::Buffer::InstancePtr response_data4 = Envoy::Grpc::Common::serializeToGrpcFrame(response4); + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, "envoy.filters.http.proto_message_extraction"); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "name" + value { + string_value: "apikey-name" + } + } + } + } + } + fields { + key: "last" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "name" + value { + string_value: "last-apikey-name" + } + } + } + } + } + } + } +} +)pb"); + })); + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data4, true)); + checkSerializedData(*response_data4, {response4}); +} + +TEST_F(FilterTestExtractOk, RequestResponseWithTrailers) { + setUp(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "key.display_name" value: EXTRACT } + response_extraction_by_field: { key: "display_name" value: EXTRACT } + } + } + )pb"); + Envoy::Http::TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "key" + value { + struct_value { + fields { + key: "displayName" + value { + string_value: "Display Name" + } + } + } + } + } + } + } + } + } + } +} +)pb"); + })); + + // Sending end_stream=false to indicate presence of trailers. + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, false)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "displayName" + value { + string_value: "Display Name" + } + } + } + } + } + } + } +} +)pb"); + })); + + // Sending end_stream=false to indicate presence of trailers. + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, false)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +using FilterTestFieldTypes = FilterTestBase; + +TEST_F(FilterTestFieldTypes, SingularType) { + setUp(R"pb( +mode: FIRST_AND_LAST +extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { + key: "supported_types.string" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.uint32" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.uint64" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.int32" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.int64" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.sint32" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.sint64" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.fixed32" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.fixed64" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.sfixed32" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.sfixed64" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.float" + value: EXTRACT + } + request_extraction_by_field: { + key: "supported_types.double" + value: EXTRACT + } + response_extraction_by_field: { + key: "kms_key" + value: EXTRACT + } + response_extraction_by_field: { + key: "location" + value: EXTRACT + } + } +})pb"); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, false)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest( + R"pb( +supported_types: { + string: "1" + uint32: 2 + uint64: 3 + int32: 4 + int64: 5 + sint32: 6 + sint64: 7 + fixed32: 8 + fixed64: 9 + sfixed32: 10 + sfixed64: 11 + float: 1.2 + double: 1.3 +} +)pb"); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, "envoy.filters.http.proto_message_extraction"); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "supportedTypes" + value { + struct_value { + fields { + key: "double" + value { + number_value: 1.3 + } + } + fields { + key: "fixed32" + value { + number_value: 8 + } + } + fields { + key: "fixed64" + value { + string_value: "9" + } + } + fields { + key: "float" + value { + number_value: 1.2 + } + } + fields { + key: "int32" + value { + number_value: 4 + } + } + fields { + key: "int64" + value { + string_value: "5" + } + } + fields { + key: "sfixed32" + value { + number_value: 10 + } + } + fields { + key: "sfixed64" + value { + string_value: "11" + } + } + fields { + key: "sint32" + value { + number_value: 6 + } + } + fields { + key: "sint64" + value { + string_value: "7" + } + } + fields { + key: "string" + value { + string_value: "1" + } + } + fields { + key: "uint32" + value { + number_value: 2 + } + } + fields { + key: "uint64" + value { + string_value: "3" + } + } + } + } + } + } + } + } + } + } +})pb"); + })); + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "kmsKey" + value { + string_value: "projects/my-project/locations/my-location" + } + } + fields { + key: "location" + value { + string_value: "global" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +TEST_F(FilterTestFieldTypes, RepeatedTypes) { + setUp(R"pb( +mode: FIRST_AND_LAST +extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { + key: "repeated_supported_types.string" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.uint32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.uint64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.int32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.int64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.sint32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.sint64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.fixed32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.fixed64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.sfixed32" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.sfixed64" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.float" + value: EXTRACT + } + request_extraction_by_field: { + key: "repeated_supported_types.double" + value: EXTRACT + } + } +})pb"); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, false)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest( + R"pb( +repeated_supported_types: { + string: "1" + uint32: 2 + uint64: 3 + int32: 4 + int64: 5 + sint32: 6 + sint64: 7 + fixed32: 8 + fixed64: 9 + sfixed32: 10 + sfixed64: 11 + float: 1.2 + double: 1.3 + string: "11" + uint32: 22 + uint64: 33 + int32: 44 + int64: 55 + sint32: 66 + sint64: 77 + fixed32: 88 + fixed64: 99 + sfixed32: 1010 + sfixed64: 1111 + float: 1.212 + double: 1.313 +} + +)pb"); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, "envoy.filters.http.proto_message_extraction"); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "repeatedSupportedTypes" + value { + struct_value { + fields { + key: "double" + value { + list_value { + values { + number_value: 1.3 + } + values { + number_value: 1.313 + } + } + } + } + fields { + key: "fixed32" + value { + list_value { + values { + number_value: 8 + } + values { + number_value: 88 + } + } + } + } + fields { + key: "fixed64" + value { + list_value { + values { + string_value: "9" + } + values { + string_value: "99" + } + } + } + } + fields { + key: "float" + value { + list_value { + values { + number_value: 1.2 + } + values { + number_value: 1.212 + } + } + } + } + fields { + key: "int32" + value { + list_value { + values { + number_value: 4 + } + values { + number_value: 44 + } + } + } + } + fields { + key: "int64" + value { + list_value { + values { + string_value: "5" + } + values { + string_value: "55" + } + } + } + } + fields { + key: "sfixed32" + value { + list_value { + values { + number_value: 10 + } + values { + number_value: 1010 + } + } + } + } + fields { + key: "sfixed64" + value { + list_value { + values { + string_value: "11" + } + values { + string_value: "1111" + } + } + } + } + fields { + key: "sint32" + value { + list_value { + values { + number_value: 6 + } + values { + number_value: 66 + } + } + } + } + fields { + key: "sint64" + value { + list_value { + values { + string_value: "7" + } + values { + string_value: "77" + } + } + } + } + fields { + key: "string" + value { + list_value { + values { + string_value: "1" + } + values { + string_value: "11" + } + } + } + } + fields { + key: "uint32" + value { + list_value { + values { + number_value: 2 + } + values { + number_value: 22 + } + } + } + } + fields { + key: "uint64" + value { + list_value { + values { + string_value: "3" + } + values { + string_value: "33" + } + } + } + } + } + } + } + } + } + } + } + } +})pb"); + })); + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); +} + +using FilterTestWithExtractRedacted = FilterTestBase; + +TEST_F(FilterTestWithExtractRedacted, UnarySingleBuffer) { + setUp(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: EXTRACT_REDACT } + request_extraction_by_field: { key: "key.name" value: EXTRACT_REDACT } + request_extraction_by_field: { key: "key.display_name" value: EXTRACT } + response_extraction_by_field: { key: "expire_time" value: EXTRACT_REDACT } + response_extraction_by_field: { key: "kms_key" value: EXTRACT } + } + } + )pb"); + + Envoy::Http::TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "key" + value { + struct_value { + fields { + key: "displayName" + value { + string_value: "Display Name" + } + } + } + } + } + fields { + key: "parent" + value { + struct_value { + } + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "expireTime" + value { + struct_value { + } + } + } + fields { + key: "kmsKey" + value { + string_value: "projects/my-project/locations/my-location" + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +TEST_F(FilterTestWithExtractRedacted, StreamingMultipleMessageSingleBuffer) { + setUp(R"pb( +mode: FIRST_AND_LAST +extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKeyInStream" + value: { + request_extraction_by_field: { + key: "parent" + value: EXTRACT_REDACT + } + response_extraction_by_field: { + key: "name" + value: EXTRACT_REDACT + } + } +} + )pb"); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKeyInStream"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + CreateApiKeyRequest request1 = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data1 = Envoy::Grpc::Common::serializeToGrpcFrame(request1); + CreateApiKeyRequest request2 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req2" +)pb"); + Envoy::Buffer::InstancePtr request_data2 = Envoy::Grpc::Common::serializeToGrpcFrame(request2); + CreateApiKeyRequest request3 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req3" +)pb"); + Envoy::Buffer::InstancePtr request_data3 = Envoy::Grpc::Common::serializeToGrpcFrame(request3); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl request_data; + request_data.move(*request_data1); + request_data.move(*request_data2); + request_data.move(*request_data3); + EXPECT_EQ(request_data1->length(), 0); + EXPECT_EQ(request_data2->length(), 0); + EXPECT_EQ(request_data3->length(), 0); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(request_data, false)); + + // Inject data back and no data modification. + checkSerializedData(request_data, {request1, request2, request3}); + + // No op for the following messages. + CreateApiKeyRequest request4 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req4" +)pb"); + Envoy::Buffer::InstancePtr request_data4 = Envoy::Grpc::Common::serializeToGrpcFrame(request4); + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, "envoy.filters.http.proto_message_extraction"); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "requests" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "parent" + value { + struct_value { + } + } + } + } + } + } + fields { + key: "last" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.CreateApiKeyRequest" + } + } + fields { + key: "parent" + value { + struct_value { + } + } + } + } + } + } + } + } +} +)pb"); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data4, true)); + + // No data modification. + checkSerializedData(*request_data4, {request4}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, true)); + + apikeys::ApiKey response1 = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data1 = Envoy::Grpc::Common::serializeToGrpcFrame(response1); + apikeys::ApiKey response2 = makeCreateApiKeyResponse( + R"pb( + name: "apikey-name-2" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb"); + Envoy::Buffer::InstancePtr response_data2 = Envoy::Grpc::Common::serializeToGrpcFrame(response2); + apikeys::ApiKey response3 = makeCreateApiKeyResponse( + R"pb( + name: "apikey-name-3" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb"); + Envoy::Buffer::InstancePtr response_data3 = Envoy::Grpc::Common::serializeToGrpcFrame(response3); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl response_data; + response_data.move(*response_data1); + response_data.move(*response_data2); + response_data.move(*response_data3); + EXPECT_EQ(response_data1->length(), 0); + EXPECT_EQ(response_data2->length(), 0); + EXPECT_EQ(response_data3->length(), 0); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(response_data, false)); + + // Inject data back and no data modification. + checkSerializedData(response_data, {response1, response2, response3}); + + apikeys::ApiKey response4 = makeCreateApiKeyResponse( + R"pb( + name: "last-apikey-name" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb"); + Envoy::Buffer::InstancePtr response_data4 = Envoy::Grpc::Common::serializeToGrpcFrame(response4); + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce(Invoke([](const std::string& ns, const ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, "envoy.filters.http.proto_message_extraction"); + checkProtoStruct(new_dynamic_metadata, R"pb( +fields { + key: "responses" + value { + struct_value { + fields { + key: "first" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "name" + value { + struct_value { + } + } + } + } + } + } + fields { + key: "last" + value { + struct_value { + fields { + key: "@type" + value { + string_value: "type.googleapis.com/apikeys.ApiKey" + } + } + fields { + key: "name" + value { + struct_value { + } + } + } + } + } + } + } + } +} +)pb"); + })); + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data4, true)); + checkSerializedData(*response_data4, {response4}); +} + +using FilterTestExtractRejected = FilterTestBase; + +TEST_F(FilterTestExtractRejected, BufferLimitedExceeded) { + setUp(); + ON_CALL(mock_decoder_callbacks_, decoderBufferLimit()).WillByDefault(testing::Return(0)); + + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_, + sendLocalReply( + Http::Code::BadRequest, "Rejected because internal buffer limits are exceeded.", + Eq(nullptr), Eq(Envoy::Grpc::Status::FailedPrecondition), + "proto_message_extraction_FAILED_PRECONDITION{REQUEST_BUFFER_CONVERSION_FAIL}")); + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, + filter_->decodeData(*request_data, true)); + + ON_CALL(mock_encoder_callbacks_, encoderBufferLimit()).WillByDefault(testing::Return(0)); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, true)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_, + sendLocalReply( + Http::Code::BadRequest, "Rejected because internal buffer limits are exceeded.", + Eq(nullptr), Eq(Envoy::Grpc::Status::FailedPrecondition), + "proto_message_extraction_FAILED_PRECONDITION{RESPONSE_BUFFER_CONVERSION_FAIL}")); + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, + filter_->encodeData(*response_data, true)); +} + +TEST_F(FilterTestExtractRejected, NotEnoughData) { + setUp(); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, false)); + + Envoy::Buffer::OwnedImpl empty; + + EXPECT_CALL(mock_decoder_callbacks_, + sendLocalReply(Http::Code::BadRequest, + "did not receive enough data to form a message.", Eq(nullptr), + Eq(Envoy::Grpc::Status::InvalidArgument), + "proto_message_extraction_INVALID_ARGUMENT{REQUEST_OUT_OF_DATA}")); + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, filter_->decodeData(empty, true)); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + EXPECT_CALL(mock_encoder_callbacks_, + sendLocalReply(Http::Code::BadRequest, + "did not receive enough data to form a message.", Eq(nullptr), + Eq(Envoy::Grpc::Status::InvalidArgument), + "proto_message_extraction_INVALID_ARGUMENT{RESPONSE_OUT_OF_DATA}")); + EXPECT_EQ(Envoy::Http::FilterDataStatus::StopIterationNoBuffer, filter_->encodeData(empty, true)); +} + +TEST_F(FilterTestExtractRejected, RequestMisformedGrpcPath) { + setUp(); + ON_CALL(mock_decoder_callbacks_, decoderBufferLimit()).WillByDefault(testing::Return(0)); + + TestRequestHeaderMapImpl req_headers = TestRequestHeaderMapImpl{ + {":method", "POST"}, {":path", "/misformatted"}, {"content-type", "application/grpc"}}; + EXPECT_CALL(mock_decoder_callbacks_, + sendLocalReply(Http::Code::BadRequest, + ":path `/misformatted` should be in form of `/package.service/method`", + Eq(nullptr), Eq(Envoy::Grpc::Status::InvalidArgument), + "proto_message_extraction_INVALID_ARGUMENT{BAD_REQUEST}")); + + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, false)); +} + +using FilterTestPassThrough = FilterTestBase; + +TEST_F(FilterTestPassThrough, RequestNotGrpc) { + setUp(); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "not-grpc"}}; + + // Pass through headers directly. + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(req_headers, true)); +} + +TEST_F(FilterTestPassThrough, ResponseNotGrpc) { + setUp(); + Envoy::Http::TestResponseHeaderMapImpl resp_headers = + TestResponseHeaderMapImpl{{":status", "200"}, {"content-type", "application/grpc"}}; + + // Pass through headers directly. + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::Continue, filter_->encodeHeaders(resp_headers, true)); +} + +TEST_F(FilterTestPassThrough, PathNotExist) { + setUp(); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, {"content-type", "application/grpc"}}; + + // Pass through headers directly. + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(req_headers, true)); +} + +TEST_F(FilterTestPassThrough, UnconfiguredRequest) { + setUp(); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/pkg.svc/UnconfiguredRequest"}, + {"content-type", "application/grpc"}}; + + // Pass through headers directly. + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(req_headers, true)); +} + +TEST_F(FilterTestPassThrough, NothingToExtract) { + setUp(R"pb( +mode: FIRST_AND_LAST +extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKeyInStream" + value: {} +} + )pb"); + TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(""); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::Continue, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(""); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +using FilterTestWithExtractModeUnspecified = FilterTestBase; + +TEST_F(FilterTestWithExtractModeUnspecified, ModeUnspecified) { + // Mode unspecified is treated as FIRST_AND_LAST. + setUp(R"pb( + mode: ExtractMode_UNSPECIFIED + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: EXTRACT } + response_extraction_by_field: { key: "name" value: EXTRACT } + } + } + )pb"); + + Envoy::Http::TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedRequestExtractedResult); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedResponseExtractedResult); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} + +// ExtractDirective_UNSPECIFIED is treated as EXTRACT. +using FilterTestWithExtractDirectiveUnspecified = FilterTestBase; + +TEST_F(FilterTestWithExtractDirectiveUnspecified, HappyPath) { + setUp(R"pb( + mode: FIRST_AND_LAST + extraction_by_method: { + key: "apikeys.ApiKeys.CreateApiKey" + value: { + request_extraction_by_field: { key: "parent" value: ExtractDirective_UNSPECIFIED } + response_extraction_by_field: { key: "name" value: ExtractDirective_UNSPECIFIED } + } + } + )pb"); + + Envoy::Http::TestRequestHeaderMapImpl req_headers = + TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}}; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->decodeHeaders(req_headers, true)); + + CreateApiKeyRequest request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + + EXPECT_CALL(mock_decoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedRequestExtractedResult); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->decodeData(*request_data, true)); + + // No data modification. + checkSerializedData(*request_data, {request}); + + Envoy::Http::TestResponseHeaderMapImpl resp_headers = TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::StopIteration, + filter_->encodeHeaders(resp_headers, false)); + + apikeys::ApiKey response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = Envoy::Grpc::Common::serializeToGrpcFrame(response); + + EXPECT_CALL(mock_encoder_callbacks_.stream_info_, setDynamicMetadata(_, _)) + .WillOnce( + Invoke([](const std::string& ns, const Envoy::ProtobufWkt::Struct& new_dynamic_metadata) { + EXPECT_EQ(ns, kFilterName); + checkProtoStruct(new_dynamic_metadata, kExpectedResponseExtractedResult); + })); + + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, filter_->encodeData(*response_data, true)); + + // No data modification. + checkSerializedData(*response_data, {response}); +} +} // namespace + +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/http/proto_message_extraction/integration_test.cc b/test/extensions/filters/http/proto_message_extraction/integration_test.cc new file mode 100644 index 000000000000..20879c91cb60 --- /dev/null +++ b/test/extensions/filters/http/proto_message_extraction/integration_test.cc @@ -0,0 +1,279 @@ +#include +#include + +#include "envoy/common/optref.h" + +#include "test/extensions/filters/http/grpc_field_extraction/message_converter/message_converter_test_lib.h" +#include "test/integration/http_protocol_integration.h" +#include "test/proto/apikeys.pb.h" + +#include "absl/strings/str_format.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace ProtoMessageExtraction { +namespace { + +using ::apikeys::ApiKey; +using ::apikeys::CreateApiKeyRequest; +using ::Envoy::Extensions::HttpFilters::GrpcFieldExtraction::checkSerializedData; + +void compareJson(const std::string& actual, const std::string& expected) { + ProtobufWkt::Value expected_value, actual_value; + TestUtility::loadFromJson(expected, expected_value); + TestUtility::loadFromJson(actual, actual_value); + EXPECT_TRUE(TestUtility::protoEqual(expected_value, actual_value)) + << "got:\n" + << actual_value.DebugString() << "\nexpected:\n" + << expected_value.DebugString(); +} + +class IntegrationTest : public HttpProtocolIntegrationTest { +public: + void SetUp() override { + HttpProtocolIntegrationTest::SetUp(); + + config_helper_.prependFilter(filter()); + useAccessLog("%DYNAMIC_METADATA(envoy.filters.http.proto_message_extraction)%"); + + initialize(); + } + + void TearDown() override { + cleanupUpstreamAndDownstream(); + HttpProtocolIntegrationTest::TearDown(); + } + + void sendResponse(IntegrationStreamDecoder* response, Envoy::Buffer::Instance* response_data) { + Envoy::Http::TestResponseHeaderMapImpl resp_headers = Envoy::Http::TestResponseHeaderMapImpl{ + {":status", "200"}, + {"grpc-status", "1"}, + {"content-type", "application/grpc"}, + }; + upstream_request_->encodeHeaders(resp_headers, false); + upstream_request_->encodeData(*response_data, true); + ASSERT_TRUE(response->waitForEndStream()); + } + + std::string filter() { + return absl::StrFormat( + R"EOF( +name: proto_message_extraction +typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.proto_message_extraction.v3.ProtoMessageExtractionConfig + mode: FIRST_AND_LAST + data_source: + filename: %s + extraction_by_method: + apikeys.ApiKeys.CreateApiKey: + request_extraction_by_field: + parent: EXTRACT + response_extraction_by_field: + name: EXTRACT + apikeys.ApiKeys.CreateApiKeyInStream: + request_extraction_by_field: + parent: EXTRACT + response_extraction_by_field: + name: EXTRACT +)EOF", + TestEnvironment::runfilesPath("test/proto/apikeys.descriptor")); + } +}; + +CreateApiKeyRequest makeCreateApiKeyRequest(absl::string_view pb = R"pb( + parent: "project-id" +)pb") { + CreateApiKeyRequest request; + Protobuf::TextFormat::ParseFromString(pb, &request); + return request; +} + +apikeys::ApiKey makeCreateApiKeyResponse(absl::string_view pb = R"pb( + name: "apikey-name" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } +)pb") { + apikeys::ApiKey response; + Envoy::Protobuf::TextFormat::ParseFromString(pb, &response); + return response; +} + +TEST_P(IntegrationTest, Unary) { + codec_client_ = makeHttpConnection(lookupPort("http")); + auto request = makeCreateApiKeyRequest(); + Envoy::Buffer::InstancePtr request_data = Envoy::Grpc::Common::serializeToGrpcFrame(request); + auto request_headers = Http::TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKey"}, + {"content-type", "application/grpc"}, + {":authority", "host"}, + {":scheme", "http"}}; + + auto response = codec_client_->makeRequestWithBody(request_headers, request_data->toString()); + waitForNextUpstreamRequest(); + + // Make sure that the body was properly propagated (with no modification). + EXPECT_TRUE(upstream_request_->complete()); + EXPECT_TRUE(upstream_request_->receivedData()); + EXPECT_EQ(upstream_request_->body().toString(), request_data->toString()); + + // Send response. + ApiKey apikey_response = makeCreateApiKeyResponse(); + Envoy::Buffer::InstancePtr response_data = + Envoy::Grpc::Common::serializeToGrpcFrame(apikey_response); + sendResponse(response.get(), response_data.get()); + + compareJson(waitForAccessLog(access_log_name_), + R"( +{ + "requests": { + "first": { + "@type": "type.googleapis.com/apikeys.CreateApiKeyRequest", + "parent": "project-id" + } + }, + "responses": { + "first": { + "@type": "type.googleapis.com/apikeys.ApiKey", + "name": "apikey-name" + } + } +})"); +} + +TEST_P(IntegrationTest, Streaming) { + codec_client_ = makeHttpConnection(lookupPort("http")); + auto request_headers = + Http::TestRequestHeaderMapImpl{{":method", "POST"}, + {":path", "/apikeys.ApiKeys/CreateApiKeyInStream"}, + {"content-type", "application/grpc"}, + {":authority", "host"}, + {":scheme", "http"}}; + + CreateApiKeyRequest request1 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req1" + )pb"); + Envoy::Buffer::InstancePtr request_data1 = Envoy::Grpc::Common::serializeToGrpcFrame(request1); + CreateApiKeyRequest request2 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req2" + )pb"); + Envoy::Buffer::InstancePtr request_data2 = Envoy::Grpc::Common::serializeToGrpcFrame(request2); + CreateApiKeyRequest request3 = makeCreateApiKeyRequest( + R"pb( + parent: "from-req3" + )pb"); + Envoy::Buffer::InstancePtr request_data3 = Envoy::Grpc::Common::serializeToGrpcFrame(request3); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl request_data; + request_data.move(*request_data1); + request_data.move(*request_data2); + request_data.move(*request_data3); + EXPECT_EQ(request_data1->length(), 0); + EXPECT_EQ(request_data2->length(), 0); + EXPECT_EQ(request_data3->length(), 0); + + auto response = codec_client_->makeRequestWithBody(request_headers, request_data.toString()); + waitForNextUpstreamRequest(); + + // Make sure that the body was properly propagated (with no modification). + EXPECT_TRUE(upstream_request_->complete()); + EXPECT_TRUE(upstream_request_->receivedData()); + checkSerializedData(upstream_request_->body(), + {request1, request2, request3}); + + // Create streaming response and send it. + ApiKey response1 = makeCreateApiKeyResponse( + R"pb( + name: "apikey-name-1" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } + )pb"); + Envoy::Buffer::InstancePtr response_data1 = Envoy::Grpc::Common::serializeToGrpcFrame(response1); + ApiKey response2 = makeCreateApiKeyResponse( + R"pb( + name: "apikey-name-2" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } + )pb"); + Envoy::Buffer::InstancePtr response_data2 = Envoy::Grpc::Common::serializeToGrpcFrame(response2); + ApiKey response3 = makeCreateApiKeyResponse( + R"pb( + name: "apikey-name-3" + display_name: "Display Name" + current_key: "current-key" + create_time { seconds: 1684306560 nanos: 0 } + update_time { seconds: 1684306560 nanos: 0 } + location: "global" + kms_key: "projects/my-project/locations/my-location" + expire_time { seconds: 1715842560 nanos: 0 } + )pb"); + Envoy::Buffer::InstancePtr response_data3 = Envoy::Grpc::Common::serializeToGrpcFrame(response3); + + // Split into multiple buffers. + Envoy::Buffer::OwnedImpl response_data; + response_data.move(*response_data1); + response_data.move(*response_data2); + response_data.move(*response_data3); + EXPECT_EQ(response_data1->length(), 0); + EXPECT_EQ(response_data2->length(), 0); + EXPECT_EQ(response_data3->length(), 0); + + sendResponse(response.get(), &response_data); + + // Inject data back and no data modification. + checkSerializedData(response_data, {response1, response2, response3}); + + compareJson(waitForAccessLog(access_log_name_), R"( +{ + "responses": { + "first": { + "name": "apikey-name-1", + "@type": "type.googleapis.com/apikeys.ApiKey" + }, + "last": { + "name": "apikey-name-3", + "@type": "type.googleapis.com/apikeys.ApiKey" + } + }, + "requests": { + "last": { + "@type": "type.googleapis.com/apikeys.CreateApiKeyRequest", + "parent": "from-req3" + }, + "first": { + "@type": "type.googleapis.com/apikeys.CreateApiKeyRequest", + "parent": "from-req1" + } + } +})"); +} + +INSTANTIATE_TEST_SUITE_P(Protocols, IntegrationTest, + testing::ValuesIn(HttpProtocolIntegrationTest::getProtocolTestParams( + /*downstream_protocols=*/{Http::CodecType::HTTP2}, + /*upstream_protocols=*/{Http::CodecType::HTTP2})), + HttpProtocolIntegrationTest::protocolTestParamsToString); + +} // namespace +} // namespace ProtoMessageExtraction +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/proto/BUILD b/test/proto/BUILD index 81de53e0a69c..2817301f6fdf 100644 --- a/test/proto/BUILD +++ b/test/proto/BUILD @@ -66,18 +66,18 @@ envoy_proto_descriptor( ) envoy_proto_library( - name = "logging_proto", + name = "extraction_proto", srcs = [ - "logging.proto", + "extraction.proto", ], ) envoy_proto_descriptor( - name = "logging_proto_descriptor", + name = "extraction_proto_descriptor", srcs = [ - "logging.proto", + "extraction.proto", ], - out = "logging.descriptor", + out = "extraction.descriptor", ) envoy_proto_library( diff --git a/test/proto/apikeys.proto b/test/proto/apikeys.proto index d292f7ad7d42..ec76e547a479 100644 --- a/test/proto/apikeys.proto +++ b/test/proto/apikeys.proto @@ -2,11 +2,10 @@ syntax = "proto3"; package apikeys; -import "google/protobuf/timestamp.proto"; import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; service ApiKeys { - // Creates a new API key. rpc CreateApiKey(CreateApiKeyRequest) returns (ApiKey) { } @@ -17,7 +16,6 @@ service ApiKeys { // Message for an API key. message ApiKey { - string name = 1; string display_name = 2; diff --git a/test/proto/logging.proto b/test/proto/extraction.proto similarity index 93% rename from test/proto/logging.proto rename to test/proto/extraction.proto index 15d56aea9126..e908c2420537 100644 --- a/test/proto/logging.proto +++ b/test/proto/extraction.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package logging; +package extraction; message TestBucket { string name = 1; @@ -105,7 +105,7 @@ message TestResponse { SubMessage sub_message = 6; } -service AuditLoggingUtilTestService { - // AuditTest Method. - rpc AuditTest(TestRequest) returns (TestResponse); +service ExtractionUtilTestService { + // ExtractTest Method. + rpc ExtractTest(TestRequest) returns (TestResponse); } diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index 99c4774846c1..8a612b1f1476 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -203,6 +203,7 @@ paths: - source/common/protobuf/utility.cc - source/common/protobuf/protobuf.h - source/common/protobuf/yaml_utility.cc + - source/extensions/filters/http/proto_message_extraction/extraction_util/extraction_util.cc - test/extensions/bootstrap/wasm/test_data/speed_cpp.cc namespace_check: @@ -224,6 +225,7 @@ paths: - ci/prebuilt - source/common/protobuf - source/extensions/filters/http/grpc_field_extraction + - source/extensions/filters/http/proto_message_extraction/extraction_util - test/extensions/bootstrap/wasm/test_data # Files that are allowed to use try without main thread assertion. From a27b08073ff11c491a80b25cc63f4c53dab72ed8 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Tue, 27 Aug 2024 15:51:44 +0200 Subject: [PATCH 53/53] Fix flaky geoip test (#35862) On some runs mmdb_reload custom thread is not starting until tests ends which results in segfaults in the test. Addding cond var to await in the test for when mmdb reload thread has populated the callbacks. Commit Message: Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] Fixes #35829 [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] --------- Signed-off-by: Kateryna Nezdolii --- .../maxmind/geoip_provider_test.cc | 78 ++++++++++++------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 1d4eae7932ed..b8d1cc93b647 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -101,22 +101,29 @@ class GeoipProviderTestBase { on_changed_cbs_.clear(); }; - void initializeProvider(const std::string& yaml) { + void initializeProvider(const std::string& yaml, + absl::optional& conditional) { EXPECT_CALL(context_, scope()).WillRepeatedly(ReturnRef(*scope_)); EXPECT_CALL(context_, serverFactoryContext()) .WillRepeatedly(ReturnRef(server_factory_context_)); EXPECT_CALL(server_factory_context_, api()).WillRepeatedly(ReturnRef(*api_)); - EXPECT_CALL(dispatcher_, createFilesystemWatcher_()).WillRepeatedly(InvokeWithoutArgs([this] { - Filesystem::MockWatcher* mock_watcher = new NiceMock(); - EXPECT_CALL(*mock_watcher, addWatch(_, Filesystem::Watcher::Events::MovedTo, _)) - .WillRepeatedly( - Invoke([this](absl::string_view, uint32_t, Filesystem::Watcher::OnChangedCb cb) { - absl::WriterMutexLock lock(&mutex_); - on_changed_cbs_.emplace_back(std::move(cb)); + EXPECT_CALL(dispatcher_, createFilesystemWatcher_()) + .WillRepeatedly(Invoke([this, &conditional] { + Filesystem::MockWatcher* mock_watcher = new NiceMock(); + EXPECT_CALL(*mock_watcher, addWatch(_, Filesystem::Watcher::Events::MovedTo, _)) + .WillRepeatedly(Invoke([this, &conditional](absl::string_view, uint32_t, + Filesystem::Watcher::OnChangedCb cb) { + { + absl::WriterMutexLock lock(&mutex_); + on_changed_cbs_.emplace_back(std::move(cb)); + } + if (conditional.has_value()) { + conditional->setReady(); + } return absl::OkStatus(); })); - return mock_watcher; - })); + return mock_watcher; + })); EXPECT_CALL(server_factory_context_, mainThreadDispatcher()) .WillRepeatedly(ReturnRef(dispatcher_)); envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig config; @@ -155,6 +162,7 @@ class GeoipProviderTestBase { absl::flat_hash_map captured_lookup_response_; absl::Mutex mutex_; std::vector on_changed_cbs_ ABSL_GUARDED_BY(mutex_); + absl::optional cb_added_nullopt = absl::nullopt; }; class GeoipProviderTest : public testing::Test, public GeoipProviderTestBase {}; @@ -170,7 +178,7 @@ TEST_F(GeoipProviderTest, ValidConfigCityAndIspDbsSuccessfulLookup) { city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" isp_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb" )EOF"; - initializeProvider(config_yaml); + initializeProvider(config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -199,7 +207,7 @@ TEST_F(GeoipProviderTest, ValidConfigCityLookupError) { city: "x-geo-city" city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/MaxMind-DB-test-ipv4-24.mmdb" )EOF"; - initializeProvider(config_yaml); + initializeProvider(config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("2345:0425:2CA1:0:0:0567:5673:23b5"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -221,7 +229,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonVpnSuccessfulLookup) { anon_vpn: "x-geo-anon-vpn" anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; - initializeProvider(config_yaml); + initializeProvider(config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("1.2.0.0"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -245,7 +253,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonHostingSuccessfulLookup) { anon_hosting: "x-geo-anon-hosting" anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; - initializeProvider(config_yaml); + initializeProvider(config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("71.160.223.45"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -269,7 +277,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonTorNodeSuccessfulLookup) { anon_tor: "x-geo-anon-tor" anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; - initializeProvider(config_yaml); + initializeProvider(config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("65.4.3.2"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -293,7 +301,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonProxySuccessfulLookup) { anon_proxy: "x-geo-anon-proxy" anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; - initializeProvider(config_yaml); + initializeProvider(config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("abcd:1000::1"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -310,7 +318,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonProxySuccessfulLookup) { } TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { - initializeProvider(default_anon_config_yaml); + initializeProvider(default_anon_config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("10.10.10.10"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -323,7 +331,7 @@ TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { } TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { - initializeProvider(default_city_config_yaml); + initializeProvider(default_city_config_yaml, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address1 = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); Geolocation::LookupRequest lookup_rq1{std::move(remote_address1)}; @@ -361,7 +369,8 @@ TEST_F(GeoipProviderTest, DbReloadedOnMmdbFileUpdate) { "}}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test-Updated.mmdb"); const std::string formatted_config = fmt::format(config_yaml, TestEnvironment::substitute(city_db_path)); - initializeProvider(formatted_config); + auto cb_added_opt = absl::make_optional(); + initializeProvider(formatted_config, cb_added_opt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -374,8 +383,9 @@ TEST_F(GeoipProviderTest, DbReloadedOnMmdbFileUpdate) { EXPECT_EQ("Boxford", city_it->second); TestEnvironment::renameFile(city_db_path, city_db_path + "1"); TestEnvironment::renameFile(reloaded_city_db_path, city_db_path); + cb_added_opt.value().waitReady(); { - absl::MutexLock guard(&mutex_); + absl::ReaderMutexLock guard(&mutex_); EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); } expectReloadStats("city_db", 1, 0); @@ -387,6 +397,7 @@ TEST_F(GeoipProviderTest, DbReloadedOnMmdbFileUpdate) { auto lookup_cb_std2 = lookup_cb2.AsStdFunction(); EXPECT_CALL(lookup_cb2, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); provider_->lookup(std::move(lookup_rq2), std::move(lookup_cb_std2)); + const auto& city1_it = captured_lookup_response_.find("x-geo-city"); EXPECT_EQ("BoxfordImaginary", city1_it->second); // Clean up modifications to mmdb file names. @@ -412,7 +423,8 @@ TEST_F(GeoipProviderTest, DbReloadError) { "libmaxminddb-offset-integer-overflow.mmdb"); const std::string formatted_config = fmt::format(config_yaml, TestEnvironment::substitute(city_db_path)); - initializeProvider(formatted_config); + auto cb_added_opt = absl::make_optional(); + initializeProvider(formatted_config, cb_added_opt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -425,8 +437,9 @@ TEST_F(GeoipProviderTest, DbReloadError) { EXPECT_EQ("Boxford", city_it->second); TestEnvironment::renameFile(city_db_path, city_db_path + "1"); TestEnvironment::renameFile(reloaded_invalid_city_db_path, city_db_path); + cb_added_opt.value().waitReady(); { - absl::MutexLock guard(&mutex_); + absl::ReaderMutexLock guard(&mutex_); EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); } // On mmdb reload error the old mmdb instance should be used for subsequent lookup requests. @@ -455,7 +468,8 @@ TEST_F(GeoipProviderDeathTest, GeoDbPathDoesNotExist) { city: "x-geo-city" city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data_atc/GeoLite2-City-Test.mmdb" )EOF"; - EXPECT_DEATH(initializeProvider(config_yaml), ".*Unable to open Maxmind database file.*"); + EXPECT_DEATH(initializeProvider(config_yaml, cb_added_nullopt), + ".*Unable to open Maxmind database file.*"); } struct GeoipProviderGeoDbNotSetTestCase { @@ -474,7 +488,7 @@ class GeoipProviderGeoDbNotSetDeathTest TEST_P(GeoipProviderGeoDbNotSetDeathTest, GeoDbNotSetForConfiguredHeader) { GeoipProviderGeoDbNotSetTestCase test_case = GetParam(); - initializeProvider(test_case.yaml_config_); + initializeProvider(test_case.yaml_config_, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow("78.26.243.166"); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -551,7 +565,8 @@ class MmdbReloadImplTest : public ::testing::TestWithParam, TEST_P(MmdbReloadImplTest, MmdbReloaded) { MmdbReloadTestCase test_case = GetParam(); - initializeProvider(test_case.yaml_config_); + auto cb_added_opt = absl::make_optional(); + initializeProvider(test_case.yaml_config_, cb_added_opt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow(test_case.ip_); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -566,8 +581,9 @@ TEST_P(MmdbReloadImplTest, MmdbReloaded) { std::string reloaded_db_file_path = TestEnvironment::substitute(test_case.reloaded_db_file_path_); TestEnvironment::renameFile(source_db_file_path, source_db_file_path + "1"); TestEnvironment::renameFile(reloaded_db_file_path, source_db_file_path); + cb_added_opt.value().waitReady(); { - absl::MutexLock guard(&mutex_); + absl::ReaderMutexLock guard(&mutex_); EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); } expectReloadStats(test_case.db_type_, 1, 0); @@ -587,7 +603,8 @@ TEST_P(MmdbReloadImplTest, MmdbReloaded) { TEST_P(MmdbReloadImplTest, MmdbReloadedInFlightReadsNotAffected) { MmdbReloadTestCase test_case = GetParam(); - initializeProvider(test_case.yaml_config_); + auto cb_added_opt = absl::make_optional(); + initializeProvider(test_case.yaml_config_, cb_added_opt); GeoipProviderPeer::synchronizer(provider_).enable(); const auto lookup_sync_point_name = test_case.db_type_.append("_lookup_pre_complete"); // Start a thread that performs geoip lookup and wait in the worker thread right after reading the @@ -620,8 +637,9 @@ TEST_P(MmdbReloadImplTest, MmdbReloadedInFlightReadsNotAffected) { std::string reloaded_db_file_path = TestEnvironment::substitute(test_case.reloaded_db_file_path_); TestEnvironment::renameFile(source_db_file_path, source_db_file_path + "1"); TestEnvironment::renameFile(reloaded_db_file_path, source_db_file_path); + cb_added_opt.value().waitReady(); { - absl::MutexLock guard(&mutex_); + absl::ReaderMutexLock guard(&mutex_); EXPECT_TRUE(on_changed_cbs_[0](Filesystem::Watcher::Events::MovedTo).ok()); } GeoipProviderPeer::synchronizer(provider_).signal(lookup_sync_point_name); @@ -635,7 +653,7 @@ TEST_P(MmdbReloadImplTest, MmdbNotReloadedRuntimeFeatureDisabled) { TestScopedRuntime scoped_runtime_; scoped_runtime_.mergeValues({{"envoy.reloadable_features.mmdb_files_reload_enabled", "false"}}); MmdbReloadTestCase test_case = GetParam(); - initializeProvider(test_case.yaml_config_); + initializeProvider(test_case.yaml_config_, cb_added_nullopt); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddressNoThrow(test_case.ip_); Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; @@ -651,7 +669,7 @@ TEST_P(MmdbReloadImplTest, MmdbNotReloadedRuntimeFeatureDisabled) { TestEnvironment::renameFile(source_db_file_path, source_db_file_path + "1"); TestEnvironment::renameFile(reloaded_db_file_path, source_db_file_path); { - absl::MutexLock guard(&mutex_); + absl::ReaderMutexLock guard(&mutex_); EXPECT_EQ(0, on_changed_cbs_.size()); } expectReloadStats(test_case.db_type_, 0, 0);