diff --git a/source/extensions/filters/http/gcp_authn/gcp_authn_client_impl.cc b/source/extensions/filters/http/gcp_authn/gcp_authn_client_impl.cc index 0acd70a138475..cb2d3d1294d7d 100644 --- a/source/extensions/filters/http/gcp_authn/gcp_authn_client_impl.cc +++ b/source/extensions/filters/http/gcp_authn/gcp_authn_client_impl.cc @@ -24,7 +24,7 @@ constexpr absl::string_view TokenUrlPath = "token"; constexpr absl::string_view AudienceQueryKey = "audience"; constexpr char MetadataFlavorKey[] = "Metadata-Flavor"; constexpr char MetadataFlavor[] = "Google"; -constexpr char ClientCertificateSha256Key[] = "client_certificate_sha256"; +constexpr char BindCertificateFingerprintKey[] = "bindCertificateFingerprint"; Http::RequestMessagePtr buildRequest(absl::string_view url) { absl::string_view host; @@ -100,7 +100,10 @@ void GcpAuthnClientImpl::fetchBoundJwt( const std::string& fingerprint, GcpAuthnClient::Callbacks& callbacks) { Http::Utility::QueryParamsMulti query_params; query_params.add(AudienceQueryKey, audience.bound_jwt().url()); - query_params.add(ClientCertificateSha256Key, fingerprint); + // N.B.: double-URL-encoding is REQUIRED by the GCP metadata server. + query_params.add(BindCertificateFingerprintKey, + Http::Utility::PercentEncoding::urlEncode( + Http::Utility::PercentEncoding::urlEncode(fingerprint))); const std::string final_url = absl::StrCat(DefaultServiceAccountPrefix, IdentityUrlPath, query_params.toString()); makeTokenRequest(TokenType::BoundJwt, audience, final_url, fingerprint, callbacks); @@ -110,7 +113,10 @@ void GcpAuthnClientImpl::fetchBoundAccessToken( const envoy::extensions::filters::http::gcp_authn::v3::Audience& audience, const std::string& fingerprint, GcpAuthnClient::Callbacks& callbacks) { Http::Utility::QueryParamsMulti query_params; - query_params.add(ClientCertificateSha256Key, fingerprint); + // N.B.: double-URL-encoding is REQUIRED by the GCP metadata server. + query_params.add(BindCertificateFingerprintKey, + Http::Utility::PercentEncoding::urlEncode( + Http::Utility::PercentEncoding::urlEncode(fingerprint))); const std::string final_url = absl::StrCat(DefaultServiceAccountPrefix, TokenUrlPath, query_params.toString()); makeTokenRequest(TokenType::BoundAccessToken, audience, final_url, fingerprint, callbacks); diff --git a/test/extensions/filters/http/gcp_authn/gcp_authn_client_impl_test.cc b/test/extensions/filters/http/gcp_authn/gcp_authn_client_impl_test.cc index 8cca1d0d799c4..5b9052a97b9ff 100644 --- a/test/extensions/filters/http/gcp_authn/gcp_authn_client_impl_test.cc +++ b/test/extensions/filters/http/gcp_authn/gcp_authn_client_impl_test.cc @@ -450,12 +450,12 @@ TEST_F(GcpAuthnClientImplTest, SuccessBoundJwt) { envoy::extensions::filters::http::gcp_authn::v3::Audience audience; audience.mutable_bound_jwt()->set_url("http://test_audience"); - const std::string fingerprint = "test_fingerprint_value"; + const std::string fingerprint = "abc+def/ghi="; client_->fetchBoundJwt(audience, fingerprint, request_callbacks_); EXPECT_EQ(message_->headers().Method()->value().getStringView(), "GET"); EXPECT_EQ(message_->headers().Path()->value().getStringView(), "/computeMetadata/v1/instance/service-accounts/default/identity?audience=http://" - "test_audience&client_certificate_sha256=test_fingerprint_value"); + "test_audience&bindCertificateFingerprint=abc%252Bdef%252Fghi%253D"); EXPECT_EQ(options_.retry_policy->num_retries().value(), 5); @@ -477,12 +477,12 @@ TEST_F(GcpAuthnClientImplTest, SuccessBoundAccessToken) { envoy::extensions::filters::http::gcp_authn::v3::Audience audience; audience.mutable_bound_access_token(); - const std::string fingerprint = "test_fingerprint_value"; + const std::string fingerprint = "abc+def/ghi="; client_->fetchBoundAccessToken(audience, fingerprint, request_callbacks_); EXPECT_EQ(message_->headers().Method()->value().getStringView(), "GET"); EXPECT_EQ(message_->headers().Path()->value().getStringView(), "/computeMetadata/v1/instance/service-accounts/default/" - "token?client_certificate_sha256=test_fingerprint_value"); + "token?bindCertificateFingerprint=abc%252Bdef%252Fghi%253D"); EXPECT_EQ(options_.retry_policy->num_retries().value(), 5); diff --git a/test/extensions/filters/http/gcp_authn/gcp_authn_filter_integration_test.cc b/test/extensions/filters/http/gcp_authn/gcp_authn_filter_integration_test.cc index 82eed53c671cc..c860575c1023f 100644 --- a/test/extensions/filters/http/gcp_authn/gcp_authn_filter_integration_test.cc +++ b/test/extensions/filters/http/gcp_authn/gcp_authn_filter_integration_test.cc @@ -3,6 +3,7 @@ #include "envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.pb.h" #include "envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.pb.validate.h" +#include "source/common/http/utility.h" #include "source/extensions/filters/http/gcp_authn/gcp_authn_filter.h" #include "test/integration/http_integration.h" @@ -169,7 +170,9 @@ class GcpAuthnFilterIntegrationTest : public testing::TestWithParam>(); auto client_context_config = std::make_unique>(); @@ -349,7 +349,7 @@ TEST_F(GcpAuthnFilterTest, ResumeFilterChainIterationWithBoundAccessToken) { EXPECT_EQ(message_->headers().Method()->value().getStringView(), "GET"); EXPECT_EQ(message_->headers().Path()->value().getStringView(), "/computeMetadata/v1/instance/service-accounts/default/" - "token?client_certificate_sha256=mock_fingerprint_base64"); + "token?bindCertificateFingerprint=mock%252Bfingerprint%252Fbase64%253D"); Envoy::Http::ResponseHeaderMapPtr resp_headers(new Envoy::Http::TestResponseHeaderMapImpl({ {":status", "200"},