--- Begin Message ---
Package: neutron-api
Version: 2:26.0.0-1~bpo12+1
Severity: wishlist
Dear Maintainer,
The init.d script controlling neutron-api would benefit from extending
options related to HTTPS config.
1. Current configuration option looks under
/etc/${PROJECT_NAME}/ssl/public and /etc/${PROJECT_NAME}/ssl/private:
66 if [ -n "${UWSGI_PORT}" ] && [ -n "${UWSGI_INI_PATH}" ] && [ -n
"${UWSGI_INI_APP}" ] ; then
67 if ! [ -f "${UWSGI_INI_APP}" ] ; then
68 ·exit 0
69 fi
70 if [ -d /etc/${PROJECT_NAME}/ssl/private ] ; then
71 KEY_FILE=$(find /etc/${PROJECT_NAME}/ssl/private -type f
-iname '*.pem' 2>/dev/null | head -n 1)
72 fi
73
74 if [ -e /usr/local/share/ca-certificates/puppet_openstack.crt ]
; then
75 # This is needed for puppet...
76 CERT_FILE=/usr/local/share/ca-certificates/puppet_openstack.crt
77 else
78 if [ -d /etc/${PROJECT_NAME}/ssl/public ] ; then
79 ·CERT_FILE=$(find /etc/${PROJECT_NAME}/ssl/public -type
f -iname '*.crt' 2>/dev/null | head -n 1)
80 fi
81 fi
2. Later in the script the parameters for https or http are decided:
128 if [ -n "${BIND_PARAMS}" ] ; then
129 DAEMON_ARGS="${BIND_PARAMS}${UWSGI_PROCESSES}"
130 else
131 if [ -n "${KEY_FILE}" ] && [ -n "${CERT_FILE}" ] ; then
132 DAEMON_ARGS="--https-socket
${UWSGI_BIND_IP}:${UWSGI_PORT},${CERT_FILE},${KEY_FILE}${UWSGI_PROCESSES}"
133 else
134 DAEMON_ARGS="--http-socket
${UWSGI_BIND_IP}:${UWSGI_PORT}${UWSGI_PROCESSES}"
135 fi
136 fi
1. It would be beneficial if one could add arbitrary path for the key
and certificate files and specify the file names instead of using find.
Or have somewhere a configuration file where one could write the values.
2. When using client certificate authentication, it is required to be
able to pass more parameters to uwsgi.
Then the DAEMON_ARGS should be something like following:
DAEMON_ARGS="--https-socket
${UWSGI_BIND_IP}:${UWSGI_PORT},${CERT_FILE},${KEY_FILE},${TLS_CIPHER},${CA_FILE}${UWSGI_PROCESSES}"
where TLS_CIPHER in this case would be 'HIGH' indicating highest
possible ciphers for TLS [1] and CA_FILE path to CA file.
Attached is the modified neutron-api script which allows us to run api
over https with the native uwsgi script.
This issue has been around already in Dalmation with Debian 12.9.
So far we could circumvent with using apache2 to serve api with wsgi
module and TLS. However now neutron requires native uwsgi to be used to
serve the APIs.
Best, Jani
[1] https://uwsgi-docs.readthedocs.io/en/latest/HTTPS.html
-- System Information:
Debian Release: trixie/sid
APT prefers stable-updates
APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500,
'stable')
Architecture: amd64 (x86_64)
Kernel: Linux 6.10.6-progress7.99-amd64 (SMP w/64 CPU threads; PREEMPT)
Locale: LANG=C.UTF-8, LC_CTYPE=C.UTF-8 (charmap=UTF-8) (ignored: LC_ALL
set to C.UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
Versions of packages neutron-api depends on:
ii adduser 3.134
ii debconf [debconf-2.0] 1.5.82
ii neutron-common 2:26.0.0-1~bpo12+1
ii python3-keystoneclient 1:5.6.0-2~bpo12+1
ii python3-openstackclient 7.4.0-3~bpo12+1
ii python3-pastescript 3.2.1-1
ii python3-q-text-as-data [q-text-as-data] 3.1.6-5~bpo12+1
ii uwsgi-plugin-python3 2.0.21-5.1
neutron-api recommends no packages.
neutron-api suggests no packages.
-- Configuration Files:
/etc/init.d/neutron-api changed:
DESC="OpenStack Neutron API (neutron-api)"
PROJECT_NAME=neutron
NAME=${PROJECT_NAME}-server
UWSGI_PORT=9696
UWSGI_INI_PATH=/etc/neutron/neutron-api-uwsgi.ini
UWSGI_INI_APP=/usr/bin/neutron-api
PYARGV="--config-file=/etc/neutron/neutron.conf"
[ -r /usr/share/neutron-common/plugin_guess_func ] || exit 0
. /usr/share/neutron-common/plugin_guess_func
if ! [ -r /etc/neutron/neutron.conf ] ; then
echo "Cloud not read /etc/neutron/neutron.conf: exiting"
exit 0
fi
CURRENT_PLUGIN=`grep "^[ \t]*core_plugin[ \t]*=[ \t]*[._a-zA-Z0-9]*\$"
/etc/neutron/neutron.conf | sed -e 's/^[ \t]*core_plugin[ \t]*=[ \t]*//'`
if [ -z "${CURRENT_PLUGIN}" ] ; then
echo "No core_plugin= value found: please set it and try again"
exit 0
fi
neutron_core_plugin_to_plugin_name ${CURRENT_PLUGIN}
neutron_plugin_ini_path ${NEUTRON_PLUGIN_NAME}
if [ -z "${NEUTRON_PLUGIN_CONFIG}" ] ; then
echo "Plugin not recognized: please edit
/etc/init.d/neutron-api to select the correct .ini file to load for your
plugin"
else
PYARGV="${PYARGV} --config-file=${NEUTRON_PLUGIN_CONFIG}"
DESC="${DESC} with ${NEUTRON_PLUGIN_NAME} plugin"
fi
if [ -e /etc/neutron/server.conf.d ] ; then
PYARGV="--config-dir=/etc/neutron/server.conf.d ${PYARGV}"
fi
mkdir -p /var/lib/neutron/tmp
chown neutron:neutron /var/lib/neutron/tmp
export TMPDIR=/var/lib/neutron/tmp
PATH=/sbin:/usr/sbin:/bin:/usr/bin
if [ -n "${UWSGI_PORT}" ] && [ -n "${UWSGI_INI_PATH}" ] && [ -n
"${UWSGI_INI_APP}" ] ; then
if ! [ -f "${UWSGI_INI_APP}" ] ; then
exit 0
fi
if [ -d /etc/${PROJECT_NAME}/ssl/private ] ; then
KEY_FILE=$(find /etc/${PROJECT_NAME}/ssl/private -type
f -iname '*.pem' 2>/dev/null | head -n 1)
fi
if [ -e /usr/local/share/ca-certificates/puppet_openstack.crt ]
; then
# This is needed for puppet...
CERT_FILE=/usr/local/share/ca-certificates/puppet_openstack.crt
else
if [ -d /etc/${PROJECT_NAME}/ssl/public ] ; then
CERT_FILE=$(find
/etc/${PROJECT_NAME}/ssl/public -type f -iname '*.crt' 2>/dev/null |
head -n 1)
fi
fi
# Sid doesn't have /usr/bin/uwsgi_python3, so we need
# to search for a more specific daemon name. For stretch
# /usr/bin/uwsgi_python3 is fine.
for i in 3 35 36 37 38 39 310 311 312 313 314 315 316 317 318
319 ; do
if [ -x /usr/bin/uwsgi_python${i} ] ; then
DAEMON=/usr/bin/uwsgi_python${i}
fi
done
if [ -n "${UWSGI_BIND_CONFIG_FILE}" ] && [ -r
"${UWSGI_BIND_CONFIG_FILE}" ] && [ -n "${UWSGI_BIND_CONFIG_SECTION}" ]
&& [ -n "${UWSGI_BIND_CONFIG_IP_DIRECTIVE}" ] && [ -n
"${UWSGI_BIND_CONFIG_PORT_DIRECTIVE}" ] && [ -r
/usr/share/openstack-pkg-tools/pkgos_func ] ; then
. /usr/share/openstack-pkg-tools/pkgos_func
pkgos_inifile get ${UWSGI_BIND_CONFIG_FILE}
${UWSGI_BIND_CONFIG_SECTION} ${UWSGI_BIND_CONFIG_IP_DIRECTIVE}
if [ -n "${RET}" ] && [ ! "${RET}" = "NOT_FOUND" ] ; then
UWSGI_BIND_IP=${RET}
fi
pkgos_inifile get ${UWSGI_BIND_CONFIG_FILE}
${UWSGI_BIND_CONFIG_SECTION} ${UWSGI_BIND_CONFIG_PORT_DIRECTIVE}
if [ -n "${RET}" ] && [ ! "${RET}" = "NOT_FOUND" ] ; then
UWSGI_PORT=${RET}
fi
if [ -n "${UWSGI_BIND_CONFIG_WORKERS_DIRECTIVE}" ] ; then
pkgos_inifile get ${UWSGI_BIND_CONFIG_FILE}
${UWSGI_BIND_CONFIG_SECTION} ${UWSGI_BIND_CONFIG_WORKERS_DIRECTIVE}
if [ -n "${RET}" ] && [ ! "${RET}" =
"NOT_FOUND" ] ; then
UWSGI_PROCESSES=" --processes ${RET}"
else
# If we can't find the directive in the
config file,
# we fallback to the number of thread / 2.
UWSGI_PROCESSES=" --processes "$((
$(nproc) / 2 ))
fi
fi
if [ "${UWSGI_BIND_CONFIG_FILE}" =
"/etc/swift/object-server.conf" ] ; then
pkgos_inifile get ${UWSGI_BIND_CONFIG_FILE}
${UWSGI_BIND_CONFIG_SECTION} devices
if [ -n "${RET}" ] && [ ! "${RET}" =
"NOT_FOUND" ] ; then
DEVICES_PATH=${RET}
NUM_DEVICES=$(ls ${DEVICES_PATH} | wc -l)
COUNT=0
while [ "${COUNT}" != "${NUM_DEVICES}"
] ; do
CUR_PORT=$(( ${UWSGI_PORT} +
${COUNT} ))
BIND_PARAMS="${BIND_PARAMS} --http-socket ${UWSGI_BIND_IP}:${CUR_PORT}"
COUNT=$(( ${COUNT} + 1 ))
done
fi
fi
else
UWSGI_BIND_IP="[::]"
fi
if [ -n "${BIND_PARAMS}" ] ; then
DAEMON_ARGS="${BIND_PARAMS}${UWSGI_PROCESSES}"
else
KEY_FILE="/srv/path/to/ssl/privkey.pem"
CERT_FILE="/srv/path/to/ssl/cert.pem"
CA_FILE="/srv/path/to/ssl/root_intermediate_cert.pem"
if [ -n "${KEY_FILE}" ] && [ -n "${CERT_FILE}" ] ; then
DAEMON_ARGS="--https-socket
${UWSGI_BIND_IP}:${UWSGI_PORT},${CERT_FILE},${KEY_FILE},HIGH,${CA_FILE}${UWSGI_PROCESSES}"
else
DAEMON_ARGS="--http-socket
${UWSGI_BIND_IP}:${UWSGI_PORT}${UWSGI_PROCESSES}"
fi
fi
DAEMON_ARGS="${DAEMON_ARGS} --ini ${UWSGI_INI_PATH}"
NO_OPENSTACK_CONFIG_FILE_DAEMON_ARG=yes
NO_OPENSTACK_LOGFILE_DAEMON_ARG=yes
fi
if [ -z "${DAEMON}" ] ; then
DAEMON=/usr/bin/${NAME}
fi
PIDFILE=/var/run/${PROJECT_NAME}/${NAME}.pid
if [ -z "${SCRIPTNAME}" ] ; then
SCRIPTNAME=/etc/init.d/${NAME}
fi
if [ -z "${SYSTEM_USER}" ] ; then
SYSTEM_USER=${PROJECT_NAME}
fi
if [ -z "${SYSTEM_GROUP}" ] ; then
SYSTEM_GROUP=${PROJECT_NAME}
fi
if [ "${SYSTEM_USER}" != "root" ] ; then
STARTDAEMON_CHUID="--chuid ${SYSTEM_USER}:${SYSTEM_GROUP}"
fi
if [ -z "${CONFIG_FILE}" ] ; then
CONFIG_FILE=/etc/${PROJECT_NAME}/${PROJECT_NAME}.conf
fi
LOGFILE=/var/log/${PROJECT_NAME}/${NAME}.log
if [ -z "${NO_OPENSTACK_CONFIG_FILE_DAEMON_ARG}" ] ; then
DAEMON_ARGS="--config-file=${CONFIG_FILE} ${DAEMON_ARGS}"
fi
[ -x $DAEMON ] || exit 0
if [ `whoami` = "root" ] ; then
for i in lock run cache ; do
mkdir -p /var/$i/${PROJECT_NAME}
chown ${SYSTEM_USER}:${SYSTEM_GROUP}
/var/$i/${PROJECT_NAME}
done
fi
. /lib/lsb/init-functions
RET=0
[ -r /etc/default/openstack ] && . /etc/default/openstack
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
[ "x$USE_SYSLOG" = "xyes" ] && DAEMON_ARGS="$DAEMON_ARGS --use-syslog"
if [ -z "${NO_OPENSTACK_LOGFILE_DAEMON_ARG}" ] ; then
[ "x$USE_LOGFILE" != "xno" ] && DAEMON_ARGS="$DAEMON_ARGS
--log-file=$LOGFILE"
fi
do_start() {
start-stop-daemon \
--start \
--quiet \
--background ${STARTDAEMON_CHUID} \
--make-pidfile --pidfile ${PIDFILE} \
--chdir /var/lib/${PROJECT_NAME} \
--startas $DAEMON \
--test > /dev/null \
|| return 1
if [ -n "${PYARGV}" ] ; then
start-stop-daemon \
--start \
--quiet \
--background ${STARTDAEMON_CHUID} \
--make-pidfile --pidfile ${PIDFILE} \
--chdir /var/lib/${PROJECT_NAME} \
--startas $DAEMON \
-- $DAEMON_ARGS --pyargv "${PYARGV}" \
|| return 2
else
start-stop-daemon \
--start \
--quiet \
--background ${STARTDAEMON_CHUID} \
--make-pidfile --pidfile ${PIDFILE} \
--chdir /var/lib/${PROJECT_NAME} \
--startas $DAEMON \
-- $DAEMON_ARGS \
|| return 2
fi
}
do_stop() {
start-stop-daemon \
--stop \
--quiet \
--retry=TERM/30/KILL/5 \
--pidfile $PIDFILE
RETVAL=$?
rm -f $PIDFILE
return "$RETVAL"
}
do_systemd_start() {
# Set umask to ensure log files are created with 0644 mode bits
# Note we can't set 0026 to have files 0640, because that's going
# to be in use in for example neutron-dhcp-agent, which makes it
# so it wont be able to read
/var/lib/neutron/external/pids/*.pid.haproxy
# and then fail hardly. However, 0022 is enough, since the log
# folders are owned by <project>:adm, so users don't have access
# to it unless they are on the adm group, which is what we want.
umask 0022
if [ -n "${PYARGV}" ] ; then
exec $DAEMON $DAEMON_ARGS --pyargv "${PYARGV}"
else
exec $DAEMON $DAEMON_ARGS
fi
}
case "$1" in
start)
log_daemon_msg "Starting $DESC" "$NAME"
do_start
case $? in
0|1) log_end_msg 0 ; RET=$? ;;
2) log_end_msg 1 ; RET=$? ;;
esac
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case $? in
0|1) log_end_msg 0 ; RET=$? ;;
2) log_end_msg 1 ; RET=$? ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME"
RET=$?
;;
systemd-start)
do_systemd_start
;;
show-args)
if [ -n "${PYARGV}" ] ; then
echo $DAEMON $DAEMON_ARGS --pyargv \"${PYARGV}\"
else
echo $DAEMON $DAEMON_ARGS
fi
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case $? in
0|1)
do_start
case $? in
0) log_end_msg 0 ; RET=$? ;;
1) log_end_msg 1 ; RET=$? ;; # Old
process is still running
*) log_end_msg 1 ; RET=$? ;; # Failed
to start
esac
;;
*) log_end_msg 1 ; RET=$? ;; # Failed to stop
esac
;;
*)
echo "Usage: $SCRIPTNAME
{start|stop|status|restart|force-reload|systemd-start}" >&2
RET=3
;;
esac
exit $RET
-- debconf information:
neutron/configure_api-endpoint: false
neutron/api-keystone-address:
neutron/api-keystone-proto: http
neutron/api-endpoint-proto: http
neutron/api-endpoint-address:
neutron/api-keystone-admin-project-name: admin
neutron/api-keystone-admin-username: admin
neutron/api-endpoint-region-name: regionOne
--
Berner Fachhochschule / Bern University of Applied Sciences
IT-Services / Team Linux & Infrastructure Services
Jani Heikkinen
IT Linux Engineer
___________________________________________________________
Dammweg 3, CH-3013 Bern
Telefon direkt +41 31 848 68 14
Telefon Servicedesk +41 31 848 48 48
[email protected]
--- End Message ---