GCP Authentication Filter should be able to use the token endpoint to inject access token
- Dominant language
- C++
- Stars
- 28.9k
- Forks
- 5.6k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 430
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:
```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:
```bash
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`:
```yaml
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.
Contributor guide
Assessment
This issue has not been assessed yet.