Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

injection opa result as header, local integrasion test pass #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kong_api_authz/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM kong-docker-kong-gateway-docker.bintray.io/kong-enterprise-edition:2.3.2.0-alpine
FROM kong:2.3-alpine

LABEL org.wada.name="openpolicyagent/demo-kong-plugin-opa"
LABEL org.wada.description="Kong image with kong-plugin-opa installed"
Expand Down
6 changes: 6 additions & 0 deletions kong_api_authz/integration/docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ services:
- httpbin

kong:
build: ..
volumes:
# Import declarative configuration
- ./testdata/kong-test.yml:/usr/local/kong/declarative/kong.yml:ro
environment:
# Switch to DB-less mode for integration tests
KONG_DATABASE: "off"
KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong.yml
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: '0.0.0.0:8001'
KONG_LOG_LEVEL: debug


opa:
working_dir: /bundle
Expand Down
10 changes: 5 additions & 5 deletions kong_api_authz/integration/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ services:
# Kong instance
kong:
build: ..
volumes:
# Import declarative configuration
- ./testdata/kong-test.yml:/usr/local/kong/declarative/kong.yml:ro
environment:
KONG_DATABASE: "off"
KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong.yml
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: '0.0.0.0:8001'
KONG_DATABASE: postgres
KONG_LOG_LEVEL: debug
KONG_PG_DATABASE: kong
KONG_PG_HOST: db
KONG_PG_PASSWORD: kong
KONG_PG_USER: kong
# add kong-plugin-opa to the list of plugins that come bundled with Kong
KONG_PLUGINS: bundled,opa
ports:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@ package httpapi.authz
# Deny access by default
default allow = false

# Mock baggage object
default baggage = {
"baggage" : "TEST"
}

# Allows admin to access '/status' endpoints
allow {
input.method == "GET"
glob.match("/status**", ["/"], input.path)
input.token.payload.role == "admin"
}
}

