Protecting APIs on Istio
Purpose
Configure the Istio gateway so that you can use it for protecting your APIs deployed on Kubernetes.
API discovery with Istio Authorizer
The ACP Istio Authorizer supports the automatic service discovery based on openapi specification.
A service can use the services.k8s.cloudentity.com/spec-url
annotation on a deployment resource
to specify an url where its openapi specification is available, for example:
kind: Deployment
metadata:
name: hello
labels:
app: hello
namespace: default
annotations:
services.k8s.cloudentity.com/openapi-url: "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore.yaml"
Istio Authorizer scans deployments and once it finds the annotation described above, it fetches the specification, parses it to get a list of APIs that a service is exposing, and then it’s sending this information to ACP.
By default, Istio Authorizer is configured to perform the service
discovery only in the default namespace. To make Istio Authorizer perform the service
discovery in more namespaces, configure them by adding the --namespace default,my-custom-ns
flag to args
of the istio-authorizer
deployment in
manifest.yaml.
Further reading
The ACP Istio Authorizer is using Istio external authorization with custom action and Authorization Policy features.
Prerequisites
Install the Kubernetes cluster with Istio
- Kubernetes version required is 1.14 or subsequent.
- Istio version required is 1.9 or subsequent.
-
You can set up a Kubernetes cluster locally using kind.
GO111MODULE="on" go get sigs.k8s.io/kind@v0.9.0 && kind create cluster
-
Install Istio.
curl -L https://istio.io/downloadIstio | sh - cd istio-1.8.2 export PATH=$PWD/bin:$PATH istioctl install --set profile=demo -y kubectl label namespace default istio-injection=enabled ✔ Istio core installed ✔ Istiod installed ✔ Egress gateways installed ✔ Ingress gateways installed ✔ Installation complete
-
Define the authorizer
-
Edit the mesh config with the following command:
kubectl edit configmap istio -n istio-system
-
Define acp authorizer using extension providers, for example:
data: mesh: |- extensionProviders: - name: "acp-authorizer" envoyExtAuthzGrpc: service: "istio-authorizer.acp-system.svc.cluster.local" port: "9001"
-
Restart Istio to apply the changes:
kubectl rollout restart deployment/istiod -n istio-system
-
Select the workspace
-
In your browser, navigate to ACP and log in with your credentials.
-
In the Workspace Directory view, select a workspace that you want to enter.
Create the Istio gateway
-
In the workspace, select APIs from the sidebar.
-
Select the GATEWAYS tab.
-
Select ADD GATEWAY.
-
Select Istio, enter the name and the description for your gateway, and select NEXT.
-
In the Gateway Management view, go to the QUICK START tab and proceed as follows:
-
Select Download Package to download the zipped Istio Authorizer package. Unzip the package locally and enter the extracted folder.
Note
The package includes
-
manifest.yaml listing API details
-
kustomization.yaml defining resources and secret generator inputs.
-
-
To deploy Istio Authorizer, execute command
kubectl apply -k .
Result
Istio Authorizer scans deployments in configured namespaces and funnels information about discovered APIs to ACP.
-
Back in the ACP administrator portal (Gateway Management > QUICK START), select CONNECT API GROUPS to connect APIs and enable enforcement policies.
Result
The predefined set of API groups has been imported and displayed in the APIs tab of the Gateway Management view. The API groups are ready to be connected to services.
-
Deploy and protect sample service
-
Deploy a sample HTTP service using the following command:
kubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: httpbin --- apiVersion: v1 kind: Service metadata: name: httpbin spec: selector: app: httpbin ports: - port: 80 name: http --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin labels: app: httpbin annotations: services.k8s.cloudentity.com/spec-url: "http://httpbin.org/spec.json" spec: replicas: 1 selector: matchLabels: app: httpbin template: metadata: labels: app: httpbin spec: serviceAccountName: httpbin containers: - name: httpbin image: "kennethreitz/httpbin" ports: - containerPort: 80 name: http EOF
-
Apply the policy:
kubectl apply -f - <<EOF apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: acp-authorizer namespace: default spec: action: CUSTOM provider: name: acp-authorizer rules: - {} EOF
Note
In the example above, the policy is applied to all services in the default namespace. Take a look at Authorization Policy if you would like to protect only a specific service.
Connect a service
There are two ways to connect Istio API groups to ACP services: starting from the gateway to be connected or starting from the service that you want to connect.
From the gateway
-
From the list of available gateways, select your newly-created Istio gateway and go to its APIs tab.
Result
A list of imported API groups opens.
-
From the list of API groups available, select an API group and, from its drop-down menu, pick a service to which you’d like to connect the API group.
Note
You can connect the API group to an existing service or a new one you create, both options available from the same service drop-down menu.
From the service
-
Select APIs from the left sidebar and go to the AUTHORIZATION tab.
-
Pick a service that you want to connect and select ADD GATEWAY API for the selected service.
-
In the Connect Istio API Group popup window, select an API gateway and an API group to be connected. Click CONNECT to proceed.
Result
In the APIS tab of the Gateway Management view, you can see specific API groups integrated to services.
Apply a sample policy
-
Select APIs from the left sidebar and go to the AUTHORIZATION tab.
-
Select a service protected by Istio and any API with authorization status None.
-
In the Edit API popup window, select Policy from the dropdown list and click Update to proceed.
Result
You have successfully assigned a policy to your API.
Call deployed and protected service
To test your deployed and protected service, change the variables and execute the command:
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.9/samples/sleep/sleep.yaml
export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
kubectl exec -it $SLEEP_POD -c sleep curl {YOUR_SERVICE_URL}/{ENDPOINT}
Example
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.9/samples/sleep/sleep.yaml export SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) kubectl exec -it $SLEEP_POD -c sleep curl http://httpbin.default:80/deny