Tutorial: Istio
Istio is an open source service mesh for managing the different microservices that makeup a cloud-native application. Istio provides a mechanism to use a service as an external authorizer with theAuthorizationPolicy API.
This tutorial shows how Istio's AuthorizationPolicy can be configured to delegate authorization decisions to OPA.
Prerequisites
This tutorial requires Kubernetes 1.20 or later. To run the tutorial locally ensure you start a cluster with Kubernetesversion 1.20+, we recommend usingminikube orKIND.
The tutorial also requires Istio v1.19.0 or later. It assumes you have Istio deployed on top of Kubernetes.See Istio'sHelm Install page to get started.
If you are using an earlier version of Istio (1.9+), you will have to customize theAuthorizationPolicy
in thequick_start.yaml
file to use thesecurity.istio.io/v1beta1
API version instead ofsecurity.istio.io/v1
.
Steps
1. Install OPA-Envoy
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/opa-envoy-plugin/main/examples/istio/quick_start.yaml
Thequick_start.yaml
manifest defines the following resources:
AuthorizationPolicy to direct authorization checks to the OPA-Envoy sidecar. See
kubectl -n {$NAMESPACE} get authorizationpolicy ext-authz
for details.ServiceEntry to allow Istio to find the OPA-Envoy sidecars. See
kubectl -n {$NAMESPACE} get serviceentry opa-ext-authz-grpc-local
for details.Kubernetes namespace (
opa-istio
) for OPA-Envoy control plane components.Kubernetes admission controller in the
opa-istio
namespace that automatically injects the OPA-Envoy sidecar into pods in namespaces labelled withopa-istio-injection=enabled
.OPA configuration file and an OPA policy into ConfigMaps in the namespace where the app will be deployed, e.g.,
default
.The following is the example OPA policy:- alice is granted aguest role and can perform a
GET
request to/productpage
. - bob is granted anadmin role and can perform a
GET
to/productpage
and/api/v1/products
.
authz.regopackage istio.authz
default allow:=false
allow if{
input.parsed_path[0]=="health"
input.attributes.request.method=="GET"
}
allow if{
some user_role in _user_roles[_user_name]
some permission in _role_permissions[user_role]
permission.method== input.attributes.request.http.method
permission.path== input.attributes.request.http.path
}
# Underscore prefix used only to signal that rules and functions are
# intended to be referenced only within the same policy, i.e. "private".
# It has no special meaning to OPA.
_user_name:= parsed if{
[_, encoded]:=split(input.attributes.request.http.headers.authorization," ")
[parsed,_]:=split(base64url.decode(encoded),":")
}
_user_roles:={
"alice":["guest"],
"bob":["admin"],
}
_role_permissions:={
"guest":[{"method":"GET","path":"/productpage"}],
"admin":[
{"method":"GET","path":"/productpage"},
{"method":"GET","path":"/api/v1/products"},
],
}OPA is configured to query for the
data.istio.authz.allow
decision. If the response istrue
the operation is allowed, otherwise theoperation is denied. Sample input received by OPA is shown below:input.json{
"attributes":{
"request":{
"http":{
"method":"GET",
"path":"/productpage",
"headers":{
"authorization":"Basic YWxpY2U6cGFzc3dvcmQ="
}
}
}
}
}package example
result:= data.istio.authz.allowAn example of the complete input received by OPA can be seenhere.
In typical deployments the policy would either be built into the OPA containerimage or it would be fetched dynamically via theBundle API. ConfigMaps areused in this tutorial for test purposes.
- alice is granted aguest role and can perform a
2. Configure the mesh to define the external authorizer
Edit the mesh configmap withkubectl edit configmap -n istio-system istio
and define the external provider:
data:
mesh:|-
# Add the following lines to define the ServiceEntry previously created as an external authorizer:
extensionProviders:
-name: opa-ext-authz-grpc
envoyExtAuthzGrpc:
service: opa-ext-authz-grpc.local
port:9191
Seethe Istio Docs for AuthorizationPolicy formore details.
The format of the service value is[<Namespace>/]<Hostname>
. The specificationof<Namespace>
is required only when it is insufficient to unambiguously resolvea service in the service registry. See also theconfiguration documentation.Example:opa-ext-authz-grpc.foo.svc.cluster.local
orbar/opa-ext-authz-grpc.local
.
3. Enable automatic injection of the Istio Proxy and OPA-Envoy sidecars in the namespace where the app will be deployed, e.g.,default
kubectl label namespace default opa-istio-injection="enabled"
kubectl label namespace default istio-injection="enabled"
4. Deploy the BookInfo application and make it accessible outside the cluster
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml
5. Set theSERVICE_HOST
environment variable in your shell to the public IP/port of the Istio Ingress gateway
Run this command in a new terminal window to start a Minikube tunnel that sends traffic to your Istio Ingress Gateway:
minikube tunnel
Check that the Service shows anEXTERNAL-IP
:
kubectl -n istio-system get service istio-ingressgateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.98.42.178 127.0.0.1 15021:32290/TCP,80:30283/TCP,443:32497/TCP,31400:30216/TCP,15443:30690/TCP 5s
minikube:
export SERVICE_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
For other platforms see theIstio documentation on determining ingress IP and ports.
6. Exercise the OPA policy
Check thatalice can access/productpage
BUT NOT/api/v1/products
.
curl --user alice:password -i http://$SERVICE_HOST/productpage
curl --user alice:password -i http://$SERVICE_HOST/api/v1/products
Check thatbob can access/productpage
AND/api/v1/products
.
curl --user bob:password -i http://$SERVICE_HOST/productpage
curl --user bob:password -i http://$SERVICE_HOST/api/v1/products
Wrap Up
Congratulations for finishing the tutorial !
This tutorial showed how Istio'sAuthorizationPolicy APIcan be configured to use OPA as an External authorization service.
This tutorial also showed a sample OPA policy that returns aboolean
decisionto indicate whether a request should be allowed or not.
More details about the tutorial can be seenhere.
- Prerequisites
- Steps
- 1. Install OPA-Envoy
- 2. Configure the mesh to define the external authorizer
- 3. Enable automatic injection of the Istio Proxy and OPA-Envoy sidecars in the namespace where the app will be deployed, e.g.,
default
- 4. Deploy the BookInfo application and make it accessible outside the cluster
- 5. Set the
SERVICE_HOST
environment variable in your shell to the public IP/port of the Istio Ingress gateway - 6. Exercise the OPA policy
- Wrap Up