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

feat: implement base code structure #5

Merged
merged 24 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b355673
Update docker compose
tsutsu3 Nov 17, 2024
d884d2d
Fix vite.config
tsutsu3 Nov 17, 2024
cb64e22
Update
tsutsu3 Nov 23, 2024
42be9a3
Fix status command
tsutsu3 Nov 23, 2024
b56152f
Update readme usage
tsutsu3 Nov 23, 2024
35818a9
npm run format
tsutsu3 Nov 23, 2024
24ff905
Update Jest configuration to specify coverage collection from source …
tsutsu3 Nov 23, 2024
76900ce
Add unbound server test
tsutsu3 Nov 23, 2024
87a12e7
Update Unbound configuration to support dynamic DNS and control ports
tsutsu3 Nov 23, 2024
d638fd1
Update GitHub Actions workflow to specify Unbound ports for each version
tsutsu3 Nov 23, 2024
f03409d
Fix dig
tsutsu3 Nov 23, 2024
062fdcd
Add health check for Unbound in GitHub Actions workflow
tsutsu3 Nov 23, 2024
bb4c975
Remove commented-out Unbound version configurations in GitHub Actions…
tsutsu3 Nov 23, 2024
111d94a
Set permissions for Unix socket in GitHub Actions workflow
tsutsu3 Nov 23, 2024
d238c39
Comment out it
tsutsu3 Nov 23, 2024
63269fb
Update Unbound configuration and enhance test cases with options and …
tsutsu3 Nov 24, 2024
64dc49f
Fix response
tsutsu3 Nov 24, 2024
ae43257
Refactor
tsutsu3 Nov 24, 2024
a03a85c
Support tcp socket
tsutsu3 Nov 28, 2024
a93830d
Add workflow to generate mock certificates
tsutsu3 Nov 28, 2024
e31865e
Fix typo
tsutsu3 Nov 28, 2024
5ff7e42
Fix paths for generated certificate files in CI workflow
tsutsu3 Nov 28, 2024
87dea16
CI workflow: Upload and download generated keys as artifacts
tsutsu3 Nov 28, 2024
b979302
Add tls test
tsutsu3 Dec 1, 2024
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
16 changes: 11 additions & 5 deletions .env
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Unbound Configuration Path
# Select one of the following options:
# - unix: Unix Domain Socket
# - tls: TLS Socket
UNBOUND_CONF_PATH=./unbound-config/unix
# UNBOUND_CONF_PATH=./unbound-config/tls
# default: ./unbound-config/unix
# UNBOUND_CONF_PATH=./unbound-config/unix
# UNBOUND_CONF_PATH=./unbound-config/tls

# Unbound Version
# default: latest
# UNBOUND_VERSION=latest

# Unbound DNS, Control Port
# UNBOUND_DNS_PORT=53
# UNBOUND_CONTROL_PORT=8953
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Unbound Configuration Path
# default: ./unbound-config/unix
# UNBOUND_CONF_PATH=./unbound-config/unix
# UNBOUND_CONF_PATH=./unbound-config/tls

# Unbound Version
# default: latest
# UNBOUND_VERSION=latest

# Unbound DNS, Control Port
# UNBOUND_DNS_PORT=53
# UNBOUND_CONTROL_PORT=8953
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,43 @@ jobs:
run: npm ci
- name: Lint with ESLint
run: npm run lint
generate-certs:
name: Generate Certs
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install OpenSSL
run: sudo apt-get install -y openssl
- name: Generate server key
run: |
openssl genrsa -out tests/key/unbound_server.key 2048
openssl req -new -key tests/key/unbound_server.key -out tests/key/unbound_server.csr -subj "/CN=server"
openssl x509 -req -in tests/key/unbound_server.csr -signkey tests/key/unbound_server.key -out tests/key/unbound_server.pem -days 365
- name: Generate client key
run: |
openssl genrsa -out tests/key/unbound_control.key 2048
openssl req -new -key tests/key/unbound_control.key -out tests/key/unbound_control.csr -subj "/CN=client"
openssl x509 -req -in tests/key/unbound_control.csr -signkey tests/key/unbound_control.key -out tests/key/unbound_control.pem -days 365
- name: Upload generated keys
uses: actions/upload-artifact@v4
with:
name: test-keys
path: tests/key/
test:
name: Test
needs: generate-certs
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x, 22.x]
steps:
- uses: actions/checkout@v4
- name: Download generated keys
uses: actions/download-artifact@v4
with:
name: test-keys
path: tests/key/
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
Expand Down
92 changes: 92 additions & 0 deletions .github/workflows/it.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# TODO: Fix Unix domain socket permissions

