Apache APIs IX integrates Open Policy Agent

Open Policy Agent (OPA) is an open source lightweight general policy engine, which can replace the built-in policy function module in the software to help users realize the decoupling of service and policy engine. Benefit from OPA Perfect ecosystem , users can easily integrate OPA and other services, such as program library, HTTP API, etc.

As shown in the figure below, OPA first describes the policy through the policy language Rego; Then the policy data is stored through JSON, and then the user can send a query request. After receiving the query request, OPA will combine the policy, data and the query request content entered by the user to generate the policy decision, and send the decision to the service.

Plug in introduction

Apache APISIX provides an OPA plug-in. Users can use this plug-in to easily introduce the policy capabilities provided by OPA into Apache APISIX to realize flexible identity authentication and admission control functions.

After the OPA plug-in is configured on the route, Apache apisid will assemble the request information and connection information into JSON data and send them to the policy decision API address when processing the response request. As long as the policies deployed in OPA comply with the data specifications set by Apache APISIX, functions such as pass request, reject request, custom status code, custom response header, custom response header and so on can be realized.

Taking HTTP API as an example, this paper introduces the OPA plug-in, and explains in detail how to integrate Apache apisid with OPA to realize the decoupling of authentication and authorization of back-end services.

How to use

Step 1: build a test environment

  1. Use Docker to build OPA services.
# Run OPA using Docker
docker run -d --name opa -p 8181:8181 openpolicyagent/opa:0.35.0 run -s
  1. Create a policy example.
# Create policy
curl -XPUT 'localhost:8181/v1/policies/example' \
--header 'Content-Type: text/plain' \
--data-raw 'package example

import input.request
import data.users

default allow = false

allow {
    # It has a request header named test header and a value of only for test
    request.headers["test-header"] == "only-for-test"
    # The request method is GET
    request.method == "GET"
    # Request path starts with / get
    startswith(request.path, "/get")
    # GET parameter test exists and is not equal to abcd
    request.query["test"] != "abcd"
    # GET parameter user does not exist
    request.query["user"]
}

reason = users[request.query["user"]].reason {
    not allow
    request.query["user"]
}

headers = users[request.query["user"]].headers {
    not allow
    request.query["user"]
}

status_code = users[request.query["user"]].status_code {
    not allow
    request.query["user"]
}'
  1. Create users data.
# Create test user data
curl -XPUT 'localhost:8181/v1/data/users' \
--header 'Content-Type: application/json' \
--data-raw '{
    "alice": {
        "headers": {
            "Location": "http://example.com/auth"
        },
        "status_code": 302
    },
    "bob": {
        "headers": {
            "test": "abcd",
            "abce": "test"
        }
    },
    "carla": {
        "reason": "Give you a string reason"
    },
    "dylon": {
        "headers": {
            "Content-Type": "application/json"
        },
        "reason": {
            "code": 40001,
            "desc": "Give you a object reason"
        }
    }
}'

Step 2: create a route and open the opa plug-in

curl -XPUT 'http://127.0.0.1:9080/apisix/admin/routes/r1' \
--header 'X-API-KEY: <api-key>' \
--header 'Content-Type: application/json' \
--data-raw '{
    "uri": "/*",
    "methods": [
        "GET",
        "POST",
        "PUT",
        "DELETE"
    ],
    "plugins": {
        "opa": {
            "host": "http://127.0.0.1:8181",
            "policy": "example"
        }
    },
    "upstream": {
        "nodes": {
            "httpbin.org:80": 1
        },
        "type": "roundrobin"
    }
}'

Step 3: Test Request

# Allow request
curl -XGET '127.0.0.1:9080/get?test=none&user=dylon' \
    --header 'test-header: only-for-test'
    
{
    "args": {
        "test": "abcd1",
        "user": "dylon"
    },
    "headers": {
        "Test-Header": "only-for-test",
        "with": "more"
    },
    "origin": "127.0.0.1",
    "url": "http://127.0.0.1/get?test=abcd1&user=dylon"
}

# Reject the request and rewrite the status code and response header
curl -XGET '127.0.0.1:9080/get?test=abcd&user=alice' \
    --header 'test-header: only-for-test'

HTTP/1.1 302 Moved Temporarily
Date: Mon, 20 Dec 2021 09:37:35 GMT
Content-Type: text/html
Content-Length: 142
Connection: keep-alive
Location: http://example.com/auth
Server: APISIX/2.11.0

# Reject the request and return the custom response header
curl -XGET '127.0.0.1:9080/get?test=abcd&user=bob' \
    --header 'test-header: only-for-test'

HTTP/1.1 403 Forbidden
Date: Mon, 20 Dec 2021 09:38:27 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 150
Connection: keep-alive
abce: test
test: abcd
Server: APISIX/2.11.0

# Reject the request and return a custom response (string)
curl -XGET '127.0.0.1:9080/get?test=abcd&user=carla' \
    --header 'test-header: only-for-test'

HTTP/1.1 403 Forbidden
Date: Mon, 20 Dec 2021 09:38:58 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.11.0

Give you a string reason

# Reject the request and return a custom response (JSON)
curl -XGET '127.0.0.1:9080/get?test=abcd&user=dylon' \
    --header 'test-header: only-for-test'

HTTP/1.1 403 Forbidden
Date: Mon, 20 Dec 2021 09:42:12 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.11.0

{"code":40001,"desc":"Give you a object reason"}

Add: close plug-in

Thanks to the dynamic characteristics of Apache apisik, you can close the OPA plug-in on the route by removing the relevant configuration of the OPA plug-in in the route configuration and saving it.

summary

This article describes the detailed operation steps of the docking between Apache APIs IX and Open Policy Agent. I hope this article can give you a clearer understanding of the use of Open Policy Agent in Apache APIs IX and facilitate subsequent practical operation.

Apache APISIX is not only committed to maintaining its high performance, but also attaches great importance to the construction of open source ecology. At present, Apache APISIX has 10 + authentication and authorization related plug-ins, which support docking with the mainstream authentication and authorization services in the industry.

If you have the need to connect with other authentication and authorization, you may wish to visit Apache APIs IX's GitHub , leave your suggestions through issue; Or subscribe to Apache APIs IX mailing list , express your thoughts by email.

Keywords: Java Apache gateway

Added by itandme on Wed, 23 Feb 2022 11:56:10 +0200