Alibaba Cloud Service Mesh (ASM) supports custom external authorization. You can add an authentication process to the communication between services to ensure that only authenticated requests can access key services. This topic uses the httpbin application as an example to describe how to implement custom external authorization.

Prerequisites

External authorization process

  1. Deploy an external authorization service in the Container Service for Kubernetes (ACK) cluster. This service must comply with the Istio API specifications for custom authentication services and support the HTTP and gRPC protocols.
  2. Deploy a sample application in the ACK cluster to verify the external authorization feature.
  3. Define an external authorization service in ASM and associate the service with the external authorization service that you deployed in Step 1. This way, ASM can use the authorization service deployed in Step 1 for authentication.
  4. Create an authorization policy in ASM, configure an application that requires external authentication, and perform authentication by using the external authorization service that you configured in Step 3.
Flowchart

Step 1: Deploy an external authorization service

Deploy an external authorization service named ext-authz in the ACK cluster to implement external authentication logic. The external authorization service specifies that only requests with the x-ext-authz: allow request header can be authenticated to access the httpbin application.

  1. Use kubectl to connect to the ACK cluster. For more information, see Connect to ACK clusters by using kubectl.
  2. Create an ext-authz.yaml file that contains the following content:
    # Copyright Istio Authors
    #
    #   Licensed under the Apache License, Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing, software
    #   distributed under the License is distributed on an "AS IS" BASIS,
    #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.
    
    # Example configurations for deploying ext-authz server separately in the mesh.
    
    apiVersion: v1
    kind: Service
    metadata:
      name: ext-authz
      labels:
        app: ext-authz
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 8000
      - name: grpc
        port: 9000
        targetPort: 9000
      selector:
        app: ext-authz
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ext-authz
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: ext-authz
      template:
        metadata:
          labels:
            app: ext-authz
        spec:
          containers:
          - image: istio/ext-authz:0.6
            imagePullPolicy: IfNotPresent
            name: ext-authz
            ports:
            - containerPort: 8000
            - containerPort: 9000
    ---
  3. Run the following command to deploy the external authorization service in the ACK cluster:
    kubectl apply -f ext-authz.yaml

    Expected output:

    service/ext-authz created
    deployment.apps/ext-authz created
  4. Run the following command to check whether the ext-authz service works as expected.
    kubectl logs "$(kubectl get pod -l app=ext-authz -n default -o jsonpath={.items..metadata.name})" -n default -c ext-authz

    Expected output:

    2021/01/07 22:55:47 Starting HTTP server at [::]:8000
    2021/01/07 22:55:47 Starting gRPC server at [::]:9000

    If the preceding result is returned, the external authorization service is deployed.

  5. Obtain the gRPC port that is used by the ext-authz application.
    1. Log on to the ACK console.
    2. In the left-side navigation pane of the ACK console, click Clusters.
    3. On the Clusters page, find the cluster that you want to manage and click the name of the cluster or click Details in the Actions column. The details page of the cluster appears.
    4. In the left-side navigation pane of the details page, choose Network > Services
    5. On the Services page, click ext-authz.
      In the Endpoint section of the service details page, you can find that the gRPC port used is 9000.

