Skip to content

Commit

Permalink
feat: add opa plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
bzp2010 committed Dec 8, 2021
1 parent b85ebd4 commit 51ea55f
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 4 deletions.
17 changes: 13 additions & 4 deletions apisix/core/request.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ local io = require("apisix.core.io")
local ngx = ngx
local get_headers = ngx.req.get_headers
local clear_header = ngx.req.clear_header
local tonumber = tonumber
local error = error
local type = type
local str_fmt = string.format
local tonumber = tonumber
local error = error
local type = type
local str_fmt = string.format
local str_lower = string.lower
local req_read_body = ngx.req.read_body
local req_get_body_data = ngx.req.get_body_data
Expand Down Expand Up @@ -269,6 +269,15 @@ function _M.get_port(ctx)
end


function _M.get_path(ctx, original)
if not ctx then
ctx = ngx.ctx.api_ctx
end

return ctx.var.uri or ''
end


function _M.get_http_version()
return ngx.req.http_version()
end
Expand Down
104 changes: 104 additions & 0 deletions apisix/plugins/opa.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements. See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You 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.
--

local core = require("apisix.core")
local http = require("resty.http")
local helper = require("apisix.plugins.opa.helper")

local schema = {
type = "object",
properties = {
host = {type = "string"},
ssl_verify = {
type = "boolean",
default = true,
},
package = {type = "string"},
decision = {type = "string", maxLength = 256},
timeout = {
type = "integer",
minimum = 1,
maximum = 60000,
default = 3000,
description = "timeout in milliseconds",
},
keepalive = {type = "boolean", default = true},
keepalive_timeout = {type = "integer", minimum = 1000, default = 60000},
keepalive_pool = {type = "integer", minimum = 1, default = 5}
},
required = {"host", "package", "decision"}
}


local _M = {
version = 0.1,
priority = 2001,
name = "opa",
schema = schema,
}


function _M.check_schema(conf)
local ok, err = core.schema.check(schema, conf)
if not ok then
return false, err
end

return true
end


function _M.access(conf, ctx)
local body = helper.build_opa_input(conf, ctx, "http")
local params = {
method = "POST",
body = body,
headers = {
["Content-Type"] = "application/json",
},
keepalive = conf.keepalive,
ssl_verify = conf.ssl_verify
}

if conf.keepalive then
params.keepalive_timeout = conf.keepalive_timeout
params.keepalive_pool = conf.keepalive_pool
end

local endpoint = conf.host .. "/v1/data/" .. conf.package .. "/" .. conf.decision

local httpc = http.new()
httpc:set_timeout(conf.timeout)

local res, err = httpc:request_uri(endpoint, params)

-- block by default when decision is unavailable
if not res or err then
core.log.error("failed to process OPA decision, err: ", err)
return 403
end

-- parse the results of the decision
local ret = core.json.decode(res.body).result

if not ret then
return 403
end
end


return _M
62 changes: 62 additions & 0 deletions apisix/plugins/opa/helper.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements. See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You 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.
--

local core = require("apisix.core")
local ngx_var = ngx.var
local ngx_time = ngx.time

local _M = {}


local function build_var(conf, ctx)
return {
server_addr = ngx_var.server_addr,
server_port = ngx_var.server_port,
remote_addr = ngx_var.remote_addr,
remote_port = ngx_var.remote_port,
timestamp = ngx_time(),
}
end


local function build_http_request(conf, ctx)
return {
scheme = core.request.get_scheme(ctx),
method = core.request.get_method(ctx),
host = core.request.get_host(ctx),
port = core.request.get_port(ctx),
path = core.request.get_path(ctx, true),
header = core.request.headers(ctx),
query = core.request.get_uri_args(ctx),
}
end


function _M.build_opa_input(conf, ctx, subsystem)
local request = build_http_request(conf, ctx)

local data = {
type = subsystem,
request = request,
var = build_var(conf, ctx)
}

return core.json.encode({input = data})
end


return _M

0 comments on commit 51ea55f

Please sign in to comment.