# name: Test Unbound with Multiple Versions

# on:
# push:
# branches:
# - main
# pull_request:
# branches:
# - main

# jobs:
# test-unbound:
# runs-on: ubuntu-latest

# strategy:
# matrix:
# include:
# # TODO: Multiple versions of Unbound can be tested by adding more versions here.
# # - fix: unbound.conf, test file's socket path
# # - unbound-version: 1.18.0
# # unbound-port: 5318
# # unbound-control-port: 8918
# # - unbound-version: 1.19.3
# # unbound-port: 5319
# # unbound-control-port: 8919
# # - unbound-version: 1.20.0
# # unbound-port: 5320
# # unbound-control-port: 8920
# # - unbound-version: 1.21.1
# # unbound-port: 5321
# # unbound-control-port: 8921
# - unbound-version: 1.22.0
# unbound-port: 5322
# unbound-control-port: 8922

# steps:
# - uses: actions/checkout@v4

# - name: Set up Docker Compose
# run: sudo apt-get update && sudo apt-get install -y docker-compose

# - name: Start Unbound containers
# run: |
# UNBOUND_VERSION=${{ matrix.unbound-version }} \
# UNBOUND_DNS_PORT=${{ matrix.unbound-port }} \
# UNBOUND_CONTROL_PORT=${{ matrix.unbound-control-port }} \
# docker-compose up -d
# - name: Verify Unbound is running
# run: docker ps

# - name: Wait for Unbound to become healthy
# run: |
# echo "Waiting for Unbound to be ready..."
# for i in {1..30}; do
# HEALTH=$(docker inspect --format='{{.State.Health.Status}}' unbound-${{ matrix.unbound-version }})
# if [ "$HEALTH" == "healthy" ]; then
# echo "Unbound is healthy!"
# break
# fi
# echo "Unbound is not ready yet. Waiting..."
# sleep 2
# done
# if [ "$HEALTH" != "healthy" ]; then
# echo "Unbound did not become healthy in time."
# exit 1
# fi

# - name: Fix permissions inside container
# run: |
# docker exec unbound-${{ matrix.unbound-version }} chmod 777 /opt/unbound/etc/unbound/socket/unbound.ctl

# - name: Set permissions for Unix socket
# run: ls -Rl "$GITHUB_WORKSPACE/unbound-config"

# - name: Test Unbound
# run: |
# dig @localhost -p ${{ matrix.unbound-port }} example.com

# - name: Use Node.js 22.x
# uses: actions/setup-node@v4
# with:
# node-version: 22.x

# - name: Install dependencies
# run: npm ci
# - run: npm run test:it

# - name: Stop Unbound
# run: |
# docker compose stop unbound-${{ matrix.unbound-version }}
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@ dist-ssr


