Authentication means verifying the identity of a client. Authorization, on the other hand, verifies the permissions of that client, or: “can this service do what they’re asking to do?”
While all requests in an Istio mesh are allowed by default, Istio provides an AuthorizationPolicy
resource that allows you to define granular policies for your workloads. Istio translates your AuthorizationPolicies into Envoy-readable config, then mounts that config into the Istio sidecar proxies. From there, authorization policy checks are performed by the sidecar proxies. Let’s see how it works.
Here, the ShoeStore application is deployed to the default
Kubernetes namespace. There are three HTTP workloads, each defined with their own Kubernetes Deployment, Service, and ServiceAccount.
- shoes: exposes an API for all the shoes in the store
- users: stores purchase history
- inventory: loads new shoe models into shoes.
We want to authorize the inventory service to be able to POST
data to the shoes services, and then lock down all access to the users service. To do this, we will create two AuthorizationPolicies
: one for shoes
, and one for users
.
Before deploying any policies, we can access both shoes and users from inside the inventory service’s application container.
$ curl -X GET shoes
🥾 Shoes service
$ curl -x GET users
👥 Users service
First, let’s create an AuthorizationPolicy for shoes
:
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "shoes-writer"
namespace: default
spec:
selector:
matchLabels:
app: shoes
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/inventory-sa"]
to:
- operation:
methods: ["POST"]
In this policy:
- The
selector
onshoes
means we’re enforcing any Deployment labeled withapp:shoes
. - The
source
workload we’re allowing has theinventory-sa
identity. In a Kubernetes environment, this means that only pods with theinventory-sa
Service Account can access shoes. (Note: You must enable Istio mutual TLS authentication to use service account-based authorization policies. Mutual TLS is what allows the workload’s service account certificates to be passed in the request.) - The only whitelisted HTTP operation is
POST
, meaning that other HTTP operations, likeGET
, will be denied.
Once we apply the shoes-writer
policy, we can successfully POST
from inventory:
$ curl -X POST shoes
🥾 Shoes service
But GET
requests from inventory
are denied:
$ curl -X GET shoes
RBAC: access denied
And if we try to POST
from a workload other than inventory
, for instance, from users
, the request will be denied:
$ curl -X POST shoes
RBAC: access denied
Next, let’s create a “deny-all” policy for the users service:
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "users-deny-all"
namespace: default
spec:
selector:
matchLabels:
app: users
Note that there are no rules
for this service, just a matchLabels
for our users Deployment. Also note that the difference between a deny-all and an allow-all AuthorizationPolicy is subtle: in an allow-all policy, you would specify rules: {}
.
Once we apply this resource, we are no longer able to access users from any of our services:
$ curl users
RBAC: access denied
To learn more: