Add secure Node image webhook service
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
FROM nginx:1.29.5-alpine@sha256:1eff5a5f3fcf8431a0abb7eddf5471fec24e5e1905a2581aeacdb07a4479b92b
|
||||
|
||||
COPY templates/default.conf.template /etc/image/default.conf.template
|
||||
COPY entrypoint.sh /usr/local/bin/image-web-entrypoint
|
||||
RUN chmod 0555 /usr/local/bin/image-web-entrypoint
|
||||
|
||||
USER nginx
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/usr/local/bin/image-web-entrypoint"]
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ -z "${CADDY_SOURCE_CIDR:-}" ]; then
|
||||
echo "CADDY_SOURCE_CIDR is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
envsubst '${CADDY_SOURCE_CIDR}' \
|
||||
< /etc/image/default.conf.template \
|
||||
> /tmp/nginx.conf
|
||||
|
||||
exec nginx -c /tmp/nginx.conf -g 'daemon off;'
|
||||
@@ -0,0 +1,91 @@
|
||||
worker_processes auto;
|
||||
pid /tmp/nginx.pid;
|
||||
error_log /dev/stderr notice;
|
||||
|
||||
events {
|
||||
worker_connections 256;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
access_log /dev/stdout combined;
|
||||
client_body_temp_path /tmp/client_body;
|
||||
proxy_temp_path /tmp/proxy;
|
||||
fastcgi_temp_path /tmp/fastcgi;
|
||||
uwsgi_temp_path /tmp/uwsgi;
|
||||
scgi_temp_path /tmp/scgi;
|
||||
|
||||
server {
|
||||
listen 8080;
|
||||
server_name _;
|
||||
server_tokens off;
|
||||
root /srv/image;
|
||||
disable_symlinks on;
|
||||
|
||||
allow 127.0.0.1;
|
||||
allow ::1;
|
||||
allow ${CADDY_SOURCE_CIDR};
|
||||
deny all;
|
||||
|
||||
location = /healthz {
|
||||
proxy_pass http://image-hook:8081/healthz;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
location = /v1/status {
|
||||
proxy_pass http://image-hook:8081/v1/status;
|
||||
proxy_set_header Host $host;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
}
|
||||
|
||||
location = /v1/inventory {
|
||||
proxy_pass http://image-hook:8081/v1/inventory;
|
||||
proxy_set_header Host $host;
|
||||
proxy_buffering off;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
}
|
||||
|
||||
location = /v1/hooks/gitea {
|
||||
limit_except POST { deny all; }
|
||||
client_max_body_size 1m;
|
||||
proxy_pass http://image-hook:8081/v1/hooks/gitea;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Gitea-Signature $http_x_gitea_signature;
|
||||
proxy_set_header X-Gitea-Event $http_x_gitea_event;
|
||||
proxy_set_header X-Gitea-Delivery $http_x_gitea_delivery;
|
||||
proxy_request_buffering on;
|
||||
}
|
||||
|
||||
location ^~ /v1/admin/ { return 404; }
|
||||
location = /image { return 404; }
|
||||
location = /image/ { return 404; }
|
||||
location ^~ /image/ { rewrite ^/image/(.*)$ /$1 last; }
|
||||
|
||||
location ^~ /game/ {
|
||||
try_files $uri =404;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
}
|
||||
|
||||
location ^~ /icons/ {
|
||||
try_files $uri =404;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
}
|
||||
|
||||
location = /hook/list.json {
|
||||
try_files $uri =404;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
}
|
||||
|
||||
location = /hook/inventory.v2.json {
|
||||
try_files $uri =404;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
}
|
||||
|
||||
location ~ (^|/)\. { return 404; }
|
||||
location ~ \.php$ { return 404; }
|
||||
location / { return 404; }
|
||||
}
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
|
||||
echo "Usage: $0 <branch> [commit]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
repository_dir=$(CDPATH= cd -- "$script_dir/../.." && pwd)
|
||||
branch=$1
|
||||
commit=${2:-}
|
||||
set -- deploy --branch "$branch"
|
||||
if [ -n "$commit" ]; then
|
||||
set -- "$@" --commit "$commit"
|
||||
fi
|
||||
exec docker compose --project-directory "$repository_dir" exec -T image-hook node src/admin-cli.mjs "$@"
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
action=${1:-check}
|
||||
source_cidr=${CADDY_SOURCE_CIDR:-}
|
||||
image_port=${IMAGE_PORT:-8191}
|
||||
chain=SAM_IMAGE_INGRESS
|
||||
|
||||
case "$image_port" in
|
||||
''|*[!0-9]*) echo "IMAGE_PORT must be numeric" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
require_root() {
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "Run this action as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
case "$action" in
|
||||
check)
|
||||
iptables -S DOCKER-USER 2>/dev/null | grep -F "$chain" || true
|
||||
iptables -S "$chain" 2>/dev/null || true
|
||||
;;
|
||||
apply)
|
||||
require_root
|
||||
if [ -z "$source_cidr" ]; then
|
||||
echo "CADDY_SOURCE_CIDR is required" >&2
|
||||
exit 2
|
||||
fi
|
||||
iptables -n -L DOCKER-USER >/dev/null
|
||||
iptables -n -L "$chain" >/dev/null 2>&1 || iptables -N "$chain"
|
||||
iptables -F "$chain"
|
||||
iptables -A "$chain" -s "$source_cidr" -j ACCEPT
|
||||
iptables -A "$chain" -j DROP
|
||||
iptables -C DOCKER-USER -p tcp -m conntrack --ctorigdstport "$image_port" -j "$chain" 2>/dev/null \
|
||||
|| iptables -I DOCKER-USER 1 -p tcp -m conntrack --ctorigdstport "$image_port" -j "$chain"
|
||||
;;
|
||||
remove)
|
||||
require_root
|
||||
while iptables -C DOCKER-USER -p tcp -m conntrack --ctorigdstport "$image_port" -j "$chain" 2>/dev/null; do
|
||||
iptables -D DOCKER-USER -p tcp -m conntrack --ctorigdstport "$image_port" -j "$chain"
|
||||
done
|
||||
if iptables -n -L "$chain" >/dev/null 2>&1; then
|
||||
iptables -F "$chain"
|
||||
iptables -X "$chain"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [check|apply|remove]" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
repository_dir=$(CDPATH= cd -- "$script_dir/../.." && pwd)
|
||||
secret_dir="$repository_dir/secrets"
|
||||
state_dir="$repository_dir/runtime-data"
|
||||
|
||||
umask 077
|
||||
mkdir -p "$secret_dir"
|
||||
mkdir -p "$state_dir"
|
||||
for name in gitea_webhook_secret image_admin_secret; do
|
||||
path="$secret_dir/$name"
|
||||
if [ ! -e "$path" ]; then
|
||||
openssl rand -hex 32 > "$path"
|
||||
fi
|
||||
chmod 600 "$path"
|
||||
done
|
||||
chmod 700 "$state_dir"
|
||||
|
||||
echo "Secret files are ready in $secret_dir (values not printed)."
|
||||
Reference in New Issue
Block a user