Refactor to server subdirectory
A client library will be included in this repository as well, prepare by moving all server components to a subdirectory. As part of this, the server script is refactored to a generated entrypoint script. Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
This commit is contained in:
parent
792149bae6
commit
1e84b2e57d
64
README.md
64
README.md
@ -1,67 +1,3 @@
|
||||
# RESTful HTTP API for nftables
|
||||
|
||||
Early work in progress.
|
||||
|
||||
## Configuration
|
||||
|
||||
A configuration file must be passed using the environment variable `NFT-API-CONFIG`. The file contains a mapping of bcrypt hashed tokens to API paths and methods. Requests to the API are only authorized if the token passed using the header `X-NFT-API-Token` and the requested path and method match an entry in the configuration.
|
||||
|
||||
### Sample configuration:
|
||||
|
||||
```
|
||||
nft-api:
|
||||
tokens:
|
||||
$2y$05$ZifkrfFg2XZU2ds7Lrcl9usJVyxHro9Ezjo84OMpsBSau4pEu42eS:
|
||||
/set/inet/filter/foo4:
|
||||
- GET
|
||||
- POST
|
||||
$2y$05$ZifkrfFg2XZU2ds7Lrcl9usJVyxHro9Ezjo84OMpsBSau4pEu42eS:
|
||||
/set/inet/filter/*:
|
||||
- GET
|
||||
```
|
||||
|
||||
Any elements can contain a wildcard in the form of a `*` character.
|
||||
|
||||
Generate token hashes using any bcrypt hashing tool, such as `htpasswd` from the `apache-utils` suite:
|
||||
|
||||
```
|
||||
$ htpasswd -Bn x
|
||||
```
|
||||
|
||||
The username (here `x`) is not used, ignore the relevant part before and including the colon in the output.
|
||||
|
||||
## Deployment
|
||||
|
||||
The application can be served using any Python WSGI server. Easiest is to use `waitress` using the script found in the repository root:
|
||||
|
||||
```
|
||||
./nftables-api.py
|
||||
```
|
||||
|
||||
It will bind on `*:9090`.
|
||||
|
||||
## Usage
|
||||
|
||||
Currently `GET` and `POST` methods are implemented, allowing to query or append data respectively.
|
||||
|
||||
All requests must contain a header `X-NFT-API-Token` containing a token authorized for the requested path and method. All `POST` requests must contain a JSON payload.
|
||||
|
||||
By default, the response body will be output deemed most "useful" - in case of `GET` requests, that is only the data found for the given query, in case of `POST` requests the result of the change. Optionally, a query parameter `raw` can be passed to retrieve a mapping containing all status information, including the raw `libnftables-json(5)` output, instead.
|
||||
|
||||
Below are examples using `curl`.
|
||||
|
||||
### nftables sets
|
||||
|
||||
#### Get a set
|
||||
|
||||
```
|
||||
$ curl -H 'X-NFT-API-Token: foo' localhost:9090/set/inet/filter/foo4
|
||||
["192.168.0.0/24", "192.168.1.1", "192.168.3.0/24", "192.168.4.0/24", "192.168.5.0/26"]⏎
|
||||
```
|
||||
|
||||
#### Append to a set
|
||||
|
||||
```
|
||||
$ curl -H 'X-NFT-API-Token: foo' --json '{"addresses": "fe80::/64"}' localhost:9090/set/inet/filter/foo
|
||||
{"status": true}⏎
|
||||
```
|
||||
|
1
nft_http_api_server/LICENSE
Symbolic link
1
nft_http_api_server/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../LICENSE
|
65
nft_http_api_server/README.md
Normal file
65
nft_http_api_server/README.md
Normal file
@ -0,0 +1,65 @@
|
||||
# RESTful HTTP API for nftables - Server
|
||||
|
||||
## Configuration
|
||||
|
||||
A configuration file must be passed using the environment variable `NFT-API-CONFIG`. The file contains a mapping of bcrypt hashed tokens to API paths and methods. Requests to the API are only authorized if the token passed using the header `X-NFT-API-Token` and the requested path and method match an entry in the configuration.
|
||||
|
||||
### Sample configuration:
|
||||
|
||||
```
|
||||
nft-api:
|
||||
tokens:
|
||||
$2y$05$ZifkrfFg2XZU2ds7Lrcl9usJVyxHro9Ezjo84OMpsBSau4pEu42eS:
|
||||
/set/inet/filter/foo4:
|
||||
- GET
|
||||
- POST
|
||||
$2y$05$ZifkrfFg2XZU2ds7Lrcl9usJVyxHro9Ezjo84OMpsBSau4pEu42eS:
|
||||
/set/inet/filter/*:
|
||||
- GET
|
||||
```
|
||||
|
||||
Any elements can contain a wildcard in the form of a `*` character.
|
||||
|
||||
Generate token hashes using any bcrypt hashing tool, such as `htpasswd` from the `apache-utils` suite:
|
||||
|
||||
```
|
||||
$ htpasswd -Bn x
|
||||
```
|
||||
|
||||
The username (here `x`) is not used, ignore the relevant part before and including the colon in the output.
|
||||
|
||||
## Deployment
|
||||
|
||||
The application can be served using any Python WSGI server. Easiest is to use `waitress` using the script found in the repository root:
|
||||
|
||||
```
|
||||
./nftables-api.py
|
||||
```
|
||||
|
||||
It will bind on `*:9090`.
|
||||
|
||||
## Usage
|
||||
|
||||
Currently `GET` and `POST` methods are implemented, allowing to query or append data respectively.
|
||||
|
||||
All requests must contain a header `X-NFT-API-Token` containing a token authorized for the requested path and method. All `POST` requests must contain a JSON payload.
|
||||
|
||||
By default, the response body will be output deemed most "useful" - in case of `GET` requests, that is only the data found for the given query, in case of `POST` requests the result of the change. Optionally, a query parameter `raw` can be passed to retrieve a mapping containing all status information, including the raw `libnftables-json(5)` output, instead.
|
||||
|
||||
Below are examples using `curl`.
|
||||
|
||||
### nftables sets
|
||||
|
||||
#### Get a set
|
||||
|
||||
```
|
||||
$ curl -H 'X-NFT-API-Token: foo' localhost:9090/set/inet/filter/foo4
|
||||
["192.168.0.0/24", "192.168.1.1", "192.168.3.0/24", "192.168.4.0/24", "192.168.5.0/26"]⏎
|
||||
```
|
||||
|
||||
#### Append to a set
|
||||
|
||||
```
|
||||
$ curl -H 'X-NFT-API-Token: foo' --json '{"addresses": "fe80::/64"}' localhost:9090/set/inet/filter/foo
|
||||
{"status": true}⏎
|
||||
```
|
@ -8,9 +8,8 @@ An English copy of the Licence is shipped in a file called LICENSE along with th
|
||||
You may obtain copies of the Licence in any of the official languages at https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12.
|
||||
"""
|
||||
|
||||
from waitress import serve
|
||||
|
||||
from nftables_api.app import app
|
||||
from waitress import serve
|
||||
|
||||
if __name__ == '__main__':
|
||||
serve(app, host='*', port=9090)
|
20
nft_http_api_server/nftables_api/server.py
Normal file
20
nft_http_api_server/nftables_api/server.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""
|
||||
A RESTful HTTP API for nftables
|
||||
Copyright 2024, Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
|
||||
|
||||
Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence").
|
||||
You may not use this work except in compliance with the Licence.
|
||||
An English copy of the Licence is shipped in a file called LICENSE along with this applications source code.
|
||||
You may obtain copies of the Licence in any of the official languages at https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12.
|
||||
"""
|
||||
|
||||
from waitress import serve
|
||||
|
||||
from nftables_api.app import app
|
||||
|
||||
|
||||
def server():
|
||||
if __name__ == '__main__':
|
||||
serve(app, host='*', port=9090)
|
||||
else:
|
||||
raise RuntimeError('serve() is intended to be used as an entrypoint.')
|
@ -4,8 +4,8 @@ build-backend = 'setuptools.build_meta'
|
||||
|
||||
|
||||
[project]
|
||||
name = 'nftables_api'
|
||||
description = 'RESTful HTTP API for nftables'
|
||||
name = 'nftables_api-server'
|
||||
description = 'RESTful HTTP API for nftables (server)'
|
||||
dynamic = ['license', 'readme', 'version']
|
||||
authors = [
|
||||
{ name='Georg Pfuetzenreuter', email='georg+python@lysergic.dev' },
|
||||
@ -30,6 +30,8 @@ requires-python = '>=3.6'
|
||||
|
||||
dependencies = [
|
||||
'PyYAML',
|
||||
'bcrypt',
|
||||
'falcon',
|
||||
# 'nftables', # cannot by managed by pip
|
||||
]
|
||||
|
||||
@ -39,6 +41,9 @@ dev = [
|
||||
'ruff',
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
nftables_api = 'nftables_api.server:server'
|
||||
|
||||
[tool.setuptools]
|
||||
include-package-data = false
|
||||
|
||||
@ -48,4 +53,3 @@ readme = {file = ['README.md']}
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ['.']
|
||||
exclude = ['scripts.*', 'tests', 'tests.*', 'ruff.toml']
|
@ -1,5 +1,5 @@
|
||||
[metadata]
|
||||
name = nftables_api
|
||||
name = nftables_api-server
|
||||
version = attr: nftables_api.__version__
|
||||
author = Georg Pfuetzenreuter
|
||||
author_email = georg+python@lysergic.dev
|
||||
@ -14,8 +14,4 @@ packages=find:
|
||||
python_requires = >=3.6
|
||||
|
||||
[options.packages.find]
|
||||
exclude=
|
||||
scripts*
|
||||
tests*
|
||||
*.toml
|
||||
where=.
|
10
ruff.toml
10
ruff.toml
@ -37,7 +37,11 @@ preview = true
|
||||
explicit-preview-rules = true
|
||||
|
||||
[lint.per-file-ignores]
|
||||
"nftables_api/__init__.py" = ["PLC0414"] # allow explicit re-exports / avoid conflict with F401
|
||||
"nft_http_api_client/nftables_api_client/__init__.py" = ["PLC0414"] # allow explicit re-exports / avoid conflict with F401
|
||||
"nft_http_api_server/nftables_api/__init__.py" = ["PLC0414"] # ^
|
||||
"nft_http_api_server/nftables-http-api.py" = [
|
||||
"INP001", # entrypoint script
|
||||
]
|
||||
"tests/*.py" = [
|
||||
"INP001", # tests do not need to be part of a package
|
||||
"S101", # allow "assert" in test suites
|
||||
@ -47,5 +51,5 @@ explicit-preview-rules = true
|
||||
[lint.pydocstyle]
|
||||
convention = "pep257"
|
||||
|
||||
[lint.isort]
|
||||
force-wrap-aliases = true
|
||||
#[lint.isort]
|
||||
#force-wrap-aliases = true
|
||||
|
@ -8,5 +8,5 @@ podman run \
|
||||
-it \
|
||||
-v .:"$wd" \
|
||||
registry.opensuse.org/home/crameleon/containers/containers/crameleon/pytest-nftables:latest \
|
||||
env NFT-API-CONFIG="$wd"/tests/config.yaml PYTHONPATH="$wd" pytest --pdb --pdbcls=IPython.terminal.debugger:Pdb -rA -s -v -x "$wd"/tests
|
||||
env NFT-API-CONFIG="$wd"/tests/config.yaml PYTHONPATH="$wd/nft_http_api_client:$wd/nft_http_api_server" pytest --pdb --pdbcls=IPython.terminal.debugger:Pdb -rA -s -v -x "$wd"/tests
|
||||
|
||||
|
@ -10,9 +10,8 @@ You may obtain copies of the Licence in any of the official languages at https:/
|
||||
|
||||
from falcon import testing
|
||||
from nftables import Nftables
|
||||
from pytest import exit, fixture
|
||||
|
||||
from nftables_api.app import app
|
||||
from pytest import exit, fixture
|
||||
|
||||
|
||||
def run_nft(nft, cmd):
|
||||
|
Loading…
Reference in New Issue
Block a user