GCP Authentication Filter should be able to use the token endpoint to inject access token
#28,866 opened on Aug 6, 2023
Repository metrics
- Stars
- (27,997 stars)
- PR merge metrics
- (Avg merge 8d) (378 merged PRs in 30d)
Description
Title: GCP Authentication Filter should be able to use the token endpoint to inject access token
Description:
The GCP Authentication filter injects the id_token (JWT) from http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity into the Authorization header of the request.
However, some Google services seem to expect the access_token from http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token instead. One example is the https://healthcare.googleapis.com APIs.
When the URI is changed to the token endpoint, the response from computeMetadata/v1/instance/service-accounts/default/token is JSON:
{"access_token":"ya29.c.redacted","expires_in":3400,"token_type":"Bearer"}
The GCP Authentication filter seems to inject the JSON response directly like so:
Authorization: Bearer {\"access_token\":\"ya29.c.redacted\",\"expires_in\":3400,\"token_type\":\"Bearer\"}
The correct access token can be retrieved using the following curl / jq commands:
curl \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
-H "Metadata-Flavor: Google" | jq -r '.access_token'
and the expected header is:
Authorization: ya29.c.redacted
Currently, I am getting over this by using a Lua filter in tandem with the GCP Authentication filter like so to strip the access_token:
http_filters:
- name: 'envoy.filters.http.gcp_authn'
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig
http_uri:
uri: 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token?audience=[AUDIENCE]'
cluster: 'gcp_authn'
timeout: 10s
# Lua filter to extract the access token from the GCP metadata server response
- name: envoy.filters.http.lua
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inline_code: |
function envoy_on_request(request_handle)
local auth_header = request_handle:headers():get("Authorization")
if auth_header then
local access_token = string.match(auth_header, '"access_token":"([^"]+)"')
if access_token then
request_handle:headers():replace("Authorization", "Bearer " .. access_token)
end
end
end
- name: envoy.filters.http.router
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
However, it'll be great to have this as a configuration option in the GCP Authentication Filter to automatically use the access_token / manipulate the response body using JSON path expressions to inject the right header.