Integrate a custom HTTP authorization service

更新时间:
复制 MD 格式

The custom authorization service feature provides fine-grained access control for services that communicate over HTTP. By adding a custom authorization check to service-to-service communication, you can ensure that only authenticated and authorized requests access your service resources, which improves security. This topic uses the sleep and httpbin applications to demonstrate how to integrate a custom HTTP authorization service.

Prerequisites

The cluster is added to the ASM instance..

Step 1: Deploy a custom authorization service

Deploy a custom authorization service in your ACK cluster. This service must comply with the Istio API specification for custom authorization services and support both HTTP and gRPC protocols to implement your custom authorization logic. The sample service used in this topic requires that a request include the x-ext-authz: allow request header to pass the authorization check.

Note

You can also use the code from this sample application as a reference to create your own custom authorization service. For more information, see Custom authorization.

  1. Connect to your cluster by using kubectl and create a file named ext-authz.yaml that contains the following content.

    For more information about how to connect to a cluster by using kubectl, see Obtain the KubeConfig of a cluster and use kubectl to connect to the cluster.

    ext-authz.yaml

    # 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: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/asm-ext-authz-example:0.6
            imagePullPolicy: IfNotPresent
            name: ext-authz
            ports:
            - containerPort: 8000
            - containerPort: 9000
    ---
  2. Run the following command to deploy the custom authorization service.

    kubectl apply -f ext-authz.yaml
  3. Run the following command to check the pod deployment status.

    kubectl get pod

    Expected output:

    NAME                         READY   STATUS    RESTARTS   AGE
    ext-authz-6b5db88f86-2m7c6   2/2     Running   0          79m
  4. Run the following command to verify that the application is working.

    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

    This output indicates that the application is working and that the custom authorization service is deployed.

  5. Get the HTTP port of the ext-authz service.

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

    2. On the Clusters page, click the name of your cluster. In the left navigation pane, click Network > Services.

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

      In the Endpoint section, note that the HTTP port is 8000. The access address for this service is ext-authz.default.svc.cluster.local:8000.

Step 2: Deploy the sample applications

  1. Create a file named httpbin.yaml with the following content.

    httpbin.yaml

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

    kubectl apply -f httpbin.yaml
  3. Create a file named sleep.yaml with the following content.

    sleep.yaml

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

    kubectl apply -f sleep.yaml

Step 3: Register the custom authorization service

