Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/root/configuration/http/http_conn_man/headers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ should be replaced by backslash-double-quote (\").

The following keys are supported:

1. ``By`` The Subject Alternative Name (URI type) of the current proxy's certificate.
1. ``By`` The Subject Alternative Name (URI type) of the current proxy's certificate. The current proxy's certificate may contain multiple URI type Subject Alternative Names, each will be a separate key-value pair.
2. ``Hash`` The SHA 256 digest of the current client certificate.
3. ``Cert`` The entire client certificate in URL encoded PEM format.
4. ``Chain`` The entire client certificate chain (including the leaf certificate) in URL encoded PEM format.
5. ``Subject`` The Subject field of the current client certificate. The value is always double-quoted.
6. ``URI`` The URI type Subject Alternative Name field of the current client certificate.
6. ``URI`` The URI type Subject Alternative Name field of the current client certificate. A client certificate may contain multiple URI type Subject Alternative Names, each will be a separate key-value pair.
7. ``DNS`` The DNS type Subject Alternative Name field of the current client certificate. A client certificate may contain multiple DNS type Subject Alternative Names, each will be a separate key-value pair.

A client certificate may contain multiple Subject Alternative Name types. For details on different Subject Alternative Name types, please refer `RFC 2459`_.
Expand Down
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Minor Behavior Changes
* file: changed disk based files to truncate files which are not being appended to. This behavioral change can be temporarily reverted by setting runtime guard ``envoy.reloadable_features.append_or_truncate`` to false.
* grpc: flip runtime guard ``envoy.reloadable_features.enable_grpc_async_client_cache`` to be default enabled. async grpc client created through getOrCreateRawAsyncClient will be cached by default.
* health_checker: exposing ``initial_metadata`` to GrpcHealthCheck in a way similar to ``request_headers_to_add`` of HttpHealthCheck.
* http: added the ability to have multiple URI type Subject Alternative Names of the client certificate in the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` header.
* http: avoiding delay-close for HTTP/1.0 responses framed by connection: close as well as HTTP/1.1 if the request is fully read. This means for responses to such requests, the FIN will be sent immediately after the response. This behavior can be temporarily reverted by setting ``envoy.reloadable_features.skip_delay_close`` to false. If clients are are seen to be receiving sporadic partial responses and flipping this flag fixes it, please notify the project immediately.
* http: changed the http status code to 504 from 408 if the request timeouts after the request is completed. This behavior can be temporarily reverted by setting the runtime guard ``envoy.reloadable_features.override_request_timeout_by_gateway_timeout`` to false.
* http: lazy disable downstream connection reading in the HTTP/1 codec to reduce unnecessary system calls. This behavioral change can be temporarily reverted by setting runtime guard ``envoy.reloadable_features.http1_lazy_read_disable`` to false.
Expand Down
13 changes: 10 additions & 3 deletions source/common/http/conn_manager_utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,9 @@ void ConnectionManagerUtility::mutateXfccRequestHeader(RequestHeaderMap& request
config.forwardClientCert() == ForwardClientCertType::SanitizeSet) {
const auto uri_sans_local_cert = connection.ssl()->uriSanLocalCertificate();
if (!uri_sans_local_cert.empty()) {
client_cert_details.push_back(absl::StrCat("By=", uri_sans_local_cert[0]));
for (const std::string& uri : uri_sans_local_cert) {
client_cert_details.push_back(absl::StrCat("By=", uri));
}
}
const std::string cert_digest = connection.ssl()->sha256PeerCertificateDigest();
if (!cert_digest.empty()) {
Expand Down Expand Up @@ -418,8 +420,13 @@ void ConnectionManagerUtility::mutateXfccRequestHeader(RequestHeaderMap& request
case ClientCertDetailsType::URI: {
// The "URI" key still exists even if the URI is empty.
const auto sans = connection.ssl()->uriSanPeerCertificate();
const auto& uri_san = sans.empty() ? "" : sans[0];
client_cert_details.push_back(absl::StrCat("URI=", uri_san));
if (!sans.empty()) {
for (const std::string& uri : sans) {
client_cert_details.push_back(absl::StrCat("URI=", uri));
}
} else {
client_cert_details.push_back("URI=");
}
break;
}
case ClientCertDetailsType::DNS: {
Expand Down
53 changes: 29 additions & 24 deletions test/common/http/conn_manager_utility_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1026,15 +1026,16 @@ TEST_F(ConnectionManagerUtilityTest, MtlsForwardOnlyClientCert) {
headers.get_("x-forwarded-client-cert"));
}

// The server (local) identity is foo.com/be. The client does not set XFCC.
// The server (local) identity is test://foo.com/be and http://backend.foo.com. The client does not
// set XFCC.
TEST_F(ConnectionManagerUtilityTest, MtlsSetForwardClientCert) {
auto ssl = std::make_shared<NiceMock<Ssl::MockConnectionInfo>>();
ON_CALL(*ssl, peerCertificatePresented()).WillByDefault(Return(true));
const std::vector<std::string> local_uri_sans{"test://foo.com/be"};
const std::vector<std::string> local_uri_sans{"test://foo.com/be", "http://backend.foo.com"};
EXPECT_CALL(*ssl, uriSanLocalCertificate()).WillOnce(Return(local_uri_sans));
std::string expected_sha("abcdefg");
EXPECT_CALL(*ssl, sha256PeerCertificateDigest()).WillOnce(ReturnRef(expected_sha));
const std::vector<std::string> peer_uri_sans{"test://foo.com/fe"};
const std::vector<std::string> peer_uri_sans{"test://foo.com/fe", "http://frontend.foo.com"};
EXPECT_CALL(*ssl, uriSanPeerCertificate()).WillRepeatedly(Return(peer_uri_sans));
std::string expected_pem("%3D%3Dabc%0Ade%3D");
EXPECT_CALL(*ssl, urlEncodedPemEncodedPeerCertificate()).WillOnce(ReturnRef(expected_pem));
Expand All @@ -1057,27 +1058,27 @@ TEST_F(ConnectionManagerUtilityTest, MtlsSetForwardClientCert) {
EXPECT_EQ((MutateRequestRet{"10.0.0.3:50000", false, Tracing::Reason::NotTraceable}),
callMutateRequestHeaders(headers, Protocol::Http2));
EXPECT_TRUE(headers.has("x-forwarded-client-cert"));
EXPECT_EQ("By=test://foo.com/be;"
EXPECT_EQ("By=test://foo.com/be;By=http://backend.foo.com;"
"Hash=abcdefg;"
"URI=test://foo.com/fe;"
"URI=test://foo.com/fe;URI=http://frontend.foo.com;"
"Cert=\"%3D%3Dabc%0Ade%3D\";"
"Chain=\"%3D%3Dabc%0Ade%3D%3D%3Dlmn%0Aop%3D\";"
"DNS=www.example.com",
headers.get_("x-forwarded-client-cert"));
}

// This test assumes the following scenario:
// The client identity is foo.com/fe, and the server (local) identity is foo.com/be. The client
// also sends the XFCC header with the authentication result of the previous hop, (bar.com/be
// calling foo.com/fe).
// The client identity is test://foo.com/fe and http://frontend.foo.com,
// and the server (local) identity is test://foo.com/be and http://backend.frontend.com.
// The client also sends the XFCC header with the authentication result of the previous hop.
TEST_F(ConnectionManagerUtilityTest, MtlsAppendForwardClientCert) {
auto ssl = std::make_shared<NiceMock<Ssl::MockConnectionInfo>>();
ON_CALL(*ssl, peerCertificatePresented()).WillByDefault(Return(true));
const std::vector<std::string> local_uri_sans{"test://foo.com/be"};
const std::vector<std::string> local_uri_sans{"test://foo.com/be", "http://backend.foo.com"};
EXPECT_CALL(*ssl, uriSanLocalCertificate()).WillOnce(Return(local_uri_sans));
std::string expected_sha("abcdefg");
EXPECT_CALL(*ssl, sha256PeerCertificateDigest()).WillOnce(ReturnRef(expected_sha));
const std::vector<std::string> peer_uri_sans{"test://foo.com/fe"};
const std::vector<std::string> peer_uri_sans{"test://foo.com/fe", "http://frontend.foo.com"};
EXPECT_CALL(*ssl, uriSanPeerCertificate()).WillRepeatedly(Return(peer_uri_sans));
std::string expected_pem("%3D%3Dabc%0Ade%3D");
EXPECT_CALL(*ssl, urlEncodedPemEncodedPeerCertificate()).WillOnce(ReturnRef(expected_pem));
Expand All @@ -1095,16 +1096,19 @@ TEST_F(ConnectionManagerUtilityTest, MtlsAppendForwardClientCert) {
details.push_back(Http::ClientCertDetailsType::Chain);
details.push_back(Http::ClientCertDetailsType::DNS);
ON_CALL(config_, setCurrentClientCertDetails()).WillByDefault(ReturnRef(details));
TestRequestHeaderMapImpl headers{{"x-forwarded-client-cert", "By=test://foo.com/fe;"
"URI=test://bar.com/be;"
"DNS=test.com;DNS=test.com"}};
TestRequestHeaderMapImpl headers{{"x-forwarded-client-cert",
"By=test://foo.com/fe;By=http://frontend.foo.com;"
"URI=test://bar.com/be;"
"DNS=test.com;DNS=test.com"}};

EXPECT_EQ((MutateRequestRet{"10.0.0.3:50000", false, Tracing::Reason::NotTraceable}),
callMutateRequestHeaders(headers, Protocol::Http2));
EXPECT_TRUE(headers.has("x-forwarded-client-cert"));
EXPECT_EQ(
"By=test://foo.com/fe;URI=test://bar.com/be;DNS=test.com;DNS=test.com,"
"By=test://foo.com/be;Hash=abcdefg;URI=test://foo.com/fe;"
"By=test://foo.com/fe;By=http://frontend.foo.com;URI=test://bar.com/"
"be;DNS=test.com;DNS=test.com,"
"By=test://foo.com/be;By=http://backend.foo.com;Hash=abcdefg;URI=test://foo.com/fe;URI=http:/"
"/frontend.foo.com;"
"Cert=\"%3D%3Dabc%0Ade%3D\";Chain=\"%3D%3Dabc%0Ade%3D%3D%3Dlmn%0Aop%3D\";DNS=www.example.com",
headers.get_("x-forwarded-client-cert"));
}
Expand Down Expand Up @@ -1139,19 +1143,19 @@ TEST_F(ConnectionManagerUtilityTest, MtlsAppendForwardClientCertLocalSanEmpty) {
}

// This test assumes the following scenario:
// The client identity is foo.com/fe, and the server (local) identity is foo.com/be. The client
// also sends the XFCC header with the authentication result of the previous hop, (bar.com/be
// calling foo.com/fe).
// The client identity is test://foo.com/fe and http://frontend.foo.com, and the server
// (local) identity is test://foo.com/be and http://backend.foo.com. The client
// also sends the XFCC header with the authentication result of the previous hop.
TEST_F(ConnectionManagerUtilityTest, MtlsSanitizeSetClientCert) {
auto ssl = std::make_shared<NiceMock<Ssl::MockConnectionInfo>>();
ON_CALL(*ssl, peerCertificatePresented()).WillByDefault(Return(true));
const std::vector<std::string> local_uri_sans{"test://foo.com/be"};
const std::vector<std::string> local_uri_sans{"test://foo.com/be", "http://backend.foo.com"};
EXPECT_CALL(*ssl, uriSanLocalCertificate()).WillOnce(Return(local_uri_sans));
std::string expected_sha("abcdefg");
EXPECT_CALL(*ssl, sha256PeerCertificateDigest()).WillOnce(ReturnRef(expected_sha));
std::string peer_subject("/C=US/ST=CA/L=San Francisco/OU=Lyft/CN=test.lyft.com");
EXPECT_CALL(*ssl, subjectPeerCertificate()).WillOnce(ReturnRef(peer_subject));
const std::vector<std::string> peer_uri_sans{"test://foo.com/fe"};
const std::vector<std::string> peer_uri_sans{"test://foo.com/fe", "http://frontend.foo.com"};
EXPECT_CALL(*ssl, uriSanPeerCertificate()).WillRepeatedly(Return(peer_uri_sans));
std::string expected_pem("abcde=");
EXPECT_CALL(*ssl, urlEncodedPemEncodedPeerCertificate()).WillOnce(ReturnRef(expected_pem));
Expand All @@ -1173,10 +1177,11 @@ TEST_F(ConnectionManagerUtilityTest, MtlsSanitizeSetClientCert) {
EXPECT_EQ((MutateRequestRet{"10.0.0.3:50000", false, Tracing::Reason::NotTraceable}),
callMutateRequestHeaders(headers, Protocol::Http2));
EXPECT_TRUE(headers.has("x-forwarded-client-cert"));
EXPECT_EQ("By=test://foo.com/be;Hash=abcdefg;Subject=\"/C=US/ST=CA/L=San "
"Francisco/OU=Lyft/CN=test.lyft.com\";URI=test://foo.com/"
"fe;Cert=\"abcde=\";Chain=\"abcde=lmnop=\"",
headers.get_("x-forwarded-client-cert"));
EXPECT_EQ(
"By=test://foo.com/be;By=http://backend.foo.com;Hash=abcdefg;Subject=\"/C=US/ST=CA/L=San "
"Francisco/OU=Lyft/CN=test.lyft.com\";URI=test://foo.com/fe;URI=http://frontend.foo.com;"
"Cert=\"abcde=\";Chain=\"abcde=lmnop=\"",
headers.get_("x-forwarded-client-cert"));
}

// This test assumes the following scenario:
Expand Down
34 changes: 17 additions & 17 deletions test/config/integration/certs/cacert.pem
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
6 changes: 6 additions & 0 deletions test/config/integration/certs/cacert_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// NOLINT(namespace-envoy)
constexpr char TEST_CA_CERT_256_HASH[] =
"c3e7f584b399f0f11e65268a24b2ab536ba6a9f7d722150d0e10afa70a470ad4";
constexpr char TEST_CA_CERT_1_HASH[] = "5df2ca889db6287a61ebc9464d6f474fa50d37aa";
constexpr char TEST_CA_CERT_SPKI[] = "VYTUpj60bicmU8PDzK7BzeGY5Zx2x+0bs0V5tFpRk+Y=";
constexpr char TEST_CA_CERT_SERIAL[] = "190c1c9f7cff909627e6a766d2747edf03724801";
50 changes: 25 additions & 25 deletions test/config/integration/certs/cakey.pem
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
Loading