Gate: Open Policy Agent Evaluator
This plugin supports all intercept modes (request
, response
, request_response
)
This plugin embeds an Open Policy Agent engine into Gate and restricts access to specific HTTP resources based on OPA policy evaluations. To evaluate an OPA policy you need two pieces of input:
- The Rego policy
- Input data, passed to the Rego policy as the special
input
object
When it comes to policy distribution, the plugin currently supports two different methods to distribute policies.
The first is to inline policies, this approach works best when you have a limited number of policies and performance is really important.
The second approach is to use a remote bundle. The remote bundle can be pulled from any remote host, including the SlashID distribution hub.
Policy input object example
As mentioned, the input option is the second ingredient necessary for OPA. The plugin passes the follow input format to OPA.
Note that this format is compatible with OPA-Envoy, so you can reuse your existing OPA policies with Gate.
The following is an example of input
object Gate makes available to Rego policies during evaluation in its current Version 1 format:
{
"version": {
"gate": "v1.1"
},
"request": {
"http": {
"headers": {
"Accept": [
"application/json, text/plain, */*"
],
"Accept-Encoding": [
"gzip, compress, deflate, br"
],
"Authorization": [
"Bearer eyJhb..."
],
"Cookie": [
"foo=bar"
]
"User-Agent": [
"axios/1.3.4"
]
},
"cookies": {
"foo": "bar"
}
"host": "example.com",
"method": "GET",
"path": "/some/path",
"protocol": "HTTP/1.1",
"query": "option=value",
"scheme": "https",
"url": "https://example.com/some/path?option=value"
},
"parsed_path": [
"some",
"path"
],
"parsed_query": {
"option": [
"value"
]
},
"parsed_token": {
"header": {
"alg": "RS256",
"kid": "pYsNGA"
},
"payload": {
...
},
"signature": "JvVt..."
},
"time": "2023-04-09T18:38:41.117405838Z",
"token": "eyJh..."
}
}
Note that if the plugin is configured to execute on responses as well then the input object contains both the request and response objects. The request is the same as the object shown above. The whole input object looks as follows:
{
"version": {
"gate": "v1.1"
},
"request": {
"http": {
...
}
},
"response": {
"http": {
"contentType": "application/json"
"status": 200
"body": "{}"
"headers": {
"Accept": [
"application/json, text/plain, */*"
],
"Accept-Encoding": [
"gzip, compress, deflate, br"
],
"Authorization": [
"Bearer eyJhb..."
],
"User-Agent": [
"axios/1.3.4"
]
},
},
"time": "2023-04-09T18:38:46.117405838Z",
"parsed_path": [
"some",
"path"
],
"parsed_query": {
"option": [
"value"
]
},
}
}
The output of an evaluation is expected to be a boolean to be found at the location specified in the policy_decision_path
plugin parameter.
Configuring Gate
- Environment variables
- HCL
- JSON
- TOML
- YAML
GATE_PLUGINS_<PLUGIN NUMBER>_TYPE=opa
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_HEADER_WITH_TOKEN=<Header with token>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_COOKIE_WITH_TOKEN=<Cookie with token>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_SLASHID_BASE_URL=<SlashID base URL>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_POLICY=<Embedded Rego policy>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_POLICY_BUNDLE_URL=<URL of a remote OPA bundle>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_POLICY_DECISION_PATH=<Location of the policy evaluation decision>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_MONITORING_MODE=<boolean - Run the plugin in monitoring mode or enforcement mode. Default is enforcementn>
In the Environment variables configuration, <PLUGIN NUMBER>
defined plugin execution order.
gate = {
plugins = [
// ...
{
type = "opa"
parameters = {
header_with_token = <Header with token>
cookie_with_token = <Cookie with token>
policy = "<Embedded Rego policy>"
policy_bundle_url = "<URL of a remote OPA bundle>"
policy_decision_path = "<Location of the policy evaluation decision>"
monitoring_mode = "<Monitoring mode>"
}
}
// ...
]
}
{
"gate": {
"plugins": [
// ...
{
"type": "opa",
"parameters": {
"header_with_token": "<Header with token>",
"cookie_with_token": "<Cookie with token>",
"policy": "<Embedded Rego policy>",
"policy_bundle_url": "<URL of a remote OPA bundle>",
"policy_decision_path": "<Location of the policy evaluation decision>"
"monitoring_mode": "<Monitoring mode>"
}
}
// ...
]
}
}
[[gate.plugins]]
type = "opa"
parameters.header_with_token = "<Header with token>"
parameters.cookie_with_token = "<Cookie with token>"
parameters.policy = "<Embedded Rego policy>"
parameters.policy_bundle_url = "<URL of a remote OPA bundle>"
parameters.policy_decision_path = "<Location of the policy evaluation decision>"
parameters.monitoring_mode = "<Monitoring mode>"
gate:
plugins:
// ...
- type: opa
parameters:
header_with_token: <Header with token>
cookie_with_token: <Cookie with token>
policy: <Embedded Rego policy>
policy_bundle_url: <URL of a remote OPA bundle>
policy_decision_path: <Location of the policy evaluation decision>
monitoring_mode: <Monitoring mode>
// ...
where:
<Header with token>
is the request header containing the token, if any. This option andcookie_with_token
are mutually exclusive.<Cookie with token>
is the request cookie containing the token, if any. This option andheader_with_token
are mutually exclusive.<Embedded Rego policy>
a Rego policy you can inline directly in Gate's configuration to accept or deny incoming requests. This option is mutually exclusive withpolicy_bundle_url
.<URL of a remote OPA bundle>
location of a policy and data OPA bundle built withopa build
Gate will fetch periodically to gather updated policies and data. This option is mutually exclusive with the embeddedpolicy
option.<Location of the policy evaluation decision>
a Rego policy decision path to a boolean value: iftrue
the request is granted, otherwise it's rejected with a 403 status.<Monitoring mode>
a boolean indicating whether to run the plugin in monitoring mode or enforcement mode. Iftrue
the plugin runs in monitoring mode, by default it isfalse
(enforcement mode).
If neither <Header with token>
nor <Cookie with token>
are set, the plugin attempts to get a bearer token from the Authorization
header, and strips the Bearer
prefix from it.
Disabling plugin for specific URLs
You can enable or disable this plugin for specific URLs by using the enabled
option in the URLs configuration.
- Environment variables
- HCL
- JSON
- TOML
- YAML
GATE_URLS_0_PATTERN=svc-example.com/*
GATE_URLS_0_TARGET=http://example:8080
GATE_URLS_1_PATTERN=svc-another-example.com/
GATE_URLS_1_TARGET=https://another-example:8080
gate = {
urls = [
{
pattern = "svc-example.com/*"
target = "http://example:8080"
},
{
pattern = "svc-another-example.com/"
target = "https://another-example:8080"
}
]
// ...
}
{
"gate": {
"urls": [
{
"pattern": "svc-example.com/*",
"target": "http://example:8080",
},
{
"pattern": "svc-another-example.com/",
"target": "https://another-example:8080"
}
],
// ...
URL are matched in the order they are defined in the configuration file.
[[gate.urls]]
pattern = "svc-example.com/*"
target = "http://example:8080"
[[gate.urls]]
pattern = "svc-another-example.com/"
target = "https://another-example:8080"
URL are matched in the order they are defined in the configuration file.
gate:
urls:
- pattern: svc-example.com/*
target: http://example:8080
- pattern: svc-another-example.com/
target: https://another-example:8080
URL are matched in the order they are defined in the configuration file.