initial commit
This commit is contained in:
12
scripts/angie
Executable file
12
scripts/angie
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
|
||||
## hardcoded configuration directory
|
||||
d=/run/ngx/conf
|
||||
|
||||
## reparse PATH: remove /usr/local/sbin
|
||||
PATH=$(printf 'x:%s:x' "${PATH}" | sed -zE 's#:/usr/local/sbin/?:#:#g;s/^x://;s/:x$//')
|
||||
export PATH
|
||||
|
||||
exec env -C $d /usr/sbin/angie -p $d -c $d/angie.conf -e stderr --log-level=info -g 'error_log stderr info;' "$@"
|
||||
exit 126
|
26
scripts/angie-builtin-modules.sh
Executable file
26
scripts/angie-builtin-modules.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
set -f
|
||||
|
||||
conf_dir='/etc/angie.dist'
|
||||
|
||||
## Angie: unset core variables
|
||||
unset ANGIE ANGIE_BPF_MAPS
|
||||
|
||||
t=$(mktemp) || exit $?
|
||||
|
||||
/usr/sbin/angie -m 2>&1 | tee "$t" >/dev/null
|
||||
|
||||
sed -En '/^ngx_(http|mail|stream)/d;/^ngx_(.+)_module$/{s//\1/;s/_filter$//;s/_/-/g;p}' < "$t" \
|
||||
| sort -uV > "${conf_dir}/builtin.core"
|
||||
|
||||
for m in http mail stream ; do
|
||||
sed -En '/^ngx_'"${m}"'_(.+)_module$/{s//\1/;s/_filter$//;s/_/-/g;p}' < "$t" \
|
||||
| sort -uV > "${conf_dir}/builtin.$m"
|
||||
done
|
||||
|
||||
rm -f "$t" ; unset t
|
||||
|
||||
## merely debug output
|
||||
for m in core http mail stream ; do
|
||||
echo "${conf_dir}/builtin.$m"
|
||||
done | xargs -r ls -ld >&2
|
15
scripts/angie-reload.sh
Executable file
15
scripts/angie-reload.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
|
||||
pid_file="${1:-/run/ngx/angie.pid}"
|
||||
[ -f "${pid_file}" ] || {
|
||||
echo "Angie is not running? (${pid_file} not found)"
|
||||
exit 0
|
||||
}
|
||||
[ -s "${pid_file}" ] || {
|
||||
echo "Angie is not running? (${pid_file} is empty)"
|
||||
exit 1
|
||||
}
|
||||
pid=$(cat "${pid_file}") || exit 1
|
||||
|
||||
exec env kill -SIGHUP "${pid}"
|
56
scripts/apt-clean.sh
Executable file
56
scripts/apt-clean.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
set -f
|
||||
|
||||
## apt
|
||||
find /var/cache/apt/ ! -type d ! -name 'lock' -delete
|
||||
find /var/lib/apt/ ! -type d -wholename '/var/lib/apt/listchanges*' -delete
|
||||
find /var/lib/apt/lists/ ! -type d ! -name 'lock' -delete
|
||||
find /var/log/ ! -type d -wholename '/var/log/apt/*' -delete
|
||||
find /var/log/ ! -type d -wholename '/var/log/aptitude*' -delete
|
||||
|
||||
## dpkg
|
||||
: "${DPKG_ADMINDIR:=/var/lib/dpkg}"
|
||||
truncate -s 0 "${DPKG_ADMINDIR}/available"
|
||||
find "${DPKG_ADMINDIR}/" ! -type d -wholename "${DPKG_ADMINDIR}/*-old" -delete
|
||||
find /var/log/ ! -type d -wholename '/var/log/alternatives.log' -delete
|
||||
find /var/log/ ! -type d -wholename '/var/log/dpkg.log' -delete
|
||||
|
||||
## DONT DO THIS AT HOME!
|
||||
find "${DPKG_ADMINDIR}/" ! -type d -wholename "${DPKG_ADMINDIR}/info/*.symbols" -delete
|
||||
|
||||
## debconf
|
||||
find /var/cache/debconf/ ! -type d -wholename '/var/cache/debconf/*-old' -delete
|
||||
|
||||
__t=$(mktemp) ; : "${__t:?}"
|
||||
debconf_trim_i18n() {
|
||||
mawk 'BEGIN { m = 0; }
|
||||
$0 == "" { print; }
|
||||
/^[^[:space:]]/ {
|
||||
if ($1 ~ "\.[Uu][Tt][Ff]-?8:") {
|
||||
m = 1;
|
||||
next;
|
||||
}
|
||||
m = 0;
|
||||
print $0;
|
||||
}
|
||||
/^[[:space:]]/ {
|
||||
if (m == 1) next;
|
||||
print $0;
|
||||
}' < "$1" > "${__t}"
|
||||
cat < "${__t}" > "$1"
|
||||
}
|
||||
|
||||
debconf_trim_i18n /var/cache/debconf/templates.dat
|
||||
while read -r tmpl ; do
|
||||
[ -n "${tmpl}" ] || continue
|
||||
[ -s "${tmpl}" ] || continue
|
||||
debconf_trim_i18n "${tmpl}"
|
||||
done <<EOF
|
||||
$(find "${DPKG_ADMINDIR}/info/" -type f -name '*.templates' | sort -V)
|
||||
EOF
|
||||
rm -f "${__t}" ; unset __t
|
||||
|
||||
## misc
|
||||
rm -f /var/cache/ldconfig/aux-cache
|
||||
|
||||
exit 0
|
8
scripts/apt-env.sh
Executable file
8
scripts/apt-env.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -a
|
||||
DEBCONF_NONINTERACTIVE_SEEN=true
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
DEBIAN_PRIORITY=critical
|
||||
TERM=linux
|
||||
set +a
|
||||
exec "$@"
|
267
scripts/apt-install-angie-mod.sh
Executable file
267
scripts/apt-install-angie-mod.sh
Executable file
@@ -0,0 +1,267 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
|
||||
[ $# -gt 0 ] || exit 1
|
||||
|
||||
set -a
|
||||
ANGIE_MODULES_DIR="${ANGIE_MODULES_DIR:-/usr/lib/angie/modules}"
|
||||
set +a
|
||||
|
||||
unset NGX_DEBUG
|
||||
NGX_DEBUG=$(/usr/sbin/angie --build-env 2>&1 | mawk '$1=="DEBUG:" {print $2;exit;}')
|
||||
NGX_DEBUG="${NGX_DEBUG:-0}"
|
||||
case "${NGX_DEBUG}" in
|
||||
0 | 1 ) ;;
|
||||
* ) NGX_DEBUG=1 ;;
|
||||
esac
|
||||
|
||||
unset NGX_PRO
|
||||
NGX_PRO=$(/usr/sbin/angie -v 2>&1 | mawk 'NR==1 {print $4;exit;}' | tr '[:upper:]' '[:lower:]')
|
||||
NGX_PRO="${NGX_PRO:-0}"
|
||||
case "${NGX_PRO}" in
|
||||
'(pro)' ) NGX_PRO=1 ;;
|
||||
* ) NGX_PRO=0 ;;
|
||||
esac
|
||||
|
||||
## "fqpn" stands for "Full Qualified Package Name"
|
||||
## Angie OSS: angie-module-<name>
|
||||
## Angie PRO: angie-pro-module-<name>
|
||||
if [ ${NGX_PRO} = 1 ] ; then
|
||||
fqpn() { echo "angie-pro-module-$1" ; }
|
||||
else
|
||||
fqpn() { echo "angie-module-$1" ; }
|
||||
fi
|
||||
|
||||
is_pkg_installed() {
|
||||
case "$(dpkg-query -W -f='${Status}' "$1" 2>/dev/null)" in
|
||||
"install ok installed" )
|
||||
## package is installed normally
|
||||
return 0
|
||||
;;
|
||||
"hold ok installed" )
|
||||
## package is installed and marked as "hold"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
is_mod_installed() {
|
||||
is_pkg_installed "$(fqpn "$1")" || return 1
|
||||
}
|
||||
|
||||
## produce package list
|
||||
mods=
|
||||
for i ; do
|
||||
[ -n "$i" ] || continue
|
||||
|
||||
printf '%s' "$i" | grep -zEq '^[a-z0-9.+-]+$' || {
|
||||
env printf 'package name %q is not legal, quitting!\n' "$i" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if is_mod_installed "$i" ; then
|
||||
echo "package '$i' is already installed, skipping" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
mods="${mods}${mods:+ }$i"
|
||||
done
|
||||
|
||||
[ -n "${mods}" ] || exit 0
|
||||
|
||||
list_have_item() {
|
||||
[ -n "$1" ] || return 1
|
||||
[ -n "$2" ] || return 1
|
||||
case " $1 " in
|
||||
*" $2 "* ) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
normalize_list() {
|
||||
[ -n "$1" ] || return 0
|
||||
|
||||
printf '%s' "$1" \
|
||||
| sed -zE 's/[[:space:]]+/ /g;s/^ //;s/ $//'
|
||||
}
|
||||
|
||||
sort_dedup_list() {
|
||||
[ -n "$1" ] || return 0
|
||||
|
||||
printf '%s' "$1" \
|
||||
| tr -s '[:space:]' '\n' | sort -uV \
|
||||
| sed -zE 's/[[:space:]]+/ /g;s/^ //;s/ $//'
|
||||
}
|
||||
|
||||
mods=$(sort_dedup_list "${mods}")
|
||||
|
||||
## angie-module-lua: depends on angie-module-ndk
|
||||
## angie-module-set-misc: depends on angie-module-ndk
|
||||
unset want_ndk ; want_ndk=0
|
||||
if list_have_item "${mods}" lua ; then
|
||||
want_ndk=1
|
||||
elif list_have_item "${mods}" set-misc ; then
|
||||
want_ndk=1
|
||||
fi
|
||||
if [ ${want_ndk} = 1 ] ; then
|
||||
while : ; do
|
||||
if list_have_item "${mods}" ndk ; then break ; fi
|
||||
if is_mod_installed ndk ; then break ; fi
|
||||
mods="${mods} ndk"
|
||||
break ; done
|
||||
fi
|
||||
|
||||
## angie-module-wamr: depends on angie-module-wasm
|
||||
## angie-module-wasmtime: depends on angie-module-wasm
|
||||
unset want_wasm ; want_wasm=0
|
||||
if list_have_item "${mods}" wamr ; then
|
||||
want_wasm=1
|
||||
elif list_have_item "${mods}" wasmtime ; then
|
||||
want_wasm=1
|
||||
fi
|
||||
if [ ${want_wasm} = 1 ] ; then
|
||||
while : ; do
|
||||
if list_have_item "${mods}" wasm ; then break ; fi
|
||||
if is_mod_installed wasm ; then break ; fi
|
||||
mods="${mods} wasm"
|
||||
break ; done
|
||||
fi
|
||||
|
||||
## kind of quirk
|
||||
dirs='cache lib log'
|
||||
for n in ${dirs} ; do
|
||||
d="/run/ngx/$n"
|
||||
[ -d "$d" ] || install -d "$d"
|
||||
done
|
||||
|
||||
pkgs=
|
||||
for m in ${mods} ; do
|
||||
pkgs="${pkgs}${pkgs:+ }$(fqpn "$m")"
|
||||
done
|
||||
apt-install.sh ${pkgs}
|
||||
|
||||
ANGIE_DIST_MODCONF_DIR=/etc/angie.dist/mod
|
||||
ANGIE_MODCONF_DIR=/etc/angie/mod
|
||||
[ -d "${ANGIE_MODCONF_DIR}" ] || install -d "${ANGIE_MODCONF_DIR}"
|
||||
|
||||
have_preseed() {
|
||||
if [ -e "${ANGIE_DIST_MODCONF_DIR}/.$1.preseed" ] ; then
|
||||
return 0
|
||||
fi
|
||||
if [ -e "${ANGIE_MODCONF_DIR}/.$1.preseed" ] ; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
list_ngx_modules() {
|
||||
set +e
|
||||
dpkg-query -L "$1" \
|
||||
| grep -F -e "${ANGIE_MODULES_DIR}/" \
|
||||
| grep -E -e '/[^/]+_module(-debug)?\.so$' \
|
||||
| sed -E '\,^(.+)-debug\.so$,{p;s//\1.so/;p;d}' \
|
||||
| sort -uV \
|
||||
| xargs -r ls -U1d 2>/dev/null
|
||||
set -e
|
||||
}
|
||||
|
||||
is_same_file() {
|
||||
find -L "$1" -samefile "$2" -printf . -quit 2>/dev/null | grep -Fq . || return 1
|
||||
}
|
||||
|
||||
gen_mod_config() {
|
||||
if [ -s "$2" ] ; then
|
||||
printf '%s: configuration already exists: %s\n' "$1" "$2" >&2
|
||||
return
|
||||
fi
|
||||
|
||||
[ -n "$3" ] || return
|
||||
|
||||
local __m
|
||||
for __m in $3 ; do
|
||||
echo "load_module ${__m};"
|
||||
done > "$2"
|
||||
}
|
||||
|
||||
for m in ${mods} ; do
|
||||
[ -n "$m" ] || continue
|
||||
p=$(fqpn "$m")
|
||||
|
||||
## adjust modules:
|
||||
## - remove debug module if not in debug image
|
||||
## - move debug module to usual location otherwise
|
||||
while read -r fmod_debug ; do
|
||||
# [ -n "${fmod_debug}" ] || continue
|
||||
case "${fmod_debug}" in
|
||||
*-debug.so ) ;;
|
||||
* ) continue ;;
|
||||
esac
|
||||
fmod="${fmod_debug%-debug.so}.so"
|
||||
|
||||
if [ "${NGX_DEBUG}" = 0 ] ; then
|
||||
if [ -f "${fmod}" ] ; then
|
||||
fmod_real=$(readlink -f "${fmod}")
|
||||
else
|
||||
env printf 'missing (non-debug) file: %q\n' "${fmod}" >&2
|
||||
env printf 'falling back to (debug) file: %q\n' "${fmod_debug}" >&2
|
||||
fmod_real=$(readlink -f "${fmod_debug}")
|
||||
fi
|
||||
else
|
||||
fmod_real=$(readlink -f "${fmod_debug}")
|
||||
fi
|
||||
[ -n "${fmod_real}" ] || exit 1
|
||||
|
||||
fmod_tmp=$(mktemp -u "${fmod}.XXXXXXXXXX")
|
||||
ln "${fmod_real}" "${fmod_tmp}"
|
||||
rm -f "${fmod}" "${fmod_debug}"
|
||||
mv -f "${fmod_tmp}" "${fmod}"
|
||||
|
||||
apt-mark hold "$p" || :
|
||||
done <<-EOF
|
||||
$(list_ngx_modules "$p")
|
||||
EOF
|
||||
|
||||
if have_preseed "$m" ; then
|
||||
printf '%s: skipping generation of module load config (preseed is in effect)\n' "$p" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
## produce attachable module configs
|
||||
http_modules= ; mail_modules= ; stream_modules=
|
||||
while read -r fmod ; do
|
||||
[ -n "${fmod}" ] || continue
|
||||
|
||||
fmod_short="modules/${fmod#"${ANGIE_MODULES_DIR}/"}"
|
||||
fname=${fmod##*/}
|
||||
case "${fname}" in
|
||||
ngx_http_* )
|
||||
http_modules="${http_modules}${http_modules:+ }${fmod_short}"
|
||||
;;
|
||||
ngx_mail_* )
|
||||
mail_modules="${mail_modules}${mail_modules:+ }${fmod_short}"
|
||||
;;
|
||||
ngx_stream_* )
|
||||
stream_modules="${stream_modules}${stream_modules:+ }${fmod_short}"
|
||||
;;
|
||||
## damn NDK
|
||||
ndk_http_* )
|
||||
http_modules="${http_modules}${http_modules:+ }${fmod_short}"
|
||||
;;
|
||||
* )
|
||||
env printf '%s: unable to determine module type for file (skipping): %q\n' "$p" "${fmod}" >&2
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
done <<-EOF
|
||||
$(list_ngx_modules "$p")
|
||||
EOF
|
||||
|
||||
[ -z "${http_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/http-$m.conf" "${http_modules}"
|
||||
[ -z "${mail_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/mail-$m.conf" "${mail_modules}"
|
||||
[ -z "${stream_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/stream-$m.conf" "${stream_modules}"
|
||||
|
||||
done
|
||||
|
||||
echo "extra files/directories (if any):" >&2
|
||||
find /run/ngx/cache/ /run/ngx/lib/ /run/ngx/log/ -mindepth 1 -exec ls -ld {} + >&2
|
45
scripts/apt-install.sh
Executable file
45
scripts/apt-install.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
|
||||
find_fresh_ts() {
|
||||
{
|
||||
find "$@" -exec stat -c '%Y' '{}' '+' 2>/dev/null || :
|
||||
# duck and cover!
|
||||
echo 1
|
||||
} | sort -rn | head -n 1
|
||||
}
|
||||
|
||||
_apt_update() {
|
||||
# update package lists; may fail sometimes,
|
||||
# e.g. soon-to-release channels like Debian "bullseye" @ 22.04.2021
|
||||
|
||||
# (wannabe) smart package list update
|
||||
ts_sources=$(find_fresh_ts /etc/apt/ -follow -regextype egrep -regex '.+\.(list|sources)$' -type f)
|
||||
ts_lists=$(find_fresh_ts /var/lib/apt/lists/ -maxdepth 1 -regextype egrep -regex '.+_Packages(\.(bz2|gz|lz[4o]|xz|zstd?))?$' -type f)
|
||||
if [ ${ts_sources} -gt ${ts_lists} ] ; then
|
||||
apt-env.sh apt-get update
|
||||
fi
|
||||
}
|
||||
|
||||
_dpkg_avail_hack() {
|
||||
: "${DPKG_ADMINDIR:=/var/lib/dpkg}"
|
||||
VERSION_CODENAME=$(. /etc/os-release ; printf '%s' "${VERSION_CODENAME}") || :
|
||||
f="${DPKG_ADMINDIR}/available"
|
||||
# if ${VERSION_CODENAME} is empty then we're on Debian sid or so :)
|
||||
case "${VERSION_CODENAME}" in
|
||||
stretch | buster | bionic | focal )
|
||||
# ref: https://unix.stackexchange.com/a/271387/49297
|
||||
if [ -s "$f" ] ; then
|
||||
return
|
||||
fi
|
||||
/usr/lib/dpkg/methods/apt/update "${DPKG_ADMINDIR}" apt apt
|
||||
;;
|
||||
* )
|
||||
touch "$f"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_apt_update
|
||||
_dpkg_avail_hack
|
||||
exec apt-env.sh apt-get install -y --no-install-recommends --no-install-suggests "$@"
|
5
scripts/apt-remove.sh
Executable file
5
scripts/apt-remove.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
|
||||
apt-env.sh apt-get purge -y --allow-remove-essential "$@"
|
||||
exec apt-env.sh apt-get autopurge -y
|
7
scripts/divert-rm.sh
Executable file
7
scripts/divert-rm.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
: "${1:?}"
|
||||
d=$(printf '%s' "/run/ngx/dpkg-divert/$1" | tr -s '/')
|
||||
mkdir -p "${d%/*}"
|
||||
dpkg-divert --divert "$d" --rename "$1" 2>/dev/null
|
||||
rm -f "$d"
|
24
scripts/dpkg-search.sh
Executable file
24
scripts/dpkg-search.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
: "${1:?}"
|
||||
|
||||
if dpkg-query --search "$1" ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
*\** | *\?* )
|
||||
env printf '%s does not support globs: %q\n' "${0##*/}" "$1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
while read -r f ; do
|
||||
[ -n "$f" ] || continue
|
||||
dpkg-query --search "$f" || continue
|
||||
exit 0
|
||||
done <<EOF
|
||||
$(set +e ; find / -xdev -follow -samefile "$1" 2>/dev/null | grep -Fxv -e "$1")
|
||||
EOF
|
||||
|
||||
exit 1
|
23
scripts/envsubst-args.sh
Executable file
23
scripts/envsubst-args.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
set -f
|
||||
|
||||
sed -znE '/^([^=]+)=.*$/s,,\1,p' /proc/$$/environ \
|
||||
| sed -zE \
|
||||
-e '/^_$/d' \
|
||||
-e '/^ANGIE(|_BPF_MAPS)$/d' \
|
||||
-e '/^__IEP_/d;/^IEP_$/d' \
|
||||
-e '/^NGX_STATIC_/d' \
|
||||
-e '/^ENVSUBST_/d' \
|
||||
-e '/^J2CFG_/d' \
|
||||
| {
|
||||
if [ -n "${ENVSUBST_EXCLUDE_REGEX:-}" ] ; then
|
||||
grep -zEv -e "${ENVSUBST_EXCLUDE_REGEX}"
|
||||
elif [ -n "${ENVSUBST_INCLUDE_REGEX:-}" ] ; then
|
||||
grep -zE -e "${ENVSUBST_INCLUDE_REGEX}"
|
||||
else
|
||||
cat
|
||||
fi
|
||||
} \
|
||||
| sort -zV \
|
||||
| xargs -0 -r printf '${%s} ' \
|
||||
| sed -zE 's/ $//'
|
12
scripts/envsubst.sh
Executable file
12
scripts/envsubst.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
set -f
|
||||
|
||||
while [ -n "${ENVSUBST_ARGS}" ] ; do
|
||||
[ -f "${ENVSUBST_ARGS}" ] || break
|
||||
[ -s "${ENVSUBST_ARGS}" ] || break
|
||||
|
||||
exec envsubst "$(cat "${ENVSUBST_ARGS}" </dev/null)" "$@"
|
||||
exit 126
|
||||
done
|
||||
|
||||
exec envsubst "$(envsubst-args.sh </dev/null)" "$@"
|
2
scripts/j2cfg-dump
Executable file
2
scripts/j2cfg-dump
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec python3 "/usr/local/lib/j2cfg/${0##*/}.py" "$@"
|
2
scripts/j2cfg-multi
Executable file
2
scripts/j2cfg-multi
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec python3 "/usr/local/lib/j2cfg/${0##*/}.py" "$@"
|
2
scripts/j2cfg-single
Executable file
2
scripts/j2cfg-single
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec python3 "/usr/local/lib/j2cfg/${0##*/}.py" "$@"
|
100
scripts/openssl-cert-auto-pem.sh
Executable file
100
scripts/openssl-cert-auto-pem.sh
Executable file
@@ -0,0 +1,100 @@
|
||||
#!/bin/sh
|
||||
set -f
|
||||
|
||||
[ $# -gt 0 ] || exit 0
|
||||
me=${0##*/}
|
||||
|
||||
[ -n "$1" ] || exit 1
|
||||
[ -f "$1" ] || {
|
||||
env printf '%s: not a file or does not exist: %q\n' "${me}" "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -s "$1" ] || exit 0
|
||||
|
||||
w=$(mktemp -d) || exit 1
|
||||
w_cleanup() {
|
||||
[ -z "$w" ] || ls -lA "$w/" >&2
|
||||
[ -z "$w" ] || rm -rf "$w"
|
||||
unset w
|
||||
exit "${1:-0}"
|
||||
}
|
||||
|
||||
bundle_offsets() {
|
||||
mawk 'BEGIN { OFS = ","; i_begin = 0; }
|
||||
$0 == "-----BEGIN CERTIFICATE-----" {
|
||||
i_begin = NR;
|
||||
}
|
||||
$0 == "-----END CERTIFICATE-----" {
|
||||
if (i_begin > 0) {
|
||||
print i_begin, NR;
|
||||
i_begin = 0;
|
||||
}
|
||||
}' "$1"
|
||||
}
|
||||
|
||||
bundle_fingerprints() {
|
||||
local x f
|
||||
while read -r x ; do
|
||||
[ -n "$x" ] || continue
|
||||
|
||||
f=$(sed -ne "${x}p" "$1" | openssl x509 -noout -fingerprint -sha256)
|
||||
[ -n "$f" ] || f=$(sed -ne "${x}p" "$1" | openssl x509 -noout -fingerprint)
|
||||
[ -n "$f" ] || continue
|
||||
|
||||
printf '%s\n' "$f" | tr '[:upper:]' '[:lower:]'
|
||||
done < "$2"
|
||||
}
|
||||
|
||||
openssl storeutl -certs "$1" > "$w/cert.pem" || w_cleanup 1
|
||||
[ -s "$w/cert.pem" ] || w_cleanup 1
|
||||
tr -s '\r\n' '\n' < "$w/cert.pem" > "$w/cert.txt"
|
||||
[ -s "$w/cert.txt" ] || w_cleanup 1
|
||||
rm -f "$w/cert.pem"
|
||||
|
||||
bundle_offsets "$w/cert.txt" > "$w/cert.off"
|
||||
[ -s "$w/cert.off" ] || w_cleanup 1
|
||||
|
||||
bundle_fingerprints "$w/cert.txt" "$w/cert.off" > "$w/cert.fp.all"
|
||||
[ -s "$w/cert.fp.all" ] || w_cleanup 1
|
||||
|
||||
sort -uV < "$w/cert.fp.all" > "$w/cert.fp"
|
||||
while read -r fp ; do
|
||||
[ -n "${fp}" ] || continue
|
||||
|
||||
n=$(grep -m1 -Fxn -e "${fp}" "$w/cert.fp.all" | cut -d : -f 1)
|
||||
[ -n "$n" ] || continue
|
||||
|
||||
off=$(sed -ne "${n}p" "$w/cert.off")
|
||||
[ -n "${off}" ] || continue
|
||||
|
||||
sed -ne "${off}p" "$w/cert.txt"
|
||||
done < "$w/cert.fp" > "$w/cert.pem"
|
||||
[ -s "$w/cert.pem" ] || w_cleanup 1
|
||||
rm -f "$w/cert.txt" "$w/cert.off" "$w/cert.fp.all"
|
||||
|
||||
if [ -n "$2" ] ; then
|
||||
while : ; do
|
||||
if [ -e "$2" ] ; then
|
||||
[ -f "$2" ] || break
|
||||
fi
|
||||
cat > "$2"
|
||||
break ; done
|
||||
else
|
||||
cat
|
||||
fi < "$w/cert.pem"
|
||||
|
||||
while [ -n "$3" ] ; do
|
||||
if [ -e "$3" ] ; then
|
||||
[ -f "$3" ] || break
|
||||
fi
|
||||
cat "$w/cert.fp" > "$3"
|
||||
break ; done
|
||||
|
||||
while [ -n "$4" ] ; do
|
||||
if [ -e "$4" ] ; then
|
||||
[ -f "$4" ] || break
|
||||
fi
|
||||
bundle_offsets "$w/cert.pem" > "$4"
|
||||
break ; done
|
||||
|
||||
rm -rf "$w" ; unset w
|
16
scripts/openssl-generate-dh-bundle.sh
Normal file
16
scripts/openssl-generate-dh-bundle.sh
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
|
||||
for k in 1024 2048 ; do
|
||||
f="dh${k}.pem"
|
||||
echo "# openssl genpkey: $f" >&2
|
||||
timeout --kill-after=32s 30s \
|
||||
openssl genpkey -quiet -genparam -algorithm DH -out "./$f" -pkeyopt "dh_paramgen_prime_len:${k}"
|
||||
done
|
||||
|
||||
for k in 2048 3072 4096 ; do
|
||||
f="ffdhe${k}.pem"
|
||||
echo "# openssl genpkey: $f" >&2
|
||||
timeout --kill-after=32s 30s \
|
||||
openssl genpkey -quiet -genparam -algorithm DH -out "./$f" -pkeyopt "group:ffdhe${k}"
|
||||
done
|
206
scripts/openssl-ocsp.sh
Executable file
206
scripts/openssl-ocsp.sh
Executable file
@@ -0,0 +1,206 @@
|
||||
#!/bin/sh
|
||||
set -ef
|
||||
|
||||
ocsp_fetch_timeout=15
|
||||
ocsp_fetch_retries=3
|
||||
ocsp_fetch_retry_delay=5
|
||||
ocsp_valid_threshold=86400
|
||||
|
||||
usage() {
|
||||
cat >&2 <<-EOF
|
||||
# usage: ${0##*/} <command> [args...]
|
||||
# ${0##*/} get-uri <in:cert.pem>
|
||||
# ${0##*/} is-valid <in:issuer.pem> <in:cert.pem> <in:ocsp.der>
|
||||
# ${0##*/} is-expiring <in:issuer.pem> <in:cert.pem> <in:ocsp.der>
|
||||
# ${0##*/} fetch <in:issuer.pem> <in:cert.pem> <out:ocsp.der>
|
||||
EOF
|
||||
exit "${1:-0}"
|
||||
}
|
||||
[ $# != 0 ] || usage
|
||||
|
||||
## $1 - X509 in PEM format
|
||||
ossl_x509_verify_fmt() {
|
||||
openssl x509 -in "$1" -noout >/dev/null
|
||||
}
|
||||
|
||||
## $1 - cert
|
||||
ossl_ocsp_uri() {
|
||||
openssl x509 -in "$1" -noout -ocsp_uri \
|
||||
| head -n 1
|
||||
}
|
||||
|
||||
## $1 - chain
|
||||
## $2 - cert
|
||||
## $3 - ocsp uri
|
||||
## $4 - ocsp response
|
||||
ossl_ocsp_fetch() {
|
||||
openssl ocsp \
|
||||
-timeout "${ocsp_fetch_timeout}" \
|
||||
-nonce \
|
||||
-issuer "$1" -cert "$2" -url "$3" -respout "$4"
|
||||
}
|
||||
|
||||
## $1 - ocsp response
|
||||
ossl_ocsp_verify_fmt() {
|
||||
openssl ocsp \
|
||||
-noverify -respin "$1"
|
||||
}
|
||||
|
||||
## $1 - chain
|
||||
## $2 - cert
|
||||
## $3 - ocsp response
|
||||
ossl_ocsp_read() {
|
||||
openssl ocsp \
|
||||
-issuer "$1" -cert "$2" -respin "$3" -resp_text
|
||||
}
|
||||
|
||||
## $1 - chain
|
||||
## $2 - cert
|
||||
## $3 - ocsp response
|
||||
ossl_ocsp_verify() {
|
||||
ossl_ocsp_read "$@" >/dev/null
|
||||
}
|
||||
|
||||
## stdin - output of ossl_ocsp_read()
|
||||
ossl_ocsp_next_update() {
|
||||
sed -En '/^\s*[Nn]ext [Uu]pdate:\s*(\S.+\S)\s*$/{s//\1/;p;q}'
|
||||
}
|
||||
|
||||
unset arg_ok cmd chain cert ocsp_uri ocsp_resp
|
||||
arg_ok=
|
||||
while : ; do
|
||||
[ -n "$1" ] || break
|
||||
cmd="$1"
|
||||
case "$1" in
|
||||
get-uri )
|
||||
[ -n "$2" ] || break
|
||||
[ -s "$2" ] || break
|
||||
ossl_x509_verify_fmt "$2" || break
|
||||
cert="$2"
|
||||
;;
|
||||
is-valid | is-expiring | fetch )
|
||||
[ -n "$2" ] || break
|
||||
[ -s "$2" ] || break
|
||||
ossl_x509_verify_fmt "$2" || break
|
||||
chain="$2"
|
||||
[ -n "$3" ] || break
|
||||
[ -s "$3" ] || break
|
||||
ossl_x509_verify_fmt "$3" || break
|
||||
cert="$3"
|
||||
[ -n "$4" ] || break
|
||||
ocsp_resp="$4"
|
||||
## OCSP response validation is handled later and in various ways (!)
|
||||
## e.g. "is-valid" (cmd_is_valid) validates OCSP response as expected
|
||||
## but "is-expiring" (cmd_is_expiring) returns success for invalid OCSP response
|
||||
## which means OCSP response should be updated ASAP
|
||||
;;
|
||||
*) break ;;
|
||||
esac
|
||||
arg_ok=1
|
||||
break ; done
|
||||
[ -n "${arg_ok}" ] || usage 1
|
||||
unset arg_ok
|
||||
|
||||
## OCSP URI is used only in "get-uri" and "fetch" commands
|
||||
## but implicitly required for all actions
|
||||
ocsp_uri=$(ossl_ocsp_uri "${cert}") || exit 1
|
||||
if [ -z "${ocsp_uri}" ] ; then
|
||||
env printf '%s: unable to extract OCSP URI from %q\n' "${0##*/}" "${cert}" >&2
|
||||
exit 1
|
||||
fi
|
||||
## early command handling
|
||||
if [ "${cmd}" = 'get-uri' ] ; then
|
||||
printf '%s\n' "${ocsp_uri}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
## $1 - chain
|
||||
## $2 - cert
|
||||
## $3 - ocsp response
|
||||
cmd_is_valid() {
|
||||
ossl_ocsp_verify_fmt "$3" || return 1
|
||||
ossl_ocsp_verify "$1" "$2" "$3" || return 1
|
||||
}
|
||||
|
||||
## $1 - chain
|
||||
## $2 - cert
|
||||
## $3 - ocsp response
|
||||
cmd_is_expiring() {
|
||||
cmd_is_valid "$1" "$2" "$3" || return 0
|
||||
|
||||
local need_update next ts_now ts_next ts_diff
|
||||
|
||||
need_update=1
|
||||
while : ; do
|
||||
next=$(ossl_ocsp_read "$1" "$2" "$3" 2>/dev/null | ossl_ocsp_next_update)
|
||||
[ -n "${next}" ] || break
|
||||
|
||||
ts_now=$(date '+%s')
|
||||
ts_next=$(date -d "${next}" '+%s')
|
||||
[ -n "${ts_next}" ] || break
|
||||
[ ${ts_now} -lt ${ts_next} ] || break
|
||||
|
||||
ts_diff=$((ts_next - ts_now))
|
||||
[ ${ts_diff} -le ${ocsp_valid_threshold} ] || need_update=0
|
||||
break ; done
|
||||
|
||||
if [ "${need_update}" = 0 ] ; then
|
||||
env printf '%q has valid and fresh OCSP response\n' "$2" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
## $1 - chain
|
||||
## $2 - cert
|
||||
## $3 - ocsp uri
|
||||
## $4 - ocsp response
|
||||
cmd_fetch() {
|
||||
local t i r
|
||||
|
||||
t=$(mktemp) ; : "${t:?}"
|
||||
|
||||
for i in $(seq 1 "${ocsp_fetch_retries}") ; do
|
||||
i= ## no-op
|
||||
|
||||
if ossl_ocsp_fetch "$1" "$2" "$3" "$t" ; then
|
||||
break
|
||||
fi
|
||||
: > "$t"
|
||||
sleep "${ocsp_fetch_retry_delay}"
|
||||
done
|
||||
|
||||
r=
|
||||
while : ; do
|
||||
[ -s "$t" ] || break
|
||||
cmd_is_valid "$1" "$2" "$t" || break
|
||||
r=1
|
||||
break ; done
|
||||
if [ -z "$r" ] ; then
|
||||
env printf 'unable to fetch OCSP response for %q via %q\n' "$2" "$3" >&2
|
||||
rm -rf "$t"
|
||||
return 1
|
||||
fi
|
||||
|
||||
r=
|
||||
while : ; do
|
||||
touch "$4" || break
|
||||
tee "$4" < "$t" >/dev/null || break
|
||||
chmod 0644 "$4" || break
|
||||
r=1
|
||||
break ; done
|
||||
if [ -z "$r" ] ; then
|
||||
env printf 'unable to save OCSP response for %q into %q\n' "$2" "$4" >&2
|
||||
rm -rf "$t"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
case "${cmd}" in
|
||||
is-valid ) cmd_is_valid "${chain}" "${cert}" "${ocsp_resp}" ;;
|
||||
is-expiring ) cmd_is_expiring "${chain}" "${cert}" "${ocsp_resp}" ;;
|
||||
fetch ) cmd_fetch "${chain}" "${cert}" "${ocsp_uri}" "${ocsp_resp}" ;;
|
||||
esac
|
8
scripts/pip-env.sh
Executable file
8
scripts/pip-env.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -a
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||
PIP_NO_CACHE_DIR=1
|
||||
PIP_ROOT_USER_ACTION=ignore
|
||||
PIP_NO_COMPILE=1
|
||||
set +a
|
||||
exec "$@"
|
9
scripts/python-rm-cache.sh
Executable file
9
scripts/python-rm-cache.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
set -f
|
||||
for i ; do
|
||||
[ -n "$i" ] || continue
|
||||
[ -d "$i" ] || continue
|
||||
find "$i/" -name __pycache__ -exec rm -rf {} +
|
||||
find "$i/" ! -type d -name '*.py[co]' -exec rm -f {} +
|
||||
done
|
||||
exit 0
|
54
scripts/static-compress.sh
Executable file
54
scripts/static-compress.sh
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
set -f
|
||||
|
||||
if command -v gzip >/dev/null ; then has_gzip=1 ; fi
|
||||
if command -v brotli >/dev/null ; then has_brotli=1 ; fi
|
||||
if command -v zstd >/dev/null ; then has_zstd=1 ; fi
|
||||
|
||||
do_gzip() { [ -s "$1.gz" ] || gzip -1kf "$1" || return ; comp_fixup "$1" "$1.gz" || rm -f "$1.gz" ; }
|
||||
do_brotli() { [ -s "$1.br" ] || brotli -1kf "$1" || return ; comp_fixup "$1" "$1.br" || rm -f "$1.br" ; }
|
||||
do_zstd() { [ -s "$1.zst" ] || zstd -q1kf "$1" || return ; comp_fixup "$1" "$1.zst" || rm -f "$1.zst" ; }
|
||||
|
||||
float_div() {
|
||||
mawk -v "a=$1" -v "b=$2" 'BEGIN{print a/b;exit;}' </dev/null
|
||||
}
|
||||
|
||||
comp_fixup() {
|
||||
[ -f "$1" ] || return 1
|
||||
size1=$(env stat -Lc '%s' "$1") || return 1
|
||||
[ -n "${size1}" ] || return 1
|
||||
[ "${size1}" != 0 ] || return 1
|
||||
|
||||
[ -f "$2" ] || return 1
|
||||
size2=$(env stat -c '%s' "$2") || return 1
|
||||
[ -n "${size2}" ] || return 1
|
||||
[ "${size2}" != 0 ] || return 1
|
||||
|
||||
ratio=$(float_div "${size2}" "${size1}") || return 1
|
||||
case "${ratio}" in
|
||||
[0-9]*e-[0-9]* )
|
||||
## doubtful but okay (c) Oleg Tinkov
|
||||
;;
|
||||
0.[0-8]* | 0.90* )
|
||||
## compression ratio below 90% is fine
|
||||
;;
|
||||
* ) return 1 ;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
for i ; do
|
||||
[ -n "$i" ] || continue
|
||||
|
||||
case "$i" in
|
||||
*.br | *.gz | *.zst ) continue ;;
|
||||
esac
|
||||
|
||||
[ -f "$i" ] || continue
|
||||
[ -s "$i" ] || continue
|
||||
|
||||
[ -z "${has_gzip}" ] || do_gzip "$i"
|
||||
[ -z "${has_brotli}" ] || do_brotli "$i"
|
||||
[ -z "${has_zstd}" ] || do_zstd "$i"
|
||||
done
|
Reference in New Issue
Block a user