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
27 changes: 27 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/docker-existing-dockerfile
{
"name": "lua_resty_netacea Dev container",
"build": {
"dockerfile": "../Dockerfile",
"target": "test"
},
// Add the IDs of extensions you want installed when the container is created.
"customizations": {
"vscode": {
"extensions": [
"bierner.markdown-emoji", // Markdown Emoji
"bierner.markdown-mermaid", // Markdown Mermaid
"DavidAnson.vscode-markdownlint", // Markdown Lint
"ms-azuretools.vscode-docker", // Docker
"oderwat.indent-rainbow", // indent-rainbow
],
"settings": {
}
}
},
"remoteUser": "ubuntu",
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
}
}
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
name: lua-resty-netacea-build
on:
workflow_dispatch:
pull_request:
branches:
- master
push:
branches:
- master
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ luac.out
*.bak

tags

# luacov reports
luacov.report
luacov.report.*
luacov.stats.out
luacov.stats.out.*
6 changes: 6 additions & 0 deletions .luacov
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
return {
["reporter"] = "html",
["reportfile"] = "luacov.report.html",
["include"] = {"./src/" },
runreport = true
}
14 changes: 4 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
FROM openresty/openresty:xenial AS base
FROM openresty/openresty:noble AS base

USER root

WORKDIR /usr/src
# ENV HOME=/usr/src

RUN apt-get update
RUN apt-get install -y libssl-dev

# RUN cd $HOME

RUN curl -L -o /tmp/luarocks-3.12.2-1.src.rock https://luarocks.org/luarocks-3.12.2-1.src.rock &&\
luarocks install /tmp/luarocks-3.12.2-1.src.rock &&\
rm /tmp/luarocks-3.12.2-1.src.rock


FROM base AS build
COPY ./lua_resty_netacea-0.2-2.rockspec ./
COPY ./lua_resty_netacea-1.0-0.rockspec ./
COPY ./src ./src
RUN /usr/local/openresty/luajit/bin/luarocks make ./lua_resty_netacea-0.2-2.rockspec
RUN /usr/local/openresty/luajit/bin/luarocks make ./lua_resty_netacea-1.0-0.rockspec

FROM build AS test

Expand All @@ -28,6 +21,7 @@ RUN /usr/local/openresty/luajit/bin/luarocks install cluacov
RUN /usr/local/openresty/luajit/bin/luarocks install require
RUN /usr/local/openresty/luajit/bin/luarocks install luacheck

COPY ./.luacov ./.luacov
COPY ./test ./test
COPY ./run_lua_tests.sh ./run_lua_tests.sh
RUN chmod +x ./run_lua_tests.sh
Expand Down
61 changes: 49 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,53 @@
# lua_resty_netacea
An Openresty module for easy integration of Netacea services

# Building the base image
All the images used by docker rely on a specific base image being available on your local docker registry. You can ensure you have this by running the following command
```sh
docker build -t lua_resty_netacea:latest .
```
An Openresty module for easy integration of Netacea services. This repo is for developing the package. The package can be accessed by the Luarocks package management platform. See the Netacea documentation for making use of the module.

# Running Tests
`docker-compose build` then `docker-compose run test`
## Published package

## nginx.conf - mitigate
```
The Netacea package is available on the Luarocks package manager. Publishing is handled by the Netacea team.

## Docker images

The Dockerfile contains a multi-stage build, including:

| Stage name | Based on | Description |
| -- | -- | -- |
| base | openresty/openresty:noble | Base image of Openresty with updated packages around openSSL |
| build | base | Working Openresty instance with Netacea plugin installed using luarocks and rockspec file |
| test | build | Lua packages installed for testing and linting. Command overridden to run unit tests |
| lint | test | Command overridden to run luacheck linter and output results |

The docker compose file is used to mount local files to the right place in the image to support development.

### Run development version

1. Update `./src/conf/nginx.conf` to include Netacea configuration and server configuration. Default is the NGINX instance will just return a static "Hello world" page. See "Configuration" below
2. `docker compose up resty`
3. Access [](http://localhost:8080)

### Run tests

#### Unit tests

##### In dev container

Without coverage report: `./run_lua_tests.sh`
With coverage report (sent to stdout) `export LUACOV_REPORT=1 && ./run_lua_tests.sh`

##### Docker compose

Without coverage report: `docker compose run --build test`
With coverage report (sent to stdout) `docker compose run -e LUACOV_REPORT=1 --build test [> output.html]`

#### Linter

`docker compose run --build lint`

## Configuration

### nginx.conf - mitigate

```conf
worker_processes 1;

