Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"golang.go",
"unifiedjs.vscode-mdx",
"a-h.templ",
"redhat.vscode-yaml"
"redhat.vscode-yaml",
"matthewpi.caddyfile-support"
]
}
}
Expand Down
4 changes: 4 additions & 0 deletions .devcontainer/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ services:
dockerfile: .devcontainer/Dockerfile
volumes:
- ../:/workspace/anubis:cached
- node_modules:/workspace/anubis/node_modules
environment:
VALKEY_URL: redis://valkey:6379/0
#entrypoint: ["/usr/bin/sleep", "infinity"]
user: vscode

volumes:
node_modules:
3 changes: 2 additions & 1 deletion .devcontainer/poststart.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/usr/bin/env bash

pwd
sudo chown -R vscode:vscode ./node_modules

npm ci &
go mod download &
go install ./utils/cmd/... &
go install mvdan.cc/sh/v3/cmd/shfmt@latest &

wait
2 changes: 2 additions & 0 deletions .github/workflows/smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ jobs:
strategy:
matrix:
test:
- caddy
- git-clone
- git-push
- healthcheck
- i18n
- unix-socket-xff
runs-on: ubuntu-24.04
steps:
- name: Checkout code
Expand Down
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"golang.go",
"unifiedjs.vscode-mdx",
"a-h.templ",
"redhat.vscode-yaml"
"redhat.vscode-yaml",
"matthewpi.caddyfile-support"
]
}
16 changes: 8 additions & 8 deletions cmd/anubis/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,19 @@ func setupListener(network string, address string) (net.Listener, string) {

// additional permission handling for unix sockets
if network == "unix" {
slog.Debug("parsing socket mode", "mode_string", *socketMode, "address", address)

mode, err := strconv.ParseUint(*socketMode, 8, 0)
if err != nil {
listener.Close()
log.Fatal(fmt.Errorf("could not parse socket mode %s: %w", *socketMode, err))
slog.Error("could not parse socket mode", "mode", *socketMode, "err", err)
os.Exit(1)
}

err = os.Chmod(address, os.FileMode(mode))
if err != nil {
err := listener.Close()
if err != nil {
log.Printf("failed to close listener: %v", err)
}
log.Fatal(fmt.Errorf("could not change socket mode: %w", err))
if err := os.Chmod(address, os.FileMode(mode)); err != nil {
// Ignore chmod errors on Unix domain sockets - this is expected behavior
// on many systems/containers where socket permissions cannot be changed
slog.Debug("chmod failed on socket (ignoring)", "path", address, "err", err)
}
}

Expand Down
10 changes: 10 additions & 0 deletions test/anubis_configs/less_paranoid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
bots:
- name: challenge
user_agent_regex: Mozilla
action: WEIGH
weight:
adjust: 10

status_codes:
CHALLENGE: 401
DENY: 403
11 changes: 2 additions & 9 deletions test/caddy/Caddyfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
:80 {
reverse_proxy http://anubis:3000 {
header_up X-Real-Ip {remote_host}
header_up X-Http-Version {http.request.proto}
}
}

:443 {
tls /etc/techaro/pki/caddy.local.cetacean.club/cert.pem /etc/techaro/pki/caddy.local.cetacean.club/key.pem
caddy.local.cetacean.club {
tls internal

reverse_proxy http://anubis:3000 {
header_up X-Real-Ip {remote_host}
Expand Down
10 changes: 4 additions & 6 deletions test/caddy/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@ services:
ports:
- 8080:80
- 8443:443
volumes:
- "../pki/caddy.local.cetacean.club:/etc/techaro/pki/caddy.local.cetacean.club/"

anubis:
image: ghcr.io/techarohq/anubis:main
image: ko.local/anubis
environment:
BIND: ":3000"
TARGET: http://httpdebug:3000
POLICY_FNAME: /etc/techaro/anubis/less_paranoid.yaml
POLICY_FNAME: /cfg/less_paranoid.yaml
SLOG_LEVEL: DEBUG
volumes:
- ../anubis_configs:/etc/techaro/anubis
- ../anubis_configs:/cfg

httpdebug:
image: ghcr.io/xe/x/httpdebug
pull_policy: always
22 changes: 0 additions & 22 deletions test/caddy/start.sh

This file was deleted.

27 changes: 27 additions & 0 deletions test/caddy/test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
async function testWithUserAgent(userAgent) {
const statusCode =
await fetch("https://caddy.local.cetacean.club:8443/reqmeta", {
headers: {
"User-Agent": userAgent,
}
})
.then(resp => resp.status);
return statusCode;
}

const codes = {
Mozilla: await testWithUserAgent("Mozilla"),
curl: await testWithUserAgent("curl"),
}

const expected = {
Mozilla: 401,
curl: 200,
};

console.log("Mozilla:", codes.Mozilla);
console.log("curl: ", codes.curl);

if (JSON.stringify(codes) !== JSON.stringify(expected)) {
throw new Error(`wanted ${JSON.stringify(expected)}, got: ${JSON.stringify(codes)}`);
}
15 changes: 15 additions & 0 deletions test/caddy/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

set -euo pipefail

source ../lib/lib.sh

build_anubis_ko

docker compose up -d --build

export NODE_TLS_REJECT_UNAUTHORIZED=0

sleep 2

backoff-retry node test.mjs
54 changes: 54 additions & 0 deletions test/lib/lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
REPO_ROOT=$(git rev-parse --show-toplevel)
(cd $REPO_ROOT && go install ./utils/cmd/...)

function cleanup() {
pkill -P $$

if [ -f "docker-compose.yaml" ]; then
docker compose down
fi
}

trap cleanup EXIT SIGINT

function build_anubis_ko() {
(
cd ../.. &&
KO_DOCKER_REPO=ko.local/anubis VERSION=devel ko build \
--platform=all \
--base-import-paths \
--tags="latest" \
--image-user=1000 \
--image-annotation="" \
--image-label="" \
./cmd/anubis \
-L
)
}

function mint_cert() {
if [ "$#" -ne 1 ]; then
echo "Usage: mint_cert <domain.name>"
fi

domainName="$1"

# If the transient local TLS certificate doesn't exist, mint a new one
if [ ! -f "../pki/${domainName}/cert.pem" ]; then
# Subshell to contain the directory change
(
cd ../pki &&
mkdir -p "${domainName}" &&
# Try using https://github.com/FiloSottile/mkcert for better DevEx,
# but fall back to using https://github.com/jsha/minica in case
# you don't have that installed.
(
mkcert \
--cert-file ./"${domainName}"/cert.pem \
--key-file ./"${domainName}"/key.pem \
"${domainName}" ||
go tool minica -domains "${domainName}"
)
)
fi
}
55 changes: 0 additions & 55 deletions test/unix-socket-xff/start.sh

This file was deleted.

33 changes: 33 additions & 0 deletions test/unix-socket-xff/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash

set -euo pipefail

source ../lib/lib.sh

mint_cert "relayd.local.cetacean.club"

# Build static assets
(cd ../.. && npm ci && npm run assets)

# Spawn three jobs:

# HTTP daemon that listens over a unix socket (implicitly ./unixhttpd.sock)
go run ../cmd/unixhttpd &

# A copy of Anubis, specifically for the current Git checkout
go tool anubis \
--bind=./anubis.sock \
--bind-network=unix \
--socket-mode=0700 \
--policy-fname=../anubis_configs/aggressive_403.yaml \
--target=unix://$(pwd)/unixhttpd.sock &

# A simple TLS terminator that forwards to Anubis, which will forward to
# unixhttpd
go run ../cmd/relayd \
--proxy-to=unix://./anubis.sock \
--cert-dir=../pki/relayd.local.cetacean.club &

export NODE_TLS_REJECT_UNAUTHORIZED=0

backoff-retry node test.mjs
Loading