Step 2: Deploy sample applications

  1. Create an httpbin.yaml file that contains the following content:
    # Copyright Istio Authors
    #
    #   Licensed under the Apache License, Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing, software
    #   distributed under the License is distributed on an "AS IS" BASIS,
    #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.
    
    ##################################################################################################
    # httpbin service
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          serviceAccountName: httpbin
          containers:
          - image: docker.io/kennethreitz/httpbin
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
                            
  2. Run the following command to deploy the httpbin application in the ACK cluster:
    kubectl apply -f httpbin.yaml
  3. Create a sleep.yaml file that contains the following content:
    # Copyright Istio Authors
    #
    #   Licensed under the Apache License, Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing, software
    #   distributed under the License is distributed on an "AS IS" BASIS,
    #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.
    
    ##################################################################################################
    # Sleep service
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: curlimages/curl
            command: ["/bin/sleep", "3650d"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
                            
  4. Run the following command to deploy the sleep application in the ACK cluster:
    kubectl apply -f sleep.yaml

Step 3: Manage the external authorization service

Declare the ext-authz service that you deployed in Step 1 to an ASM instance so that the ASM instance can use the service to authenticate requests.

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
  4. On the details page of the ASM instance, choose Zero Trust Security > External Authorization in the left-side navigation pane.
  5. On the External Authorization page, click Create.
  6. On the Create External Authorization Service page, set the parameters that are described in the following table and click Create.
    Type Parameter Description
    Required parameters Name The name of the custom external authorization service. In this example, set the value to test.
    Protocol The protocol that is used by the external authorization application. In this example, select GRPC.
    Service Address The endpoint of the external authorization application in the format of <Application name>.<Namespace name>.svc.<Domain name of the cluster>. In this example, set the parameter to ext-authz.default.svc.cluster.local.
    Port The service port of the external authorization application. In this example, set the parameter to 9000.
    Timeout The response timeout period of the external authorization application. Unit: seconds. If the external authorization application does not respond within the specified timeout period, the external authorization service is considered unavailable. In this example, set the parameter to 10.
    Optional parameters Skip authentication while authorization service is unavailable Specifies whether to allow requests when the external authentication service is unavailable. If you turn on this switch, requests are allowed when the external authentication service is unavailable.
    Error code returned by asm proxy while Auth-Service is not available Specifies the error code to return when the external authentication service is unavailable. This parameter is available only if you turn off Skip authentication while authorization service is unavailable. If you turn on Error code returned by asm proxy while Auth-Service is not available, you must specify an error code. This way, ASM returns this error code to the caller when the external authentication service is unavailable.
    Carry origin request body within auth request Specifies whether to allow an authentication request to carry the request body. If you turn on this switch, you must specify the maximum length of the request body. If you further turn on Allow send incomplete message to Auth-Service, ASM truncates the request body to the specified maximum length if the original length of the request body exceeds the specified maximum length. Then, ASM sends the truncated request body to the external authentication service.
    Carry origin header within auth request Specifies whether to allow an authentication request to carry headers. If you turn on this switch, you must specify one or more header keys to be carried. Then, ASM adds the matched headers to a request to be sent to the external authentication service.
    Note This parameter is available only if you set the Protocol parameter to HTTP.
    Overwrite Header when authentication passes Specifies whether to overwrite the headers in a request to be sent to the destination service with the headers matched in the corresponding authentication response if the authentication is successful. If you turn on this switch, you must specify one or more header keys to be overwritten. If the authentication is successful, ASM overwrites the headers in a request to be sent to the destination service with the headers matched in the corresponding authentication response.
    Note This parameter is available only if you set the Protocol parameter to HTTP.
    Overwrite Header when authentication fails Specifies whether to overwrite the headers in a service response with the headers matched in the corresponding authentication response if the authentication fails. If you turn on this switch, you must specify one or more header keys to be overwritten. If the authentication fails, ASM overwrites the headers in a service response with the headers matched in the corresponding authentication response.
    Note This parameter is available only if you set the Protocol parameter to HTTP.

Step 4: Create an authorization policy

Create an authorization policy to configure the request operation that requires authentication.

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
  4. On the details page of the ASM instance, choose Zero Trust Security > AuthorizationPolicy in the left-side navigation pane.
  5. On the AuthorizationPolicy page, click Create.
  6. On the Create page, set the parameters that are described in the following table and click Create.
    Parameter Description
    Namespace The name of the namespace in which the sample applications are deployed. In this example, select default.
    Name The name of the custom authorization policy. In this example, set the parameter to test1.
    Policies The type of the authorization policy. In this example, select RULES.
    Action The authorization action. In this example, select CUSTOM.
    Provider Name The external authorization service. In this example, select test.
    Workload Label Selection The workload to which the authorization policy applies.

    Turn on Workload Label Selection, click Add Matching Label, and then add a label whose name is app and value is httpbin.

    Request Operation The request operation that requires authentication.

    Turn on Request Operation and click Add Request Operation to List. Click Add Request Operation. Then, set the Request Operation Domain parameter to path and the Value parameter to /headers.

Step 5: Verify whether external authorization can be implemented as expected

  1. Run the following command to access httpbin.default:8000/ip:
    kubectl exec "$(kubectl get pod -l app=sleep -n default -o jsonpath={.items..metadata.name})" -c sleep -n default -- curl "http://httpbin.default:8000/ip" -s -o /dev/null -w "%{http_code}\n"

    Expected output:

    200

    If the preceding result is returned, no authentication is triggered.

  2. Run the following command to use a request with the x-ext-authz: deny request header to access httpbin.default:8000/headers:
    kubectl exec " $(kubectl get pod -l app=sleep -n default -o jsonpath={.items..metadata.name})" -c sleep -ndefault -- curl "http://httpbin.default:8000/headers" -H "x-ext-authz: deny" -s

    Expected output:

    denied by ext_authz for not found header `x-ext-authz: allow` in the request

    If the preceding result is returned, the authentication is triggered but fails.

  3. Run the following command to use a request with the x-ext-authz: allow request header to access httpbin.default:8000/headers:
    kubectl exec "$(kubectl get pod -l app=sleep -n default -o jsonpath={.items..metadata.name})" -c sleep -n default -- curl "http://httpbin.default:8000/headers" -H "x-ext-authz: allow" -s

    Expected output:

    {
      "headers": {
        "Accept": "*/*",
        "Host": "httpbin:8000",
        "User-Agent": "curl/7.76.0-DEV",
        "X-B3-Parentspanid": "430f770aeb7ef215",
        "X-B3-Sampled": "0",
        "X-B3-Spanid": "60ff95c5acdf5288",
        "X-B3-Traceid": "fba72bb5765daf5a430f770aeb7e****",
        "X-Envoy-Attempt-Count": "1",
        "X-Ext-Authz": "allow",
        "X-Ext-Authz-Check-Result": "allowed",
        "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=e5178ee79066bfbafb1d98044fcd0cf80db76be8714c7a4b630c7922df520bf2;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep"
      }
    }

    If the preceding result is returned, the authentication is triggered and successful.

    The verification results show that only requests with the x-ext-authz: allow request header can access httpbin.default:8000/headers. This indicates that custom external authorization is implemented as expected.