envoyproxy / envoyproxy/envoy

GCP Authentication Filter should be able to use the token endpoint to inject access token

Open
#28,866 7 comments 0 reactions 0 assignees View on GitHub
area/gcp_authn enhancement help wanted
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.