events {
Expand Down Expand Up @@ -57,8 +93,9 @@ http {
}
```

## nginx.conf - inject
```
### nginx.conf - inject

```conf
worker_processes 1;

events {
Expand Down
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ version: '3.5'

services:
resty:
image: lua_resty_netacea:latest
build:
dockerfile: Dockerfile
context: .
Expand Down Expand Up @@ -30,6 +29,8 @@ services:
volumes:
- "./src:/usr/src/src"
- "./test:/usr/src/test"
- "./run_lua_tests.sh:/usr/src/run_lua_tests.sh"
- ".luacov:/usr/src/.luacov"

lint:
build:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package = "lua_resty_netacea"
version = "0.2-2"
version = "1.0-0"
source = {
url = "git://github.com/Netacea/lua_resty_netacea",
branch = "master"
}
description = {
summary = "An Openresty module for easy integration of Netacea services",
homepage = "https://github.com/Netacea/lua_resty_netacea",
maintainer = "Dan Lyon",
maintainer = "Netacea Ltd.",
license = "MIT"
}
dependencies = {
Expand Down
85 changes: 6 additions & 79 deletions run_lua_tests.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,80 +1,7 @@
# sh /docker/pull-changes.sh

OPENRESTY="/usr/local/openresty"
RESTY="${OPENRESTY}/bin/resty"
WD="${OPENRESTY}/nginx"
BASE_DIR="/usr/src"
TEST_DIR="${BASE_DIR}/test"

STATS_FILE="luacov.stats.out"
STATS_SRC="${TEST_DIR}/${STATS_FILE}"
REPORT_FILE="luacov.report.out"
REPORT_SRC="${TEST_DIR}/${REPORT_FILE}"

EXIT_CODE=0

################################################################################

OPT_PROCESS_STATS=0
OPT_EARLY_EXIT=1

while getopts "s" opt; do
case $opt in
s) OPT_PROCESS_STATS=1;;
\?) echo "invalid argument";;
esac
done

################################################################################

function exit_script {
echo ""
echo "END TESTS"
echo ""
echo "coverage stats file: ${STATS_SRC}"
end_tests
echo $1
exit $1
}

function end_tests {
echo "done"
# if [ $OPT_PROCESS_STATS -eq 1 ]; then
# cd $TEST_DIR
# (luacov)
# echo "coverage report file: ${REPORT_SRC}"
# fi
}

################################################################################

echo ""
echo "BEGIN TESTS"
echo ""

cd $TEST_DIR
PREV=$(pwd)

files=$(find . -name '*.test.lua')

while read line; do
echo " -- TEST FILE: ${line}"
DIR=$(dirname "${line}")
FILE=$(basename "${line}")

onlytag=""
grep '#only' "${line}" && onlytag="--tags='only'"

bash -c "$RESTY $line --exclude-tags='skip' ${onlytag}"
RES=$?

if [ $RES -ne 0 ]; then
EXIT_CODE=$RES
if [ $OPT_EARLY_EXIT -eq 1 ]; then break; fi
fi

cd "$PREV"
echo ""
done <<< "$files"

exit_script $EXIT_CODE
if [ "$LUACOV_REPORT" = "1" ]; then
busted --coverage-config-file ./.luacov --coverage ./test >&2
cat ./luacov.report.html
else
busted ./test
fi
2 changes: 1 addition & 1 deletion src/kinesis_resty.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ local http = require "resty.http"
local cjson = require "cjson.safe"
local sha256 = require "resty.sha256"
local str = require "resty.string"
local ngx = ngx
local ngx = require 'ngx'

local Kinesis = {}
Kinesis.__index = Kinesis
Expand Down
23 changes: 13 additions & 10 deletions src/lua_resty_netacea.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ local Ingest = require("lua_resty_netacea_ingest")
local netacea_cookies = require('lua_resty_netacea_cookies_v3')
local utils = require("netacea_utils")
local protector_client = require("lua_resty_netacea_protector_client")
local Constants = require("lua_resty_netacea_constants")

local _N = {}
_N._VERSION = '0.2.2'
_N._TYPE = 'nginx'

local ngx = require 'ngx'
local cjson = require 'cjson'
local http = require 'resty.http'

local function serveCaptcha(captchaBody)
ngx.status = ngx.HTTP_FORBIDDEN
Expand All @@ -32,12 +32,12 @@ function _N:new(options)
local n = {}
setmetatable(n, self)
self.__index = self

-- ingest:optional:ingestEnabled
n.ingestEnabled = options.ingestEnabled or false
-- ingest:required:ingestEndpoint
n.ingestEndpoint = options.ingestEndpoint

n.kinesisProperties = options.kinesisProperties or nil

if not n.kinesisProperties then
Expand Down Expand Up @@ -79,7 +79,7 @@ function _N:new(options)
-- global:optional:cookieAttributes
n.cookieAttributes = utils.parseOption(options.cookieAttributes, 'Max-Age=86400; Path=/;')
-- global:optional:captchaCookieName
n.captchaCookieName = utils.parseOption(options.captchaCookieName, '_mitatacaptcha') --options.captchaCookieName or '_mitatacaptcha'
n.captchaCookieName = utils.parseOption(options.captchaCookieName, '_mitatacaptcha')
-- global:optional:captchaCookieAttributes
n.captchaCookieAttributes = utils.parseOption(options.captchaCookieAttributes, 'Max-Age=86400; Path=/;')
-- global:optional:realIpHeader
Expand Down Expand Up @@ -126,7 +126,9 @@ function _N:getBestMitigation(protector_result)
if (captcha == Constants.captchaStates.PASS) then return nil end
if (captcha == Constants.captchaStates.COOKIEPASS) then return nil end

if (mitigate == Constants.mitigationTypes.BLOCKED and (captcha == Constants.captchaStates.SERVE or captcha == Constants['captchaStates'].COOKIEFAIL )) then
if (mitigate == Constants.mitigationTypes.BLOCKED
and (captcha == Constants.captchaStates.SERVE
or captcha == Constants['captchaStates'].COOKIEFAIL)) then
return 'captcha'
end

Expand Down Expand Up @@ -203,25 +205,26 @@ function _N:refreshSession(reason)
local cookies = {
self.cookieName .. '=' .. new_cookie.mitata_jwe .. ';' .. self.cookieAttributes
}

if protector_result.captcha_cookie and protector_result.captcha_cookie ~= '' then
local captcha_cookie_encrypted = netacea_cookies.encrypt(self.secretKey, protector_result.captcha_cookie)
table.insert(cookies, self.captchaCookieName .. '=' .. captcha_cookie_encrypted .. ';'.. self.captchaCookieAttributes)
table.insert(cookies,
self.captchaCookieName .. '=' .. captcha_cookie_encrypted .. ';'.. self.captchaCookieAttributes)
end

ngx.header['Set-Cookie'] = cookies
end

function _N:handleCaptcha()
local parsed_cookie = self:handleSession()
self:handleSession()

ngx.req.read_body()
local captcha_data = ngx.req.get_body_data()
local protector_result = self.protectorClient:validateCaptcha(captcha_data)
ngx.ctx.NetaceaState.protector_result = protector_result
ngx.ctx.NetaceaState.grace_period = -1000
ngx.log(ngx.DEBUG, "NETACEA CAPTCHA - protector result: ", cjson.encode(ngx.ctx.NetaceaState))

self:refreshSession(Constants['issueReasons'].CAPTCHA_POST)
ngx.exit(protector_result.exit_status)
end
Expand Down
2 changes: 1 addition & 1 deletion src/lua_resty_netacea_constants.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Constants = {}
local Constants = {}

Constants['idTypesText'] = {}
Constants['idTypes'] = {
Expand Down
Loading