mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-18 21:34:37 +03:00
feat: Docker setup for rosenpass with brokers
This commit is contained in:
9
examples/broker-in-podman-container/config/config.toml
Normal file
9
examples/broker-in-podman-container/config/config.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
public_key = "./pk1"
|
||||||
|
secret_key = "./sk1"
|
||||||
|
listen = ["[::]:9999"]
|
||||||
|
verbosity = "Verbose"
|
||||||
|
|
||||||
|
[[peers]]
|
||||||
|
public_key = "./pk2"
|
||||||
|
device = "YOUR WIREGUARD DEVICE"
|
||||||
|
peer = "YOUR PEER PK"
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
version: "3.8"
|
|
||||||
services:
|
|
||||||
rosenpass:
|
|
||||||
build:
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
env:
|
|
||||||
RUST_LOG: trace
|
|
||||||
volumes:
|
|
||||||
./peer-a:/config
|
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
rosenpass:
|
||||||
|
build: ../rosenpass/
|
||||||
|
command: rosenpass
|
||||||
|
ports:
|
||||||
|
- name: rosenpass-ipv4
|
||||||
|
target: 9999
|
||||||
|
host_ip: 127.0.0.1
|
||||||
|
published: 9999
|
||||||
|
protocol: udp
|
||||||
|
mode: host
|
||||||
|
- name: rosenpass-ipv4
|
||||||
|
target: 9999
|
||||||
|
host_ip: '[::1]'
|
||||||
|
published: 9999
|
||||||
|
protocol: udp
|
||||||
|
mode: host
|
||||||
|
environment:
|
||||||
|
RUST_LOG: info
|
||||||
|
#DEBUG_ENTRYPOINT: 1
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
volumes:
|
||||||
|
- ../socket:/socket:ro
|
||||||
|
- ../config:/config:ro
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
rosenpass:
|
||||||
|
build: ../rosenpass
|
||||||
|
command: psk_broker
|
||||||
|
environment:
|
||||||
|
RUST_LOG: info
|
||||||
|
USER_GAINS_CAP_NET_ADMIN: 1
|
||||||
|
#DEBUG_ENTRYPOINT: 1
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
volumes:
|
||||||
|
- ../socket:/socket:rw
|
||||||
|
network_mode: host
|
||||||
@@ -21,13 +21,12 @@ RUN cd ~rosenpass \
|
|||||||
&& rm -R rosenpass-source
|
&& rm -R rosenpass-source
|
||||||
USER root:root
|
USER root:root
|
||||||
|
|
||||||
RUN apt-get install -y iproute2 wireguard-tools
|
# TODO: Is this proper handling of ambient capabilities?
|
||||||
|
RUN setcap CAP_NET_ADMIN=+ep ~rosenpass/usr/bin/rosenpass-wireguard-broker-privileged
|
||||||
RUN setcap CAP_NET_ADMIN=+ip ~rosenpass/usr/bin/rosenpass-wireguard-broker-privileged
|
|
||||||
|
|
||||||
VOLUME /config
|
VOLUME /config
|
||||||
COPY entrypoint.sh /usr/local/sbin/docker_entrypoint
|
COPY ./entrypoint.sh /usr/local/sbin/docker_entrypoint
|
||||||
COPY fd_passing.pl /usr/local/sbin/fd_passing
|
COPY ./fd_passing.pl /usr/local/sbin/fd_passing
|
||||||
RUN chmod a+x /usr/local/sbin/docker_entrypoint /usr/local/sbin/fd_passing
|
RUN chmod a+x /usr/local/sbin/docker_entrypoint /usr/local/sbin/fd_passing
|
||||||
ENTRYPOINT ["/usr/local/sbin/docker_entrypoint"]
|
ENTRYPOINT ["/usr/local/sbin/docker_entrypoint"]
|
||||||
|
|
||||||
187
examples/broker-in-podman-container/rosenpass/entrypoint.sh
Normal file
187
examples/broker-in-podman-container/rosenpass/entrypoint.sh
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
set -e # Needed by bail()
|
||||||
|
|
||||||
|
log() {
|
||||||
|
local lvl; lvl="${1}"; shift || bail "log()" "USAGE: log LEVEL CONTEXT MSG..."
|
||||||
|
local ctx; ctx="${1}"; shift || bail "log()" "USAGE: log LEVEL CONTEXT MSG..."
|
||||||
|
echo >&2 "[entrypoint.sh/${ctx} ${lvl}]:" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug() {
|
||||||
|
if [[ -n "${DEBUG_ENTRYPOINT}" ]]; then
|
||||||
|
log "DEBUG" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info() {
|
||||||
|
log "INFO" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_err() {
|
||||||
|
log "ERROR" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
exc() {
|
||||||
|
local ctx; ctx="${1}"; shift || bail "exc()" "USAGE: exc CONTEXT CMD..."
|
||||||
|
log_debug '$' "$@"
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
bail() {
|
||||||
|
local ctx; ctx="${1}"; shift || bail "bail()" "USAGE: bail CONTEXT MSG..."
|
||||||
|
(( "$#" != 0 )) || bail "${ctx}" $'USAGE: bail CONTEXT MSG... # Bail called without parameters! Please use error messages dear developer.'
|
||||||
|
log_err "${ctx}" "$@"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
join() {
|
||||||
|
local delim; delim="$1"; shift || bail "join()" "USAGE: join DELIM ELMS..."
|
||||||
|
local tmp fst
|
||||||
|
fst="true"
|
||||||
|
for tmp in "$@"; do
|
||||||
|
if [[ "${fst}" = "true" ]]; then
|
||||||
|
printf "%s" "${tmp}"
|
||||||
|
fst=""
|
||||||
|
else
|
||||||
|
printf "%s%s" "${delim}" "${tmp}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Shred files after they where red (recursively)
|
||||||
|
# USAGE: $ burn_after_reading DIR
|
||||||
|
burn_after_reading() {
|
||||||
|
local dir; dir="$1"; shift || bail "join()" "USAGE: burn_after_reading DIR"
|
||||||
|
|
||||||
|
log_info burn_after_reading "Started for ${dir}"
|
||||||
|
|
||||||
|
# Load the list of configuration files
|
||||||
|
local -a files_arr # Array
|
||||||
|
readarray -td $'\0' files_arr < <(find "${dir}" -type f -print0)
|
||||||
|
|
||||||
|
# Convert configuration file list to associative array
|
||||||
|
local file
|
||||||
|
local -A files_todo # Associative array
|
||||||
|
for file in "${files_arr[@]}"; do
|
||||||
|
files_todo["${file}"]="1"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Watch for closed files
|
||||||
|
local file
|
||||||
|
# The --exclude '/$' excludes directories
|
||||||
|
inotifywait --quiet --monitor --event close_nowrite --exclude '/$' --recursive . --no-newline --format "%w%f%0" \
|
||||||
|
| while read -d $'\0' -r file; do
|
||||||
|
|
||||||
|
# Check if the file is in the todo list, if yes, erase it
|
||||||
|
if [[ "${files_todo["${file}"]+1}" = "1" ]]; then
|
||||||
|
log_info burn_after_reading "File loaded from configuration; removing now: ${file}";
|
||||||
|
shred "${file}"
|
||||||
|
# Clear from the todo list; What in the devils name is this quoting style bash
|
||||||
|
unset 'files_todo["${file}"]'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We're done if the todo list is empty
|
||||||
|
if (( "${#files_todo[@]}" == 0 )); then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
as_user() {
|
||||||
|
local -a cmd_prefix
|
||||||
|
if [[ "$1" = "--exec" ]]; then
|
||||||
|
cmd_prefix=("exec")
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
local user; user="$1"; shift || bail "as_user()" "USAGE: as_user USER CMD..."
|
||||||
|
(( "$#" > 0 )) || bail "as_user()" "USAGE: as_user USER CMD..."
|
||||||
|
|
||||||
|
if [[ -n "${USER_GAINS_CAP_NET_ADMIN}" ]]; then # TODO: Dirty to do this here; use --cap-net-admin or something?
|
||||||
|
exc "as_user()" "${cmd_prefix[@]}" \
|
||||||
|
capsh --caps="cap_net_admin+eip cap_setuid,cap_setgid+ep" --keep=1 \
|
||||||
|
--user="${user}" --addamb=cap_net_admin -- -c 'exec "$@"' -- "$@"
|
||||||
|
elif [[ "${user}" = "$(whoami)" ]]; then
|
||||||
|
exc "as_user()" "${cmd_prefix[@]}" "$@"
|
||||||
|
else
|
||||||
|
exc "as_user()" "${cmd_prefix[@]}" runuser -u "${user}" -- "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
bail "USAGE: ${SCRIPT} rosenpass|psk_broker"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_internal() {
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_run_command() {
|
||||||
|
exc "run_command()" as_user --exec "${SWITCH_USER}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_psk_broker() {
|
||||||
|
exc "psk_broker()" exec \
|
||||||
|
fd_passing --listen /socket/psk_broker.sock \
|
||||||
|
"$SCRIPT" internal as_user --exec "${SWITCH_USER}" \
|
||||||
|
rosenpass-wireguard-broker-socket-handler --listen-fd
|
||||||
|
}
|
||||||
|
|
||||||
|
rosenpass_start_with_socket_fd() {
|
||||||
|
local fd; fd="$1"; shift || bail "rosenpass_start_with_socket_fd()" "USAGE: rosenpass_start_with_socket_fd PSK_BROKER_FD"
|
||||||
|
exc "rosenpass_start_with_socket_fd()" exec \
|
||||||
|
rosenpass --psk-broker-fd "$fd" exchange-config /config/config.toml
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_rosenpass() {
|
||||||
|
test -z "${USER_GAINS_CAP_NET_ADMIN}" || bail "rosenpass()" "USER_GAINS_CAP_NET_ADMIN should be unset. The rosenpass instance doing key exchanges should not have network admin privileges!"
|
||||||
|
exc "psk_broker()" exec \
|
||||||
|
fd_passing --connect /socket/psk_broker.sock \
|
||||||
|
"$SCRIPT" internal as_user --exec "${SWITCH_USER}" \
|
||||||
|
"$SCRIPT" internal rosenpass_start_with_socket_fd
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local command; command="$1"; shift || usage
|
||||||
|
case "${command}" in
|
||||||
|
internal) cmd_internal "$@" ;;
|
||||||
|
run_command) ;;
|
||||||
|
psk_broker) ;;
|
||||||
|
rosenpass) ;;
|
||||||
|
*) usage;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exc "main()" umask u=rw,og=
|
||||||
|
exc "main()" cp -R "${CONFIG_MOUNT}" "${CONFIG_TMP}"
|
||||||
|
exc "main()" chmod -R u+X "${CONFIG_TMP}"
|
||||||
|
exc "main()" chown -R rosenpass:rosenpass "${CONFIG_TMP}"
|
||||||
|
# TODO: How can we do this? We should probably use a dedicated config broker.
|
||||||
|
#exc "main()" umount "${CONFIG_MOUNT}"
|
||||||
|
exc "main()" cd "${CONFIG_TMP}"
|
||||||
|
|
||||||
|
if [[ -n "${BURN_AFTER_READING}" ]]; then
|
||||||
|
( burn_after_reading /dev/shm/rosenpass-config )&
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -a path_cpy extra_path_cpy
|
||||||
|
mapfile -td ':' path_cpy < <(echo -n "$PATH")
|
||||||
|
mapfile -td ':' extra_path_cpy < <(echo -n "$EXTRA_PATH")
|
||||||
|
PATH="$(join ":" "${extra_path_cpy[@]}" "${path_cpy[@]}")"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
exc "main()" "cmd_${command}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT="$0"
|
||||||
|
|
||||||
|
# Config
|
||||||
|
CONFIG_MOUNT="${CONFIG_MOUNT:-/config}"
|
||||||
|
CONFIG_TMP="${CONFIG_TMP:-/dev/shm/rosenpass-config}"
|
||||||
|
BURN_AFTER_READING="${BURN_AFTER_READING:-true}"
|
||||||
|
SWITCH_USER="${SWITCH_USER:-rosenpass}"
|
||||||
|
#USER_GAINS_CAP_NET_ADMIN="${USER_GAINS_CAP_NET_ADMIN}"
|
||||||
|
EXTRA_PATH="${EXTRA_PATH:-"$(eval echo ~rosenpass)/usr/bin"}"
|
||||||
|
|
||||||
|
main "$@"
|
||||||
38
examples/broker-in-podman-container/rosenpass/fd_passing.pl
Executable file
38
examples/broker-in-podman-container/rosenpass/fd_passing.pl
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#! /usr/bin/perl
|
||||||
|
|
||||||
|
use Fcntl;
|
||||||
|
use IO::Socket::UNIX;
|
||||||
|
|
||||||
|
my $usage = "[$0] Usage: $0 SOCKETPATH [--connect|--listen] CMD...";
|
||||||
|
|
||||||
|
my $mode = shift or die($usage);
|
||||||
|
my $sopath = shift or die($usage);
|
||||||
|
|
||||||
|
|
||||||
|
my $listen;
|
||||||
|
if ($mode eq "--listen") {
|
||||||
|
$listen = 1;
|
||||||
|
} elsif ($mode eq "--connect") {
|
||||||
|
$listen = 0;
|
||||||
|
} else {
|
||||||
|
die($usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $socket;
|
||||||
|
if ($listen == 1) {
|
||||||
|
$socket = IO::Socket::UNIX->new(
|
||||||
|
Type => SOCK_STREAM(),
|
||||||
|
Local => $sopath,
|
||||||
|
Listen => 1,
|
||||||
|
) or die "[$0] Error listening on socket socket: $!";
|
||||||
|
} else {
|
||||||
|
$socket = IO::Socket::UNIX->new(
|
||||||
|
Type => SOCK_STREAM(),
|
||||||
|
Peer => $sopath,
|
||||||
|
) or die "[$0] Error listening on socket socket: $!";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $fd_flags = $socket->fcntl(F_GETFD, 0) or die "[$0] fcntl F_GETFD: $!";
|
||||||
|
$socket->fcntl(F_SETFD, $fd_flags & ~FD_CLOEXEC) or die "[$0] fcntl F_SETFD: $!";
|
||||||
|
|
||||||
|
exec(@ARGV, $socket->fileno); # pass it on the command line
|
||||||
0
examples/broker-in-podman-container/socket/.gitignore
vendored
Normal file
0
examples/broker-in-podman-container/socket/.gitignore
vendored
Normal file
Reference in New Issue
Block a user