Skip to content
Merged
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
21 changes: 21 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "emmylua_new",
"request": "launch",
"name": "EmmyLua New Debug",
"host": "localhost",
"port": 9966,
"ext": [
".lua",
".lua.txt",
".lua.bytes"
],
"ideConnectDebugger": true,
}
]
}
4 changes: 3 additions & 1 deletion BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

## Features

- [ ] Add retry attempts
- [x] Add retry attempts
- [ ] Add caching capability

## Improvements

- [ ] Add live tests to the OpenFGA server addition to the mock server.
- [ ] Add an example that uses Consumer in conjunction with the Basic Authentication plugin.
- [ ] Add build, test, and deploy pipeline (GitHub Actions) to the project
- [ ] Add GitHub action to perform a smoke test
- [ ] Add GitHub action to publish .rock when a version was tagged. Use LUAROCKS_API_KEY secret.

## Cleanup

Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Initial implementation of plugin
- Added GitHub action build for linting and unit testing
- Added function to handle unexpected errors and exit the plugin
- Added function to make FGA requests with retry logic
- Added unit tests to mock HTTP requests and return different responses based on call count
- Added support for EMMY Debugger with configurable host and port

### Changed

- Extracted `kong.response.exit(500, "An unexpected error occurred")` to its own function
- Extracted the code inside the `repeat ... until` loop into its own function
- Modified `make_fga_request` to return a boolean indicating allow/deny

### Fixed

### Removed
Expand Down
32 changes: 26 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,31 @@ DOCKER_NO_CACHE :=

BUILDKIT_PROGRESS :=

# Busted runtime profile
BUSTED_RUN_PROFILE := default
BUSTED_FILTER :=

# Busted exclude tags
BUSTED_EXCLUDE_TAGS := postgres
BUSTED_NO_KEEP_GOING := false
BUSTED_COVERAGE := false
BUSTED_EMMY_DEBUGGER := false

BUSTED_EMMY_DEBUGGER_ENABLED_ARGS =

BUSTED_ARGS = --config-file $(DOCKER_MOUNT_IN_CONTAINER)/.busted --run '$(BUSTED_RUN_PROFILE)' --exclude-tags='$(BUSTED_EXCLUDE_TAGS)' --filter '$(BUSTED_FILTER)'
ifdef BUSTED_NO_KEEP_GOING
ifneq ($(BUSTED_NO_KEEP_GOING), false)
BUSTED_ARGS += --no-keep-going
endif

ifneq ($(BUSTED_COVERAGE), false)
BUSTED_ARGS += --coverage
endif

ifneq ($(BUSTED_EMMY_DEBUGGER), false)
BUSTED_EMMY_DEBUGGER_ENABLED_ARGS = -e BUSTED_EMMY_DEBUGGER='/usr/local/lib/lua/5.1/emmy_core.so'
endif

KONG_SMOKE_TEST_DEPLOYMENT_PATH := _build/deployment/kong-smoke-test

CONTAINER_CI_KONG_TOOLING_IMAGE_PATH := _build/images/kong-tooling
Expand Down Expand Up @@ -82,10 +92,10 @@ CONTAINER_CI_OPENFGA_MIGRATION := $(DOCKER) run $(DOCKER_RUN_FLAGS) \
migrate --verbose

