@jnitin we did exactly this, see below for how we figured it out:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: extract-jwt-info
namespace: istio-config
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
proxy:
proxyVersion: ^1\.9.*
patch:
operation: INSERT_BEFORE
value:
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inlineCode: |
function envoy_on_request(request_handle)
-- getting jwt metadata
local meta = request_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.jwt_authn")
local claim_table = {}
-- setting ping and auth0 tokens and setting claim
claim_table["https://sso.xxxxxx.com/"] = "https://ql.custom.openid.com/client_name"
claim_table["https://api.xxxxx.xxxxx.xxxxx"] = "client_id"
claim_table["https://sso.xxxxx.xxxx.com/"] = "https://ql.custom.openid.com/client_name"
claim_table["https://sso.xxxxx.xxxxx.com/"] = "https://ql.custom.openid.com/client_name"
claim_table["https://api.xxxx.xxxxx-np.xx.xx"] = "client_id"
claim_table["https://api.xxxx.xxxx-np.xxx.xx"] = "client_id"
-- searching for metadata
for k, v in pairs(claim_table) do
if meta then
if meta[k] ~= nil then
local claims = meta[k]
local jwt_client_name_value = claims[v]
-- setting found jwt_client_name in dynamicmetadata to be consumed by metrics/logs
request_handle:streamInfo():dynamicMetadata():set("envoy.filters.http.lua", "jwt_client_name", jwt_client_name_value)
break
end
end
end
end
I then log it in envoy by adding this to the IstioOperator
object:
accessLogFormat: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% \"%UPSTREAM_TRANSPORT_FAILURE_REASON%\" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME% %DYNAMIC_METADATA(envoy.filters.http.lua:jwt_client_name)%\n"
Note the last field - “%DYNAMIC_METADATA(envoy.filters.http.lua:jwt_client_name)%”
Lastly, we even throw it on our istio_request_per_second metric so it logs in prometheus and we can track RPS per client id!
telemetry:
v2:
prometheus:
configOverride:
inboundSidecar:
debug: false
stat_prefix: istio
metrics:
- name: requests_total
dimensions:
jwt_client_name: string(metadata.filter_metadata["envoy.filters.http.lua"]["jwt_client_name"])