How to set up Istio RBAC based on groups from JWT claims? - istio

I have a service with AuthenticationPolicy and Istio RBAC enabled (authorization context is set to use groups from JWT claim) However, it seems istio does not take into account the groups attribute from JWT claim when a call is being made.
As an IDP I use dex and I have set corresponding AuthnPolicy for it.
I have set Authorization context as following :
apiVersion: "config.istio.io/v1alpha2"
kind: authorization
metadata:
name: requestcontext
namespace: istio-system
spec:
subject:
user: source.user | request.auth.claims["email"] | ""
groups: request.auth.claims["groups"] | ""
properties:
namespace: source.namespace | ""
service: source.service | ""
iss: request.auth.claims["iss"] | ""
sub: request.auth.claims["sub"] | ""
action:
namespace: destination.namespace | ""
service: destination.service | ""
method: request.method | ""
path: request.path | ""
properties:
version: request.headers["version"] | ""
I have enabled RBAC and created ServiceRole. I've added ServiceRoleBinding with subject set to a specific group called "admins" :
apiVersion: "config.istio.io/v1alpha2"
kind: ServiceRoleBinding
metadata:
name: service-admin-binding
spec:
subjects:
- group: "admins"
roleRef:
kind: ServiceRole
name: "service-admin"
When a call is made without a token AuthnPolicy works, 401 with proper message is returned. Call with valid JWT results in 403 permission denied as the group was not matched. It works fine when I change subject to "all" users instead of a group( - user: "*")
Groups claim in fetched JWT after decoding is just an array of strings :
"groups": [
"admins"
]
If I add in the authorization context a first non empty operator with hardcoded value "admins" - groups: request.auth.claims["groups"] | "admins") it works ofc, but indicates groups are empty on mixer adapter resolving phase?
If I set in the authorization context groups to be taken from request.auth.token["groups"] like it's mentioned in the docu
mixer fails with an error :
(...)'requestcontext.authorization.istio-system': failed to evaluate expression for field 'Subject'; failed to evaluate expression for field 'Subject.Groups': unknown attribute request.auth.token'.
When I took a look at attribute vocabulary docu it does not mention token attribute on request.auth and I could find it in the code neither. However, there is request.auth.claims which I'm trying to use.
How can I setup authentication policy together with RBAC to let it be working with groups from JWT? Additionally, is it possible to log/debug mixer while resolving the authorization phase, to see what's exactly evaluated?