Declare the service deployed in Step 1 to the Service Mesh so that the Service Mesh can use the service for 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 > Custom Authorization Service. On the page that appears, click Define Custom Authorization Service.

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

    Type

    Parameter

    Description

    Required parameters

    Protocol

    Select the protocol for the custom authorization service. In this example, select HTTP.

    Name

    The name of the custom authorization service. In this example, enter test4http.

    Service Address

    Enter the service address of the custom authorization application. The address must be a fully qualified domain name in the format <Application Name>.<Namespace>.svc.<Cluster Domain>. For this example, enter ext-authz.default.svc.cluster.local.

    Port(1 - 65535)

    Enter the service port of the custom authorization application. In this example, enter 8000.

    Timeout(second)

    If the authorization application does not respond within this time period, the service is considered unavailable. In this example, set the timeout to 10 seconds.

    Optional parameters

    Skip authentication while authorization service is unavailable

    If enabled, requests are allowed if the authorization service is unavailable. This option is disabled in this example.

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

    This option is available only when Skip authentication while authorization service is unavailable is disabled. If you enable this option, you must enter an error code. This code is returned to the client when the authorization service is unavailable. In this example, this option is disabled.

    Carry origin header within auth request [includeRequestHeadersInCheck]

    When enabled, you must specify the header keys to include. Matching headers are included in the request sent to the custom authorization service. For this example, see the configuration in Include headers in the authorization request.

    Note

    This parameter can be configured only when Protocol is set to HTTP.

    Add a header in the authentication request (if a header with the same name already exists, the original value will be overwritten) [includeAdditionalHeadersInCheck]

    When enabled, you must specify the header keys and values to add to the authorization request.

    If a header with the same name already exists, its value is overwritten. In this example, this option is disabled.

    Note

    This parameter can be configured only when Protocol is set to HTTP.

    Overwrite Header when authentication passes (overwrite Header in the request to the target service by using Header in the authentication request Response) [headersToUpstreamOnAllow]

    If enabled, specify which header keys to overwrite. On successful authorization, matching headers from the authorization response overwrite the corresponding headers in the request to the destination service. For this example, see the configuration in Overwrite headers on successful authorization.

    Note

    This parameter can be configured only when Protocol is set to HTTP.

    Overwrite Header when authentication fails (overwrite Header in Response using Header in authentication request Response) [headersToDownstreamOnDeny]

    If enabled, specify which header keys to overwrite. On failed authorization, matching headers from the authorization response overwrite the corresponding headers in the response to the calling service. For this example, see the configuration in Overwrite headers on failed authorization.

    Note

    This parameter can be configured only when Protocol is set to HTTP.

    Carry origin request body within auth request

    If enabled, specify the maximum size of the request body to include in the authorization check. If you also enable Allow send incomplete message to Auth-Service(HTTP 413 will be returned if request body size beyond limitation and this option is disabled), bodies that exceed the limit are truncated and sent. Otherwise, requests with oversized bodies are rejected with an HTTP 413 error.

    Figure 1. Include headers in the authorization request

    Note

    The last entry is the newly added x-ext-authz.

    The headers to be included are: cookie, x-forwarded-access-token, x-forwarded-user, x-forwarded-email, authorization, x-forwarded-proto, proxy-authorization, user-agent, x-forwarded-host, from, x-forwarded-for, accept, and x-ext-authz.

    Figure 2. Overwrite headers on successful authorization

    Note

    The last entry is the newly added x-ext-authz-check-result.

    This list also includes the five existing fields: authorization, cookie, path, x-auth-request-access-token, and x-forwarded-access-token.

    Figure 3. Overwrite headers on failed authorization

    Note

    The last entry is the newly added x-ext-authz-check-result.

    The list of headers to overwrite already contains content-type and set-cookie. The new x-ext-authz-check-result is added at the end of the list.

Step 4: Define an authorization policy

Create an authorization policy to specify which operations require authorization.

  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 parameters, and then click Create.

    Parameter

    Description

    Name

    The name of the custom authorization policy. In this example, enter test1.

    Policy Type

    Select Custom Authorization Service.

    Custom Authorization Service

    Select httpextauth-test4http(HTTP).

    Namespace

    On the Workload Scope tab, select the default Namespace.

    Effective Scope

    Select Service.

    Workload

    Select httpbin.

    Request Matching Rules

    In the Add Request Target section, enable Paths and set the value to /headers.

Step 5: Verify the custom authorization

  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"

    A 200 status code is returned, which indicates that authorization was not triggered. Because the request path /ip does not match the /headers path in the authorization policy, the policy did not apply to this request.

  2. Run the following command to access httpbin.default:8000/headers with the x-ext-authz: deny request header.

    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 -i

    Expected output:

    HTTP/1.1 403 Forbidden
    x-ext-authz-check-result: denied
    content-length: 76
    content-type: text/plain; charset=utf-8
    date: Wed, 20 Dec 2023 09:53:28 GMT
    server: envoy
    x-envoy-upstream-service-time: 10
    denied by ext_authz for not found header `x-ext-authz: allow` in the request

    The output shows that the request was denied because it triggered the authorization policy. The response includes the x-ext-authz-check-result: denied header, as configured for authorization failures. The policy was applied because the request path is /headers.

  3. Run the following command to access httpbin.default:8000/headers with the x-ext-authz: allow request header.

    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 output shows that the request was allowed because it triggered the authorization policy and passed the check. The response includes the "X-Ext-Authz-Check-Result": "allowed" header, as configured for successful authorization. The policy was applied because the request path is /headers.

Related operations