Searching online it seems that reading nested claims was implemented with Istio 1.8, I am using Istio 1.10.0.
Given the following kube yaml:
---
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: myapp-sso
namespace: mynamespace
spec:
selector:
matchLabels:
app.kubernetes.io/component: myapp
jwtRules:
- issuer: "REDACTED"
audiences: ["REDACTED"]
jwksUri: "https://login.microsoftonline.com/common/discovery/keys"
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authorize-myapp-poc-read
namespace: mynamespace
spec:
selector:
matchLabels:
app.kubernetes.io/component: myapp
action: ALLOW
rules:
- to:
- operation:
methods: ["GET"]
paths: ["*"]
when:
- key: request.auth.claims[roles]
values: ["env.read"]
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authorize-myapp-poc-write
namespace: mynamespace
spec:
selector:
matchLabels:
app.kubernetes.io/component: myapp
action: ALLOW
rules:
- to:
- operation:
methods: ["DELETE", "GET", "POST", "PUT", "PATCH"]
paths: ["*"]
when:
- key: request.auth.claims[roles]
values: ["env.write"]
A JWT token containing the following claim roles should give me read access or write access with “env.write”.
{
"aud": "REDACTED",
"iss": "REDACTED",
"iat": 1638376109,
"nbf": 1638376109,
"exp": 1638380009,
"aio": "UkVEQUNURUQK",
"appid": "REDACTED",
"appidacr": "1",
"idp": "REDACTED",
"oid": "REDACTED",
"rh": "REDACTED",
"roles": [
"env.read"
],
"sub": "REDACTED",
"tid": "REDACTED",
"uti": "REDACTED",
"ver": "1.0"
}
I get a 403 unauthorized when I submit a GET (or PUT etc for env.read).
I was able to configure my gateway’s logs to debug and what I am seeing looks to be what is expected.
2021-12-01T17:59:47.037031Z debug envoy http [C552] new stream
2021-12-01T17:59:47.037128Z debug envoy http [C552][S14242082210848494550] request headers complete (end_stream=false):
':authority', 'REDACTED'
':path', '/api/v1/namespaces'
':method', 'GET'
'authorization', 'Bearer REDACTED'
'content-type', 'application/json'
'user-agent', 'PostmanRuntime/7.28.4'
'accept', '*/*'
'cache-control', 'no-cache'
'postman-token', '9881325f-f852-454f-a8bd-281b3bc2bf0f'
'accept-encoding', 'gzip, deflate, br'
'connection', 'keep-alive'
'content-length', '93'
2021-12-01T17:59:47.037184Z debug envoy jwt Called Filter : setDecoderFilterCallbacks
2021-12-01T17:59:47.037245Z debug envoy jwt Called Filter : decodeHeaders
2021-12-01T17:59:47.037265Z debug envoy jwt Prefix requirement '/' matched.
2021-12-01T17:59:47.037274Z debug envoy jwt extract authorizationBearer
2021-12-01T17:59:47.037306Z debug envoy jwt origins-0: JWT authentication starts (allow_failed=false), tokens size=1
2021-12-01T17:59:47.037314Z debug envoy jwt origins-0: startVerify: tokens size 1
2021-12-01T17:59:47.037319Z debug envoy jwt origins-0: Parse Jwt REDACTED
2021-12-01T17:59:47.037472Z debug envoy jwt origins-0: Verifying JWT token of issuer REDACTED
2021-12-01T17:59:47.037552Z debug envoy jwt origins-0: JWT token verification completed with: OK
2021-12-01T17:59:47.037571Z debug envoy jwt Jwt authentication completed with: OK
2021-12-01T17:59:47.037601Z debug envoy filter AuthenticationFilter::decodeHeaders with config
policy {
origins {
jwt {
issuer: "REDACTED"
}
}
origin_is_optional: true
principal_binding: USE_ORIGIN
}
skip_validate_trust_domain: true
2021-12-01T17:59:47.037611Z debug envoy filter No method defined. Skip source authentication.
2021-12-01T17:59:47.037618Z debug envoy filter Validating request path /api/v1/namespaces for jwt issuer: "REDACTED"
2021-12-01T17:59:47.037705Z debug envoy filter ProcessJwtPayload: json object is {"aio":"REDACTED","appid":"REDACTED","appidacr":"1","aud":"REDACTED","exp":1638384262,"iat":1638380362,"idp":"REDACTED","iss":"REDACTED","nbf":1638380362,"oid":"REDACTED","rh":"REDACTED","roles":["env.read"],"sub":"REDACTED","tid":"REDACTED","uti":"REDACTED","ver":"1.0"}
2021-12-01T17:59:47.037730Z debug envoy filter JWT validation succeeded
2021-12-01T17:59:47.037745Z debug envoy filter Set principal from origin: REDACTED
2021-12-01T17:59:47.037748Z debug envoy filter Origin authenticator succeeded
2021-12-01T17:59:47.037852Z debug envoy filter Saved Dynamic Metadata:
fields {
key: "request.auth.audiences"
value {
string_value: "REDACTED"
}
}
fields {
key: "request.auth.claims"
value {
struct_value {
fields {
key: "aio"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "appid"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "appidacr"
value {
list_value {
values {
string_value: "1"
}
}
}
}
fields {
key: "aud"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "idp"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "iss"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "oid"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "rh"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "roles"
value {
list_value {
values {
string_value: "env.read"
}
}
}
}
fields {
key: "sub"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "tid"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "uti"
value {
list_value {
values {
string_value: "REDACTED"
}
}
}
}
fields {
key: "ver"
value {
list_value {
values {
string_value: "1.0"
}
}
}
}
}
}
}
fields {
key: "request.auth.principal"
value {
string_value: "REDACTED"
}
}
fields {
key: "request.auth.raw_claims"
value {
string_value: "{\"appidacr\":\"1\",\"ver\":\"1.0\",\"oid\":\"REDACTED\",\"sub\":\"REDACTED\",\"uti\":\"REDACTED\",\"exp\":1638384262,\"iat\":1638380362,\"tid\":\"REDACTED\",\"iss\":\"REDACTED\",\"aio\":\"REDACTED\",\"aud\":\"REDACTED\",\"nbf\":1638380362,\"appid\":\"REDACTED\",\"roles\":[\"env.read\"],\"idp\":\"REDACTED\",\"rh\":\"REDACTED\"}"
}
}
2021-12-01T17:59:47.037889Z debug envoy router [C552][S14242082210848494550] cluster 'outbound|443||mynamespace.myapp.svc.cluster.local' match for URL '/api/v1/namespaces'
2021-12-01T17:59:47.037952Z debug envoy router [C552][S14242082210848494550] router decoding headers:
':authority', 'REDACTED'
':path', '/api/v1/namespaces'
':method', 'GET'
':scheme', 'https'
'content-type', 'application/json'
'user-agent', 'PostmanRuntime/7.28.4'
'accept', '*/*'
'cache-control', 'no-cache'
'postman-token', '9881325f-f852-454f-a8bd-281b3bc2bf0f'
'accept-encoding', 'gzip, deflate, br'
'content-length', '93'
'x-forwarded-for', '10.11.229.35'
'x-forwarded-proto', 'https'
'x-envoy-internal', 'true'
'x-request-id', 'c1fe2233-f0d8-4317-82ee-ef2db4eb27ef'
'x-envoy-decorator-operation', 'mynamespace.myapp.svc.cluster.local:443/api/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGQoNSVNUSU9fVkVSU0lPThIIGgYxLjEwLjAK0gUKBkxBQkVMUxLHBSrEBQoXCgNhcHASEBoOaXN0aW8tb3BlcmF0b3IKKAobYXBwLmt1YmVybmV0ZXMuaW8vY29tcG9uZW50EgkaB2luZ3Jlc3MKJQobYXBwLmt1YmVybmV0ZXMuaW8vbWFuYWdlZEJ5EgYaBEhlbG0KMgoWYXBwLmt1YmVybmV0ZXMuaW8vbmFtZRIYGhZpc3Rpby1vcGVyYXRvci1pbmdyZXNzCi0KGWFwcC5rdWJlcm5ldGVzLmlvL3BhcnQtb2YSEBoOaXN0aW8tb3BlcmF0b3IKJQoZYXBwLmt1YmVybmV0ZXMuaW8vdmVyc2lvbhIIGgZ2MC4wLjIKEwoFY2hhcnQSChoIZ2F0ZXdheXMKHQoNaGVsbS5zaC9jaGFydBIMGgp1ZHAtYWRkb25zChQKCGhlcml0YWdlEggaBlRpbGxlcgo2CilpbnN0YWxsLm9wZXJhdG9yLmlzdGlvLmlvL293bmluZy1yZXNvdXJjZRIJGgd1bmtub3duCiIKBWlzdGlvEhkaF21ldGFkYXRhLWluZ3Jlc3NnYXRld2F5ChkKDGlzdGlvLmlvL3JldhIJGgdkZWZhdWx0CjAKG29wZXJhdG9yLmlzdGlvLmlvL2NvbXBvbmVudBIRGg9JbmdyZXNzR2F0ZXdheXMKIQoRcG9kLXRlbXBsYXRlLWhhc2gSDBoKNTU4N2Q5ODY1YwoSCgdyZWxlYXNlEgcaBWlzdGlvCjwKH3NlcnZpY2UuaXN0aW8uaW8vY2Fub25pY2FsLW5hbWUSGRoXbWV0YWRhdGEtaW5ncmVzc2dhdGV3YXkKLwojc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtcmV2aXNpb24SCBoGbGF0ZXN0ChEKA3NoYRIKGgg2MTRlYTkyYwoiChdzaWRlY2FyLmlzdGlvLmlvL2luamVjdBIHGgVmYWxzZQoaCgdNRVNIX0lEEg8aDWNsdXN0ZXIubG9jYWwKMgoETkFNRRIqGihtZXRhZGF0YS1pbmdyZXNzZ2F0ZXdheS01NTg3ZDk4NjVjLTZ3N3ZtChsKCU5BTUVTUEFDRRIOGgxpc3Rpby1zeXN0ZW0KYAoFT1dORVISVxpVa3ViZXJuZXRlczovL2FwaXMvYXBwcy92MS9uYW1lc3BhY2VzL2lzdGlvLXN5c3RlbS9kZXBsb3ltZW50cy9tZXRhZGF0YS1pbmdyZXNzZ2F0ZXdheQoXChFQTEFURk9STV9NRVRBREFUQRICKgAKKgoNV09SS0xPQURfTkFNRRIZGhdtZXRhZGF0YS1pbmdyZXNzZ2F0ZXdheQ=='
'x-envoy-peer-metadata-id', 'router~100.112.87.225~metadata-ingressgateway-5587d9865c-6w7vm.istio-system~istio-system.svc.cluster.local'
'x-envoy-attempt-count', '1'
'x-b3-traceid', '12ff4c3389a3ea240de1fc39e35f9a7a'
'x-b3-spanid', '0de1fc39e35f9a7a'
'x-b3-sampled', '0'
'x-envoy-original-path', '/api/v1/namespaces'
2021-12-01T17:59:47.037967Z debug envoy pool queueing stream due to no available connections
2021-12-01T17:59:47.037972Z debug envoy pool trying to create new connection
2021-12-01T17:59:47.037977Z debug envoy pool creating a new connection
2021-12-01T17:59:47.038046Z debug envoy client [C553] connecting
2021-12-01T17:59:47.038055Z debug envoy connection [C553] connecting to 100.112.23.29:5000
2021-12-01T17:59:47.038157Z debug envoy connection [C553] connection in progress
2021-12-01T17:59:47.038190Z debug envoy jwt Called Filter : decodeData
2021-12-01T17:59:47.038217Z debug envoy http [C552][S14242082210848494550] request end stream
2021-12-01T17:59:47.038225Z debug envoy jwt Called Filter : decodeData
2021-12-01T17:59:47.038786Z debug envoy connection [C553] connected
2021-12-01T17:59:47.039703Z debug envoy client [C553] connected
2021-12-01T17:59:47.039720Z debug envoy pool [C553] attaching to next stream
2021-12-01T17:59:47.039725Z debug envoy pool [C553] creating stream
2021-12-01T17:59:47.039734Z debug envoy router [C552][S14242082210848494550] pool ready
2021-12-01T17:59:47.040746Z debug envoy router [C552][S14242082210848494550] upstream headers complete: end_stream=false
2021-12-01T17:59:47.040796Z debug envoy http [C552][S14242082210848494550] encoding headers via codec (end_stream=false):
':status', '403'
'content-length', '19'
'content-type', 'text/plain'
'date', 'Wed, 01 Dec 2021 17:59:46 GMT'
'server', 'istio-envoy'
'x-envoy-upstream-service-time', '2'
2021-12-01T17:59:47.040813Z debug envoy client [C553] response complete
2021-12-01T17:59:47.040937Z debug envoy wasm wasm log stats_outbound stats_outbound: [extensions/stats/plugin.cc:621]::report() metricKey cache hit , stat=12
2021-12-01T17:59:47.040948Z debug envoy wasm wasm log stats_outbound stats_outbound: [extensions/stats/plugin.cc:621]::report() metricKey cache hit , stat=6
2021-12-01T17:59:47.040951Z debug envoy wasm wasm log stats_outbound stats_outbound: [extensions/stats/plugin.cc:621]::report() metricKey cache hit , stat=10
2021-12-01T17:59:47.040954Z debug envoy wasm wasm log stats_outbound stats_outbound: [extensions/stats/plugin.cc:621]::report() metricKey cache hit , stat=14
2021-12-01T17:59:47.040958Z debug envoy jwt Called Filter : onDestroy
2021-12-01T17:59:47.040961Z debug envoy filter Called AuthenticationFilter : onDestroy
2021-12-01T17:59:47.040966Z debug envoy pool [C553] response complete
2021-12-01T17:59:47.040969Z debug envoy pool [C553] saw upstream close connection
2021-12-01T17:59:47.040972Z debug envoy connection [C553] closing data_to_write=0 type=1
2021-12-01T17:59:47.040975Z debug envoy connection [C553] closing socket: 1
2021-12-01T17:59:47.041003Z debug envoy connection [C553] SSL shutdown: rc=0
2021-12-01T17:59:47.041038Z debug envoy client [C553] disconnect. resetting 0 pending requests
2021-12-01T17:59:47.041045Z debug envoy pool [C553] client disconnected, failure reason:
2021-12-01T17:59:47.041093Z debug envoy pool [C553] destroying stream: 0 remaining
Judging by all of the documentation that I have been able to find, my authz policies should be working.
My Kube cluster has 3rd party JWT enabled (I do not know if that is a contributing factor).
I am still relatively new to Istio so any help pointing me into the right direction would be most appreciated!