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.
  1. You can set up a Kubernetes cluster locally using kind.

    GO111MODULE="on" go get sigs.k8s.io/kind@v0.9.0 && kind create cluster
    
  2. 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
    
  3. Define the authorizer

    1. Edit the mesh config with the following command:

      kubectl edit configmap istio -n istio-system
      
    2. 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"    
      
    3. Restart Istio to apply the changes:

      kubectl rollout restart deployment/istiod -n istio-system
      

Select the workspace

  1. In your browser, navigate to ACP and log in with your credentials.

  2. In the Workspace Directory view, select a workspace that you want to enter.

Create the Istio gateway

  1. In the workspace, select APIs from the sidebar.

  2. Select the GATEWAYS tab.

  3. Select ADD GATEWAY.

  4. Select Istio, enter the name and the description for your gateway, and select NEXT.

  5. In the Gateway Management view, go to the QUICK START tab and proceed as follows:

    1. 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.

    2. 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.

    3. 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

  1. 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
    
  2. 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

  1. 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.

  2. 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

  1. Select APIs from the left sidebar and go to the AUTHORIZATION tab.

  2. Pick a service that you want to connect and select ADD GATEWAY API for the selected service.

  3. 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

  1. Create a policy.

  2. Select APIs from the left sidebar and go to the AUTHORIZATION tab.

  3. Select a service protected by Istio and any API with authorization status None.

  4. 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