All Products
Search
Document Center

Alibaba Cloud Service Mesh:Implement custom authorization by using the gRPC protocol

Last Updated:Feb 04, 2024

The custom authorization feature allows you to perform fine-grained Resource Access Management (RAM) on services that use the gRPC protocol. With this feature, you can customize authorization mechanisms based on your business requirements. Authentication is required when services communicate with each other. This ensures that only authenticated and authorized requests can access specific service resources and improves the security of service-to-service communication. This topic uses the httpbin application and the sleep application in the following example to describe how to implement custom authorization by using the gRPC protocol.

Prerequisites

A Container Service for Kubernetes (ACK) cluster is added to your ASM instance. For more information, see The cluster is added to the ASM instance.

Step 1: Deploy a custom authorization service

Deploy a custom authorization service in the ACK cluster. This service must comply with the API specifications of Istio for custom authorization services and support the HTTP and gRPC protocols. This service is used to implement custom authorization. The sample authorization service provided in this topic specifies that only requests with the x-ext-authz: allow header can pass the authentication.

Note

You can use the following sample authorization service or create a custom authorization service based on the code of the sample authorization service. For more information, visit the GitHub website.

  1. Create an ext-authz.yaml file that contains the following content:

    Expand to view the ext-authz.yaml file

    # 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
    ---
  2. Use kubectl to connect to the cluster and run the following command to deploy the custom authorization service in the cluster.

    For more information, see Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.

    kubectl apply -f ext-authz.yaml

    Expected output:

    service/ext-authz created
    deployment.apps/ext-authz created
  3. 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:

    2023/12/20 08:15:39 Starting gRPC server at [::]:9000
    2023/12/20 08:15:39 Starting HTTP server at [::]:8000

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

  4. Obtain the gRPC port that is used by the ext-authz service.

    1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

    2. On the Clusters page, click the name of the cluster that you want to manage and choose Network > Services in the left-side navigation pane.

    3. On the Services page, click ext-authz.

      In the Endpoint section of the service details page, you can view the gRPC port. In this example, the port is 9000.

Step 2: Deploy sample applications

  1. Create an httpbin.yaml file that contains the following content:

    Expand to view the httpbin.yaml file

    # 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 cluster:

    kubectl apply -f httpbin.yaml
  3. Create a sleep.yaml file that contains the following content:

    Expand to view the sleep.yaml file

    # 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: Use the gRPC protocol to connect to the custom authorization service

Declare the custom authorization service that you deployed in Step 1 in the ASM instance. This way, the ASM instance can use the service to authenticate requests.

  1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Mesh Security Center > Custom Authorization Service. On the page that appears, click Define Custom Authorization Service.

  3. On the Register Custom Authorization Service page, click the Custom authorization service (HTTP or gRPC protocol) implemented based on envoy.ext_authz tab, configure the related parameters, and then click Create.

    Type

    Parameter

    Description

    Required parameters

    Protocol

    The protocol that is used by the custom authorization service. In this example, GRPC is selected.

    Name

    The name of the custom authorization service. In this example, the value is set to test.

    Service Address

    The endpoint of the custom authorization service in the format of <Service name>.<Namespace>.svc.<Domain name of the cluster>. In this example, the value is set to ext-authz.default.svc.cluster.local.

    Port(1 - 65535)

    The service port of the custom authorization service. In this example, the value is set to 9000.

    Timeout(second)

    The period of time during which the authentication result must be returned. Unit: seconds. If the custom authorization service fails to respond within this period of time, the service is considered unavailable. In this example, the value is set to 10.

    Optional parameters

    Skip authentication while authorization service is unavailable

    Specifies whether to allow requests when the custom authorization service is unavailable. If you turn on this switch, requests are allowed when the custom authorization service is unavailable.

    Error code returned by asm proxy while Auth-Service is not available

    The error code to return when the custom authorization 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 custom authorization service is unavailable.

    Carry origin request body within auth request

    Specifies whether to add the body of the request to be authenticated to the authentication request to be sent to the custom authorization service. If you turn on this switch, you must specify the maximum length of the request body. If you also turn on Allow send incomplete message to Auth-Service, ASM truncates the request body if the length of the request body exceeds the maximum length. Then, ASM sends the authentication request with the truncated request body to the custom authorization service.

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. In the left-side navigation pane, choose Service Mesh > Mesh Management.

  2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Mesh Security Center > AuthorizationPolicy. On the page that appears, click Create.

  3. On the Create page, configure the related parameters and click Create.

    Parameter

    Description

    Name

    The name of the custom authorization policy. In this example, the value is set to test1.

    Policy Type

    The type of the custom authorization policy. In this example, the value is set to Custom Authorization Service.

    Custom Authorization Service

    In this example, grpcextauth-test(GRPC) is selected.

    Namespace

    The namespace in which you want to create the authorization policy. In this example, the Namespace parameter on the Workload Scope tab is set to default.

    Effective Scope

    The effective scope of the authorization policy. In this example, the value is set to Service.

    Workload

    The workload on which the authorization policy takes effect. In this example, the value is set to httpbin.

    Request Matching Rules

    In this example, Paths is turned on in the Add Request Target section and the value is set to /headers.

Step 5: Verify that custom authorization is 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"

    The status code 200 is returned, which indicates that custom authorization is not 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

    The preceding result indicates that custom authorization is triggered but the authentication 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.default:8000",
        "User-Agent": "curl/8.5.0",
        "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=c3e5364e87add0f4f69e6b0d029f5961b404c8f209bf9004b3d21a82cf67****;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep"
      }
    }

    The preceding result indicates that custom authorization is triggered and the authentication is successful. The verification results show that only requests with the x-ext-authz: allow header are allowed to access httpbin.default:8000/headers. This indicates that custom authorization is implemented as expected.

References