Answered by Piotr Mścichowski in comments:
I got a response on google groups mentioning that groups as an array of strings are not supported yet as well as groups in the subject of role binding (could be workaround by properties):
Yangmin Zhu
We're currently working adding more documents in Istio 1.0, if you're
using the most recent daily release, you could try it with the
following steps:
1) We introduced a new global custom resource to control the RBAC
behavior in the mesh: RbacConfig. You could apply one like
this to enable RBAC for the "default" namespace,
2) We made some changes to the ServiceRole.Constraints and
ServiceRoleBinding.Properties about what keys are supported. See
this PR for an overview of the supported keys. Regarding your
ServiceRoleBinding, you could use the following config to check
against the claim from the JWT (Note: the group field is not used and
not supported, instead you could specify it in properties):
apiVersion: "config.istio.io/v1alpha2"
kind: ServiceRoleBinding
metadata:
name: service-admin-binding
spec:
subjects:
- properties:
request.auth.claims[groups]: "admins"
roleRef:
kind: ServiceRole
name: "service-admin"
I think you don't need special setting to make the authentication
policy work with RBAC, if you could successfully finish this
task, it should work with RBAC automatically.
You could turn on the debug logging of the envoy proxy of your
service. For rbac, there is a specific logging group named "rbac" in
envoy, you could access the enovy admin page locally (by default it's
http://127.0.0.1:15000/logging).
Limin Wang:
We currently haven't supported JWT claims that are non-strings. If your JWT group claim is set to a single string
(instead of an array), it will just work.
"group": "admin"
Also "group" under "subject" is not supported at the moment. But as
Yangmin suggested, you can use custom "properties" instead.
subjects:
- properties:
request.auth.claims[groups]: "admins"
Thanks for bring this issue to our attention, we plan to make
improvement to support such use case in future releases.

Related

Traefik Apply Middleware On Domain Names

There's a need to apply a request body size limit to certain domain names via Traefik.
The Traefik middleware is:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: request-limits
spec:
buffering:
maxRequestBodyBytes: 10485760
retryExpression: "IsNetworkError() && Attempts() < 2"
And this can be applied globally via:
additionalArguments:
- --entrypoints.websecure.http.middlewares=traefik-request-limits#kubernetescrd
How can this middleware be applied to certain domain names?
What I've tried - remove the above additionalArguments, and replace it with:
http:
routers:
http-specific:
rule: "HostRegexp(`{name:(.*-)(service|mock|proxy)\\.(.*)\\.(example\\.com}`)"
entrypoints:
- websecure
middlewares:
- request-limits
service:
- noop#internal
However - the above route is not getting created.
Any tips or pointers would be much appreciated.
Traefik Feature Status
List item
https://github.com/traefik/traefik/issues/5098

Cloud API Gateway doesn't allow with CORS

I have Cloud Gateway API that connect to Cloud Function.
It worked great with an API key that I generated, but then when I restricted the key to enable access for my specific domain only - example.com, I started to get CORS errors on the client. ( it did worked without domain restriction)
So I enabled CORS in the config file in the Console, the file had no errors, but I still get a CORS error when accessing the API URL from my domain with the key:
https://project-xxxx.uc.gateway.dev/search?key=AIxxxxxxxxx
Config :
swagger: "2.0"
info:
title: projectapi
description: "data api"
version: "1.0.0"
schemes:
- "https"
host: "project-xxxxxxxx.apigateway.xxxxx-xxxxx.cloud.goog"
x-google-endpoints:
- name: "project-xxxxxxxx.apigateway.xxxxx-xxxxx.cloud.goog"
allowCors: True
paths:
"/search":
get:
description: "data"
operationId: "project"
x-google-backend:
address: https://us-central1-projectName.cloudfunctions.net/search
security:
- api_key: [key]
responses:
200:
description: "Success."
schema:
type: string
400:
description: "Invalid"
securityDefinitions:
api_key:
type: "apiKey"
name: "key"
in: "query"
My Cloud Function do allow CORS, and works great if called directly with the link here in the address key.
Why this config wont allow cors for the Gateway ?
Solved !
You must enable the key not only for your domain name, but also for your specific API name from the list, go to APIs & Services => Credentials => API keys => your key => API restrictions => choose your API name from the list !
This allow access to a Function from a specific domain - without using a Balancer.

AWS eks user gets error: You must be logged in to the server (Unauthorized)

I have now spent 2 hours and a half trying to fix an issue which is driving me crazy. I have created an EKS cluster. Then I have created 2 users in AWS IAM with an eks_admin role. Once done, I updated the aws-auth configmap to add the 2 users. The issue is that it works for a user but not for the second one !!
I have dug in aws doc, on stackoverflow .... Some say that it's not sufficient to create the configmap one has also to create a clusterrolebing for the newly created users. The issue is that I did not create the binding for the first user and it works. I have tried to create it for the second one and no luck. when I issue an aws eks get-token I get one.
Can anyone try to point me in the right direction ? I'm on the edge of losing my nerves ....
Here's the configmap I have :
Name: aws-auth
Namespace: kube-system
Labels: <none>
Annotations: <none>
Data
====
mapRoles:
----
- rolearn: arn:aws:iam::xxxxxxxxxxxxx:role/k8s-nodegroup-NodeInstanceRole-xxxxxxxxxxxxx
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
mapUsers:
----
- rolearn: arn:aws:iam::xxxxxxxxxx:user/yyyyyy
username: yyyyyy
groups:
-system:masters
- rolearn: arn:aws:iam::xxxxxxxxxxxx:user/zzzzz
username: zzzzzz
groups:
-system:masters
Events: <none
I have this in the controlplane authenticator logs :
time="2020-12-23T10:46:15Z" level=warning msg="access denied"
arn="arn:aws:iam::xxxxxxxxxx:user/yyyyy" client="127.0.0.1:37622"
error="ARN is not mapped: arn:aws:iam::xxxxxxxxxxxx:user/yyyyyyy"
method=POST path=/authenticate sts=sts.amazonaws.com
I don't get since it's mapped as stated in the configmap file.
Issues are finally fixed. I have modified the configmap to use userarn instead of rolearn, which is the way it should always be done, and then I had to create the clusterrolebinding for both users.
What I still don't get is why/how it has previously worked for the first user who has rolearn and no clusterrolebinding ....

Google cloud API Gateway with authentication yaml config file deployment error

I am new in API Gateway and trying to enable security on my API. I follow some instruction which I found on the internet like this:
https://medium.com/swlh/manage-serverless-apis-with-api-gateway-in-gcp-b7f906efec1a
Here is my YAML file:
# openapi2-functions.yaml
swagger: '2.0'
info:
title: simple-test
description: Sample API on API Gateway with a Google Cloud Functions backend
version: 1.0.0
schemes:
- https
produces:
- application/json
paths:
/direcciones:
get:
summary: get direcciones
operationId: direcciones
x-google-backend:
address: http://publicIP/api/v1/app/catalogos/direcciones
security:
- api_key: []
responses:
'200':
description: A successful response
schema:
type: string
securityDefinitions:
api_key:
type: "apiKey"
name: "key"
in: "query"
While deploying this config file in API gateway config, I am getting the following error:
INVALID_ARGUMENT Cannot convert to service config. 'location: "evva.yaml: x-google-backend" kind: ERROR message: "Extension x-google-backend cannot be converted into proto type google.api.BackendRule. Details: Cannot find field: security in message google.api.BackendRule" location: "evva.yaml: x-google-backend" message: "Address field in extension x-google-backend is empty. In this case, the backend address must be provided to the proxy via a runtime flag." location: "evva.yaml: Operation \'get\' in path \'/direcciones\'" message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : \'apiKey\'." ' com.google.apps.framework.request.BadRequestException: Cannot convert to service config. 'location: "evva.yaml: x-google-backend" kind: ERROR message: "Extension x-google-backend cannot be converted into proto type google.api.BackendRule. Details: Cannot find field: security in message google.api.BackendRule" location: "evva.yaml: x-google-backend" message: "Address field in extension x-google-backend is empty. In this case, the backend address must be provided to the proxy via a runtime flag." location: "evva.yaml: Operation \'get\' in path \'/direcciones\'" message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : \'apiKey\'." '
I don't understand this error what change should i need to do in YAML file to make it acceptable while deploying.
The security entry mustn't be "in" the x-google-backend, but bellow the get:. Like this.
paths:
/direcciones:
get:
summary: get direcciones
operationId: direcciones
x-google-backend:
address: http://publicIP/api/v1/app/catalogos/direcciones
security:
- api_key: []

Unable to access Cloud Endpoints on GCP Endpoints Portal

I created the API using GKE and Cloud Endpoint gRPC everything is fine but when I try to access my API from Endpoints Portal this is not working.
EndPoint Portal For API
Enter any id in ayah_id and try to execute you will see error.
ENOTFOUND: Error resolving domain "https://quran.endpoints.utopian-button-227405.cloud.goog"
I don't know why this is not working even my API is running successfully on http://34.71.56.199/v1/image/ayah/ayah-1 I'm using Http Transcoding actual gRPC running on 34.71.56.199:81
I think I missed some configuration steps. Can someone please let me know what I miss.
Update
api_config.yaml
# The configuration schema is defined by service.proto file
# https://github.com/googleapis/googleapis/blob/master/google/api/service.proto
type: google.api.Service
config_version: 3
name: quran.endpoints.utopian-button-227405.cloud.goog
usage:
rules:
# Allow unregistered calls for all methods.
- selector: "*"
allow_unregistered_calls: true
#
# API title to appear in the user interface (Google Cloud Console).
#
title: Quran gRPC API
apis:
- name: quran.Audio
- name: quran.Ayah
- name: quran.Edition
- name: quran.Image
- name: quran.Surah
- name: quran.Translation
Update 2
api_config.yaml
# The configuration schema is defined by service.proto file
# https://github.com/googleapis/googleapis/blob/master/google/api/service.proto
type: google.api.Service
config_version: 3
name: quran.endpoints.utopian-button-227405.cloud.goog
endpoints:
- name: quran.endpoints.utopian-button-227405.cloud.goog
target: "34.71.56.199"
usage:
rules:
# Allow unregistered calls for all methods.
- selector: "*"
allow_unregistered_calls: true
#
# API title to appear in the user interface (Google Cloud Console).
#
title: Quran gRPC API
apis:
- name: quran.Audio
- name: quran.Ayah
- name: quran.Edition
- name: quran.Image
- name: quran.Surah
- name: quran.Translation
api_config_http.yaml
# The configuration schema is defined by service.proto file
# https://github.com/googleapis/googleapis/blob/master/google/api/service.proto
type: google.api.Service
config_version: 3
name: quran.endpoints.utopian-button-227405.cloud.goog
#
# Http Transcoding.
#
# HTTP rules define translation from HTTP/REST/JSON to gRPC. With these rules
# HTTP/REST/JSON clients will be able to call the Quran service.
#
http:
rules:
#
# Image Service transcoding
#
- selector: quran.Image.CreateImage
post: '/v1/image'
body: '*'
- selector: quran.Image.FindImageByAyahId
get: '/v1/image/ayah/{id}'