coverage/
unbound-config/*
!unbound-config/unbound.conf
unbound-config/*/*
!unbound-config/tls/unbound.conf
!unbound-config/unix/unbound.conf
tests/__snapshots__
tests/key/*
!.gitkeep
.env
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.formatOnPaste": true,
"files.eol": "\n"
"files.eol": "\n",
"jest.runMode": {
"type": "on-demand"
}
}
67 changes: 56 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,69 @@ yarn add unbound-control-ts

Here's a basic example to demonstrate how to use the library:

Use domain socket:
```ts
import { UnboundControl } from 'unbound-control-ts';
import { UnixUnboundClient } from 'unbound-control-ts';

// Initialize the client with the path to the unbound-control binary
const unbound = new UnboundControl('/path/to/unbound-control');
const client = new UnixUnboundClient('/path/to/unbound-control.sock');

// Fetch and display Unbound statistics
async function getStats() {
(async () => {
try {
const stats = await unbound.stats();
console.log('Unbound Statistics:', stats);
const response = await client.status();
console.log(response);
} catch (error) {
console.error('Error fetching stats:', error);
if (error instanceof UnboundError) {
console.error(error.message);
} else {
console.error(error);
}
}
}
})();
```

Use tcp socket:
```ts
import { TcpUnboundClient } from 'unbound-control-ts';

const client = new TcpUnboundClient('localhost', 8953);

getStats();
(async () => {
try {
const response = await client.status();
console.log(response);
} catch (error) {
if (error instanceof UnboundError) {
console.error(error.message);
} else {
console.error(error);
}
}
})();
```

output:

```json
{
"json": {
"modules": [
"subnetcache",
"validator",
"iterator",
],
"options": [
"reuseport",
"control(namedpipe)",
],
"pid": 1,
"status": "running",
"threads": 1,
"uptime": 292,
"verbosity": 1,
"version": "1.22.0",
},
"raw": "version: 1.22.0\nverbosity: 1\nthreads: 1\nmodules: 3 [ subnetcache validator iterator ]\nuptime: 292 seconds\noptions: reuseport control(namedpipe)\nunbound (pid 1) is running...\n",
}
```

## Development
Expand All @@ -117,7 +163,6 @@ Before you begin, ensure you have the following tools installed on your system:
- **Node.js**: Version 16 or later. [Download Node.js](https://nodejs.org/)
- **npm**: Comes with Node.js, or install it separately if needed.
- **Unbound**: Ensure that `unbound-control` is installed and properly configured. Follow the [Unbound installation guide](https://nlnetlabs.nl/documentation/unbound/) for details.
- **TypeScript**: (Optional) For contributing to or extending the library, TypeScript must be installed globally or as a dev dependency.

### Develop Setup

Expand Down
63 changes: 32 additions & 31 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
services:
unbound-setup:
image: mvance/unbound:latest
volumes:
- ${UNBOUND_CONF_PATH}:/opt/unbound/etc/unbound
restart: "no"
entrypoint: []
command: >-
/bin/sh -c "
if [ ! -f /opt/unbound/etc/unbound/key/unbound_server.key ]; then
echo 'Setup start' &&
unbound-control-setup &&
mkdir /opt/unbound/etc/unbound/key &&
mv /opt/unbound/etc/unbound/unbound_* /opt/unbound/etc/unbound/key &&
echo 'Setup complete';
else
echo 'Certificates already exist';
fi
"
unbound:
image: mvance/unbound:latest
container_name: unbound
ports:
- "53:53/tcp"
- "53:53/udp"
- "8953:8953"
volumes:
- ${UNBOUND_CONF_PATH}:/opt/unbound/etc/unbound
restart: unless-stopped
depends_on:
- unbound-setup
services:
unbound-setup:
image: mvance/unbound:${UNBOUND_VERSION:-latest}
volumes:
- ${UNBOUND_CONF_PATH:-./unbound-config/unix}:/opt/unbound/etc/unbound
restart: "no"
entrypoint: []
command: >-
/bin/sh -c "
if [ ! -f /opt/unbound/etc/unbound/key/unbound_server.key ]; then
echo 'Setup start' &&
unbound-control-setup &&
mkdir /opt/unbound/etc/unbound/key /opt/unbound/etc/unbound/socket &&
mv /opt/unbound/etc/unbound/unbound_* /opt/unbound/etc/unbound/key &&
chown 1000 /opt/unbound/etc/unbound/key/* &&
echo 'Setup complete';
else
echo 'Certificates already exist';
fi
"
unbound:
image: mvance/unbound:${UNBOUND_VERSION:-latest}
container_name: unbound-${UNBOUND_VERSION:-latest}
ports:
- "${UNBOUND_DNS_PORT:-53}:53/tcp"
- "${UNBOUND_DNS_PORT:-53}:53/udp"
- "${UNBOUND_CONTROL_PORT:-8953}:8953"
volumes:
- ${UNBOUND_CONF_PATH:-./unbound-config/unix}:/opt/unbound/etc/unbound
restart: unless-stopped
depends_on:
- unbound-setup
41 changes: 38 additions & 3 deletions examples/index.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,39 @@
const { hello } = require("../../dist/index.cjs");
const path = require("path");
const { UnboundControlClient, UnboundError } = require("../dist/index.cjs");

const result = hello();
console.log(`CJS Result: ${result}`);
const baseDir = path.resolve(__dirname, "..");

const unixSocketName = path.join(
baseDir,
"unbound-config/unix/socket/unbound.ctl",
);

const client = new UnboundControlClient(unixSocketName);

(async () => {
try {
const response = await client.status();
console.log(response.raw);
console.log(response.json);
} catch (error) {
if (error instanceof UnboundError) {
console.error(error.message);
} else {
console.error(error);
}
}
})();

(async () => {
try {
const response = await client.status();
console.log(response.raw);
console.log(response.json);
} catch (error) {
if (error instanceof UnboundError) {
console.error(error.message);
} else {
console.error(error);
}
}
})();
Loading