# Allows to access '/baggage' endpoints and return user baggage
allow = baggage {
input.method == "GET"
glob.match("/headers**", ["/"], input.path)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"info": {
"_postman_id": "73199a0d-207c-49f6-a940-287e31edd3de",
"_postman_id": "6e2a2eb5-2384-4500-85d1-3e9638a1de5b",
"name": "kong-plugin-opa.integration_tests",
"description": "Collection of integration tests for the kong-plugins-opa.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
Expand All @@ -12,7 +12,6 @@
{
"listen": "test",
"script": {
"id": "c521e4b5-b2ca-43f9-a358-43c0b5e59d7d",
"exec": [
"pm.test(\"Status code is 403\", function () {\r",
" pm.response.to.have.status(403);\r",
Expand All @@ -24,7 +23,6 @@
{
"listen": "prerequest",
"script": {
"id": "c3bd7e6d-ecb7-4714-bdd5-42dc89289925",
"exec": [
""
],
Expand Down Expand Up @@ -66,7 +64,6 @@
{
"listen": "test",
"script": {
"id": "c521e4b5-b2ca-43f9-a358-43c0b5e59d7d",
"exec": [
"pm.test(\"Status code is 403\", function () {\r",
" pm.response.to.have.status(403);\r",
Expand All @@ -78,7 +75,6 @@
{
"listen": "prerequest",
"script": {
"id": "c3bd7e6d-ecb7-4714-bdd5-42dc89289925",
"exec": [
""
],
Expand Down Expand Up @@ -132,7 +128,6 @@
{
"listen": "test",
"script": {
"id": "c521e4b5-b2ca-43f9-a358-43c0b5e59d7d",
"exec": [
"pm.test(\"Status code is 200\", function () {\r",
" pm.response.to.have.status(200);\r",
Expand All @@ -144,7 +139,6 @@
{
"listen": "prerequest",
"script": {
"id": "c3bd7e6d-ecb7-4714-bdd5-42dc89289925",
"exec": [
"// Base 63 URL encoding ",
"// from https://www.jonathan-petitcolas.com/2014/11/27/creating-json-web-token-in-javascript.html",
Expand Down Expand Up @@ -228,13 +222,112 @@
},
"response": []
},
{
"name": "Test Bearer Token with Allowed Role with baggage",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"baggage header is attach to request\", function () {\r",
" console.log(pm.response.text())\r",
" pm.expect(pm.response.text()).to.include(\"Baggage\");\r",
"});"
],
"type": "text/javascript"
}
},
{
"listen": "prerequest",
"script": {
"exec": [
"// Base 63 URL encoding ",
"// from https://www.jonathan-petitcolas.com/2014/11/27/creating-json-web-token-in-javascript.html",
"function base64url(source) {",
"",
" // Encode in classical base64",
" var encodedSource = CryptoJS.enc.Base64.stringify(source);",
"",
" // Remove padding equal characters",
" encodedSource = encodedSource.replace(/=+$/, '');",
"",
" // Replace characters according to base64url specifications",
" encodedSource = encodedSource.replace(/\\+/g, '-');",
" encodedSource = encodedSource.replace(/\\//g, '_');",
"",
" return encodedSource;",
"}",
"",
"// set algorithm & token type",
"var header = {",
" \"alg\": \"HS256\",",
" \"typ\": \"JWT\"",
"};",
"",
"// set data",
"var payload = {",
" \"sub\": \"1234567890\",",
" \"name\": \"John Doe\",",
" \"iat\": Math.floor(Date.now() / 1000), // issued now",
" \"role\": pm.environment.get(\"allowed_role\") // valid role to access status endpoint",
"}",
"",
"// encode header and payload",
"var encodedHeader = base64url(CryptoJS.enc.Utf8.parse(JSON.stringify(header)))",
"var encodedPayload = base64url(CryptoJS.enc.Utf8.parse(JSON.stringify(payload)))",
"",
"// create token",
"var token = encodedHeader + '.' + encodedPayload ",
"",
"// generate verify signature",
"var signature = base64url(CryptoJS.HmacSHA256(token, 'secret'))",
"",
"pm.variables.set('token', token + \".\" + signature)"
],
"type": "text/javascript"
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{token}}",
"type": "string"
}
]
},
"method": "GET",
"header": [
{
"key": "Host",
"value": "{{route_host}}",
"type": "text"
}
],
"url": {
"raw": "http://{{kong_host}}:{{kong_port}}/headers",
"protocol": "http",
"host": [
"{{kong_host}}"
],
"port": "{{kong_port}}",
"path": [
"headers"
]
},
"description": "Test the plugin with a Token that has a role allowed to access the service"
},
"response": []
},
{
"name": "Test Bearer Token with Forbidden Role",
"event": [
{
"listen": "test",
"script": {
"id": "a4a4a5ff-dc29-48e3-a392-1cd5c8e3b254",
"exec": [
"pm.test(\"Status code is 403\", function () {\r",
" pm.response.to.have.status(403);\r",
Expand All @@ -246,7 +339,6 @@
{
"listen": "prerequest",
"script": {
"id": "2b9db012-dc62-44ee-9a18-4c6fd2e54b66",
"exec": [
"// Base 63 URL encoding ",
"// from https://www.jonathan-petitcolas.com/2014/11/27/creating-json-web-token-in-javascript.html",
Expand Down Expand Up @@ -335,7 +427,6 @@
{
"listen": "prerequest",
"script": {
"id": "82ac6756-c2d9-44e2-9b69-8124ecb14a98",
"type": "text/javascript",
"exec": [
""
Expand All @@ -345,13 +436,11 @@
{
"listen": "test",
"script": {
"id": "3a3fbb08-62e2-4843-924c-20c7cbe6c995",
"type": "text/javascript",
"exec": [
""
]
}
}
],
"protocolProfileBehavior": {}
]
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
rockspec_format = "3.0"
package = "kong-plugin-opa"
version = "0.1.1-3"
version = "0.1.1-4"
source = {
url = "git+https://github.com/open-policy-agent/contrib.git",
tag = "v0.1.1",
Expand Down
4 changes: 4 additions & 0 deletions kong_api_authz/spec/__mocks__/resty/http.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ function _M.request_uri(self, uri, params)
-- when the document does not evaluate to true,
-- the response will not contain the result property
res.body = '{}'
elseif (params.body:find("/baggage")) then
-- return baggage from opa as string
-- the response will contain baggage property
res.body = '{ "result": { "baggage": "BASE64_JWT_INTERNAL" } }'
else
-- when the document evaluates to true,
-- an element is produced in the result
Expand Down
17 changes: 17 additions & 0 deletions kong_api_authz/src/kong/plugins/opa/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ local function getDocument(input, conf)
return assert(cjson_safe.decode(res.body))
end

local function inject_header(key, value)
assert(type(key) == "string", "header key is not a string")
assert(type(value) == "string", "header value is not a string")
kong.service.request.set_header(key , value)
end

-- module
local _M = {}

Expand Down Expand Up @@ -71,6 +77,17 @@ function _M.execute(conf)
return kong.response.exit(403, [[{"message":"Access Forbidden"}]])
end

-- inject baggage
if type(res.result) == "table" then
local baggage_key = conf.policy.baggage_key_in_result
if res.result[baggage_key] ~= nil then
inject_header(baggage_key,res.result[baggage_key])
kong.log.debug(interp("Baggage header injected ${baggage}", {
baggage = res.result[baggage_key]
}))
end
end

-- access allowed
kong.log.debug(interp("Access allowed to ${method} ${path} for user ${subject}", {
method = input.method,
Expand Down
6 changes: 6 additions & 0 deletions kong_api_authz/src/kong/plugins/opa/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ return {
required = true
},
},
{
baggage_key_in_result = {
type = "string",
default = "baggage"
},
},
},
},
},
Expand Down