Skip to content

Proposal: support OpenPolicyAgent for access control #5714

Description

@bzp2010

Background

OPA is an open source lightweight general-purpose policy engine, which is a full-featured policy engine that can replace the built-in policy module in your software and decouple the service from the policy engine.
It describes policies through a policy DSL language "Rego" and stores policy data through JSON, after which the user can send a query request and OPA will combine the policy with the data and the query request entered by the user to generate policy decisions.
image
Users can easily integrate OPA with its services, such as program libraries, HTTP API, etc. In this plugin, we will integrate OPA using HTTP API.

Test Environment

# Run the OPA throught Docker
docker run -d --name opa -p 8181:8181 openpolicyagent/opa:0.35.0 run -s

# Create policy 'example'
curl -XPUT 'localhost:8181/v1/policies/example' \
--header 'Content-Type: text/plain' \
--data-raw 'package example

default allow = false

allow {
  input.request.http.headers["test-header"] == "only-for-test"
}'

# Test: success
curl -XPOST 'localhost:8181/v1/data/example/allow' \
--header 'Content-Type: application/json' \
--data-raw '{
  "input": {
    "request": {
      "http": {
        "headers": {
          "test-header": "only-for-test"
        }
      }
    }
  }
}'

{
    "result": true
}

# Test: failed
curl -XPOST 'localhost:8181/v1/data/example/allow' \
--header 'Content-Type: application/json' \
--data-raw '{
  "input": {
    "request": {
      "http": {
        "headers": {
          "test-header": "not-for-test"
        }
      }
    }
  }
}'

{
    "result": false
}

Solutions

Configure schema

Name Type Requirement Default Description
host string required OPA host (eg. https://localhost:8181)
ssl_verify boolean optional true Whether to verify the certificate
package string required   Policy package
decision string required   Policy rule name

More functions (Need more discuss)

Name Type Requirement Default Description
with_route boolean optional false Carry current Route information in OPA API requests
with_consumer boolean optional false Carry current Consumer information in OPA API requests
with_upstream boolean optional false Carry current Upstream information in OPA API requests

Implemention

Create a plugin that encodes the request information as JSON during the access execution phase, sends it to the OPA Data API and gets the response, decides whether to overwrite the response and terminates the request processing accordingly.
We provide a standard OPA response body specification, and the parts that conform to it will be parsed by APISIX. (complex response as follows)

## Requests like this `https://apisix.apache.org/contribute?abc=123`
{
  "input": {
    "request": {
      "http": { # for HTTP subsystem(maybe can used by Stream subsystem also)
        "host": "apisix.apache.org",
        "port": "443",
        "tls": {},
        "method": "GET",
        "scheme": "https",
        "path": "/contribute",
        "query": {
          "abc" : "123"
        },
        "headers": {
          "accept-encoding": "gzip, deflate"
        }
      }
    },
    "remote_addr": "127.0.0.1",
    "upstream": {},
    "route": {},
    "consumer": {}
  }
}

## Simply decision response from OPA 
{
    "result": true | false
}

## Complex decision response from OPA (supports overwriting responses and terminating request processing)
{
    "result": {
        "allow": true | false,
        "headers":{
            "opa": "forbidden"
        },
        "statusCode": 403,
        "body": "You are not authorized to access."
    }
}

Roadmap

The plugin implementation will follow the following roadmap, splitting into different PRs for submission.

  1. Implement MVP: Supports sending request information to OPA and processing the request with a simple response
  2. Support OPA complex response with response overwrite
  3. Support sending routing, upstream and other information to OPA to assist in policy determination

Other

What are your ideas?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions