Restrict access from one service to another

Good day!

We are thinking about deploying istio servie mesh in our cluster. One of the tasks is convinient way of restriction access from one service to another. In plain Kubernetes we can to it with Network Policies.
With what kind of object we can achieve it in istio?

Thank you!

Hi @reistlin,

In Istio you have a few options.

If you’re using Calico for Network Policy, you can use Calico’s integration with Istio to extend your existing Network Policy to the application layer.

Or, you can use Istio’s built-in authorization framework, which involves creating ServiceRole and ServiceRoleBinding objects.

Finally, you can use one of several Mixer adapters that allow you to enforce access control.

Hope that helps,
Spike

As @spikecurtis mentioned, one of the options is to use Istio authorization. You can try this task to see how it works https://istio.io/docs/tasks/security/authz-http/. Istio authorization is usually used with authentication. If you decide to use mTLS for your service to service communication (which you don’t need to change any code in your applications), you’ll also get encrypted communication out of the box.

Thank you!

Say I need one service has abilities to GET from another service.

I am creating simple ServiceRole which allows GET to my httpbin service:

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: httpbin
  namespace: default
spec:
  rules:
  - services: ["httpbin.default.svc.cluster.local"]
    methods: ["GET", "HEAD"]

And I am trying to bind this role to another service:

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: httpbind
  namespace: default
spec:
  subjects:
  - properties:
      source.namespace: "default" // What property to use ???
  roleRef:
    kind: ServiceRole
    name: "httpbin"

How could I achieve that? I see the closest one is source.principal property, but that means I will need to create a service account for all services?

Thank you!

K8s already created a default service account for each namespace you created (and you may guess, the name is indead default). Unless you specify otherwise, the pod running under that namespace will use the default service account.

You can create K8s accounts and annotate your deployment to use that service account. However, it is recommended to use separate namespaces if you want your policy is also protected via K8s RBAC.

To add to what Diem said, I think you should create a service account for each service. If you use the default service account for the namespace, every application in the same namespace will have the same identity. This is no difference than just restricting the access to namespace-level (source.namespace: <namespace), rather than service-level.

So if you have httpbin in namespace default like above, and sleep in namespace default or any other namespace, you can create a service account for sleep and use source.principal under properties or user, and use (most likely) cluster.local/ns/<sleep deployment namespace>/sa/<sleep service account> to allow only sleep to have GET access to httpbin.

Another choice you can try Sidecar to restrict a Service from accessing other services, this can work without authz. It works on networking layer.

You mean Kubernetes Network Policies?

Istio Sidecar https://istio.io/docs/reference/config/networking/v1alpha3/sidecar/ which introduced in 1.1

Thank you!

I am trying to use sidecar, but it seems does not work. Where is mistake?

apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
  name: iam
  namespace: ns1
spec:
  workloadSelector:
    labels:
      app: iam
  egress:
    - hosts:
        - "ns1/postgres.ns1.svc.cluster.local"

After applying this config IAM service still has access to all services