RBAC Not working while trying to allow only from a namespace

#1

Hi,
Istio version: 1.1.4
I am trying to test RBAC so that a service only is accessible from default namespace.
I have enabled RBAC and I get RBAC: Access Denied. I use the following ServiceRole and Rolebining:

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: testapp
  namespace: test-ns
spec:
  rules:
  - services: ["testapp.testns.svc.cluster.local"]
    methods: ["GET", "POST"]
---
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: testapp
  namespace: test-ns
spec:
  subjects:
  - properties:
      source.namespace: "default"
  roleRef:
    kind: ServiceRole
    name: "testapp"

If change the rolebinding subject to user * like below. I am able to access the service but from all the namespaces

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: testapp
  namespace: test-ns
spec:
  rules:
  - services: ["testapp.testns.svc.cluster.local"]
    methods: ["GET", "POST"]
---
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: testapp
  namespace: test-ns
spec:
  subjects:
  - user: "*"
  - properties:
      source.namespace: "default"
  roleRef:
    kind: ServiceRole
    name: "testapp"

I am looking to limit the testapp service only to "default namespace.

I referred the debugging authorization but could not find anything https://istio.io/help/ops/security/debugging-authorization/?_ga=2.157940531.865830535.1556444206-1951758752.1556086040

testapp-svc:

apiVersion: v1
kind: Service
metadata:
  name: testapp
  labels:
    app: testapp
    service: testapp
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: testapp
#2

The testapp ServiceRoleBinding allows both user: "*" and "source.namespace: "default" to access the ServiceRole, they are ORed together, that’s why you can access the service from all namespaces.

One thing to check is to make sure you have enabled the mTLS which is required if you want to use the namespace property.

#3

To add to what Yangmin has already said, if you want to limit access only default namespace, then you can remove user: "*" (and make sure mTLS is enabled). In the future, if you want to AND two fields within a Subject, you can specify them within one Subject (the - in user and properties in your ServiceRoleBinding indicates that there are two subjects.)

#4

Thanks @YangminZhu and @philliple . It was not working if i use just namespace properties alone.
However I have not mTLS enabled globally. Let me try enabling mTLS for this namespace.

#5

I have enabled Mutual TLS for this namespace and created Destination rule:

kind: "Policy"
metadata:
  name: "default"
  namespace: "test-ns"
spec:
  peers:
  - mtls: {}
---
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "default"
  namespace: "test-ns"
spec:
  host: "*.test-ns.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

Now when I access from the namespace other than default:

curl testapp.test-ns.svc.cluster.local
upstream connect error or disconnect/reset before headers

So I guess the white listing is working and it allows only traffic from default namespace.
However when I access the service from default namespace:

curl testapp.test-ns.cluster.local
curl: (56) Recv failure: Connection reset by peer

How can i access a service with mTLS enabled using curl.
@YangminZhu @philliple can you please help me on this?

#6

The error upstream connect error or disconnect/reset before headers usually indicates there is something wrong in your mTLS setting, which means the request is rejected in authentication layer, the authorization layer doesn’t even get the chance to see the request.

Note your DestinationRule is in the test-ns namespace, could you try to copy it also to the default namespace? Keep in mind, the DestinationRule take effect on the client side, so if you’re sending request from default namespace, you should have one in the default namespace.

#7

Now I have mTLS enabled. Service working with mTLS on permissive mode.
mTLS set using:

apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "default"
  namespace: "test-ns"
spec:
  peers:
  - mtls: {}
---
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "default"
  namespace: "test-ns"
spec:
  host: "*.test-ns.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

RBAC enabled with:

apiVersion: "rbac.istio.io/v1alpha1"
kind: ClusterRbacConfig
metadata:
  name: default
spec:
  mode: 'ON_WITH_INCLUSION'
  inclusion:
    namespaces: ["test-ns"]

I have the following ServiceRole & binding:

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: testapp
  namespace: test-ns
spec:
  rules:
  - services: ["testapp.test-ns.svc.cluster.local"]
    methods: ["GET", "POST"]
---
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: testapp
  namespace: test-ns
spec:
  subjects:
  - properties:
      source.namespace: "default"
  roleRef:
    kind: ServiceRole
    name: "testapp"

But I am able to access the service using curl from namespaces other than default as well.
To test whether the service role binding is working I deleted the service role and role binding then I got “RBAC access denied” as expected.
What could be wrong? Could this be a bug?