CONTAINER_CI_OPENFGA_RUN := $(DOCKER) run -d $(DOCKER_RUN_FLAGS) \
-p '8080:8080' \
-p '8081:8081' \
-p '3000:3000' \
-p '2112:2112' \
-p 8080:8080 \
-p 8081:8081 \
-p 3000:3000 \
-p 2112:2112 \
-e OPENFGA_DATASTORE_ENGINE=sqlite \
-e OPENFGA_DATASTORE_URI=file:/data/openfga.sqlite \
-e OPENFGA_DATASTORE_MAX_OPEN_CONNS=100 \
Expand Down Expand Up @@ -124,6 +134,7 @@ CONTAINER_CI_KONG_TOOLING_BUILD = DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=$(BUILDKIT
--build-arg PONGO_KONG_VERSION='$(PONGO_KONG_VERSION)' \
--build-arg PONGO_ARCHIVE='$(PONGO_ARCHIVE)' \
--build-arg STYLUA_VERSION='$(STYLUA_VERSION)' \
--build-arg EMMY_LUA_DEBUGGER_VERSION='$(EMMY_LUA_DEBUGGER_VERSION)' \
.

CONTAINER_CI_KONG_SMOKE_TEST_BUILD = DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=$(BUILDKIT_PROGRESS) $(DOCKER) build \
Expand All @@ -139,12 +150,20 @@ CONTAINER_CI_KONG_SMOKE_TEST_BUILD = DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=$(BUILD
.

CONTAINER_CI_KONG_TOOLING_RUN := MSYS_NO_PATHCONV=1 $(DOCKER) run $(DOCKER_RUN_FLAGS) \
-v '$(PWD):$(DOCKER_MOUNT_IN_CONTAINER)' \
-p 9966:9966 \
-e KONG_SPEC_TEST_REDIS_HOST='$(CONTAINER_CI_REDIS_NAME)' \
-e KONG_SPEC_TEST_LIVE_HOSTNAME='$(CONTAINER_CI_OPENFGA_NAME)' \
-e KONG_LICENSE_PATH=$(DOCKER_MOUNT_IN_CONTAINER)/kong-license.json \
-e KONG_DNS_ORDER='LAST,A,SRV' \
-e BUSTED_EMMY_DEBUGGER_HOST='0.0.0.0' \
-e BUSTED_EMMY_DEBUGGER_PORT='9966' \
-e BUSTED_EMMY_DEBUGGER_SOURCE_PATH='/usr/local/share/lua/5.1/kong/plugins:/usr/local/share/lua/5.1/kong/enterprise_edition' \
-e BUSTED_EMMY_DEBUGGER_SOURCE_PATH_MAPPING='$(DOCKER_MOUNT_IN_CONTAINER);$(PWD):/usr/local/share/lua/5.1;$(PWD)/.luarocks:/usr/local/openresty/lualib;$(PWD)/.luarocks' \
$(BUSTED_EMMY_DEBUGGER_ENABLED_ARGS) \
--network='$(CONTAINER_CI_NETWORK_NAME)' \
-v '$(PWD):$(DOCKER_MOUNT_IN_CONTAINER)' \
-v '$(PWD)/_build/debugger/emmy_debugger.lua:/usr/local/share/lua/5.1/kong/tools/emmy_debugger.lua' \
-v '$(PWD)/_build/debugger/busted:/kong/bin/busted' \
'$(CONTAINER_CI_KONG_TOOLING_IMAGE_NAME)'

CONTAINER_CI_KONG_SMOKE_TEST_RUN_SERVER_NAME = kong-plugin-$(KONG_PLUGIN_NAME)-smoke-test
Expand Down Expand Up @@ -308,6 +327,7 @@ lua-language-server-add-kong: container-ci-kong-tooling
-mkdir -p .luarocks
$(CONTAINER_CI_KONG_TOOLING_RUN) cp -rv /usr/local/share/lua/5.1/. $(DOCKER_MOUNT_IN_CONTAINER)/.luarocks
$(CONTAINER_CI_KONG_TOOLING_RUN) cp -rv /kong $(DOCKER_MOUNT_IN_CONTAINER)/.luarocks
$(CONTAINER_CI_KONG_TOOLING_RUN) cp -rv /usr/local/openresty/lualib/. $(DOCKER_MOUNT_IN_CONTAINER)/.luarocks

.PHONY: clean-test-results
clean-test-results:
Expand Down
70 changes: 52 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ Below is the example configuration one might use in `declarative_config`:
port: 1234
https: true
https_verify: true
max_attempts: 3
failed_attempts_backoff_timeout: 1000
timeout: 10000
keepalive: 60000
store_id: "your_store_id"
Expand All @@ -72,24 +74,26 @@ Below is the example configuration one might use in `declarative_config`:

## Configuration

| Property | Default value | Description |
| ------------------------------------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `host`<br/>_required_<br/><br/>**Type:** hostname (string) | - | Hostname of the OpenFGA server |
| `port`<br/>_required_<br/><br/>**Type:** port (number) | 8080 | HTTP API port of OpenFGA |
| `https`<br/>_optional_<br/><br/>**Type:** boolean | false | Use HTTPS to connect to OpenFGA |
| `https_verify`<br/>_optional_<br/><br/>**Type:** boolean | false | Verify HTTPS certificate |
| `timeout`<br/>_optional_<br/><br/>**Type:** number | 10000 | The total timeout time in milliseconds for a request and response cycle. |
| `keepalive`<br/>_optional_<br/><br/>**Type:** number | 60000 | The maximal idle timeout in milliseconds for the current connection. See [tcpsock:setkeepalive](https://github.com/openresty/lua-nginx-module#tcpsocksetkeepalive) for more details. |
| `store_id`<br/>_required_<br/><br/>**Type:** string | - | The store ID in OpenFGA |
| `model_id`<br/>_optional_<br/><br/>**Type:** string | - | Optional model ID (version). Latest is used if this is empty |
| `api_token`<br/>_optional_<br/><br/>**Type:** string | - | Optional API token |
| `api_token_issuer`<br/>_optional_<br/><br/>**Type:** string | - | API token issuer |
| `api_audience`<br/>_optional_<br/><br/>**Type:** string | - | API audience |
| `api_client_id`<br/>_optional_<br/><br/>**Type:** string | - | API client ID |
| `api_client_secret`<br/>_optional_<br/><br/>**Type:** string | - | API client secret |
| `api_token_cache`<br/>_optional_<br/><br/>**Type:** number | 600 | API token cache duration in seconds |
| `tuple`<br/>_required_<br/><br/>**Type:** record | - | Tuple key for authorization |
| `contextual_tuples`<br/>_optional_<br/><br/>**Type:** set | {} | Set of contextual tuples for authorization |
| Property | Default value | Description |
| --------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `host`<br/>_required_<br/><br/>**Type:** hostname (string) | - | Hostname of the OpenFGA server |
| `port`<br/>_required_<br/><br/>**Type:** port (number) | 8080 | HTTP API port of OpenFGA |
| `https`<br/>_optional_<br/><br/>**Type:** boolean | false | Use HTTPS to connect to OpenFGA |
| `https_verify`<br/>_optional_<br/><br/>**Type:** boolean | false | Verify HTTPS certificate |
| `max_attempts`<br/>_optional_<br/><br/>**Type:** integer | 3 | The maximum number of attempts to make when querying OpenFGA. This is useful for handling transient errors and retries. |
| `failed_attempts_backoff_timeout`<br/>_optional_<br/><br/>**Type:** integer | 1000 | The backoff timeout in milliseconds between retry attempts when querying OpenFGA. This helps to avoid overwhelming the server with rapid retries. Formula: `failed_attempts_backoff_timeout * 2 ^ (attempts - 1) / 1000` |
| `timeout`<br/>_optional_<br/><br/>**Type:** number | 10000 | The total timeout time in milliseconds for a request and response cycle. |
| `keepalive`<br/>_optional_<br/><br/>**Type:** number | 60000 | The maximal idle timeout in milliseconds for the current connection. See [tcpsock:setkeepalive](https://github.com/openresty/lua-nginx-module#tcpsocksetkeepalive) for more details. |
| `store_id`<br/>_required_<br/><br/>**Type:** string | - | The store ID in OpenFGA |
| `model_id`<br/>_optional_<br/><br/>**Type:** string | - | Optional model ID (version). Latest is used if this is empty |
| `api_token`<br/>_optional_<br/><br/>**Type:** string | - | Optional API token |
| `api_token_issuer`<br/>_optional_<br/><br/>**Type:** string | - | API token issuer |
| `api_audience`<br/>_optional_<br/><br/>**Type:** string | - | API audience |
| `api_client_id`<br/>_optional_<br/><br/>**Type:** string | - | API client ID |
| `api_client_secret`<br/>_optional_<br/><br/>**Type:** string | - | API client secret |
| `api_token_cache`<br/>_optional_<br/><br/>**Type:** number | 600 | API token cache duration in seconds |
| `tuple`<br/>_required_<br/><br/>**Type:** record | - | Tuple key for authorization |
| `contextual_tuples`<br/>_optional_<br/><br/>**Type:** set | {} | Set of contextual tuples for authorization |

## Plugin version

Expand Down Expand Up @@ -149,6 +153,36 @@ make lint
make test-unit
```

| Runtime configuration | Description |
| --------------------- | ------------------------------------------------------------------------------------------------- |
| BUSTED_NO_KEEP_GOING | When set to `true`, `busted` will stop running tests after the first failure. Default is `false`. |
| BUSTED_COVERAGE | When set to `true`, `busted` will generate a code coverage report. Default is `false`. |
| BUSTED_EMMY_DEBUGGER | When set to `true`, enables the EMMY Lua debugger for `busted` tests. Default is `false`. |

#### Run test with EMMY Debugger

##### Prerequisites

- Install the [EmmyLua](https://marketplace.visualstudio.com/items?itemName=tangzx.emmylua) extension in VS Code

##### Usage

1. Start your tests with debugging enabled:

`make test-unit BUSTED_EMMY_DEBUGGER=true`

2. In VS Code:
- Set breakpoints in your Lua code
- Start the debugger using F5 or the Debug panel
- The debugger will attach to the running tests
3. Debug features available:
- Step through code
- Inspect variables
- View call stack
- Set conditional breakpoints

The debugger will automatically map source files between your local workspace and the container environment using the configured source roots.

### Pack the plugin into a .rock

```sh
Expand Down
Loading
Loading