From 4eb43fa9a1177058ba0fbb020d216948cbb8e5a9 Mon Sep 17 00:00:00 2001 From: Adam Rozman Date: Wed, 28 Jun 2023 12:10:10 +0000 Subject: [PATCH] reorganize the internal structure This commit: - provides a more strict access controll for the httpd ditectories - blocks access to the ftp directories via http paths - removes unused legacy code (mainly related to ignition and coreOS) - where possible 'sed' commands have been removed and replaced with jinja templates - httpd configuration has been modifed to better utilize the modular nature of apache configuration files - environment variable controlled switch has been introduced to the allow/block serving /shared/html/images when "runhttpd" is in use --- Dockerfile | 7 +- README.md | 5 ++ ironic-config/apache2-vmedia.conf.j2 | 9 ++ ...c-api.conf.j2 => httpd-ironic-api.conf.j2} | 0 ironic-config/httpd-modules.conf | 2 +- ironic-config/httpd.conf | 8 -- ironic-config/httpd.conf.j2 | 86 +++++++++++++++++++ scripts/configure-coreos-ipa | 32 ------- scripts/configure-httpd-ipa.sh | 37 -------- scripts/coreos-ipa-common.sh | 27 ------ scripts/runhttpd | 41 ++++----- scripts/runironic-api | 2 +- 12 files changed, 124 insertions(+), 132 deletions(-) rename ironic-config/{apache2-ironic-api.conf.j2 => httpd-ironic-api.conf.j2} (100%) delete mode 100644 ironic-config/httpd.conf create mode 100644 ironic-config/httpd.conf.j2 delete mode 100755 scripts/configure-coreos-ipa delete mode 100755 scripts/configure-httpd-ipa.sh delete mode 100644 scripts/coreos-ipa-common.sh diff --git a/Dockerfile b/Dockerfile index 30631be95..03ecaa70d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,13 +46,14 @@ COPY --from=ironic-builder /tmp/ipxe/src/bin/undionly.kpxe /tmp/ipxe/src/bin-x86 COPY --from=ironic-builder /tmp/esp.img /tmp/uefi_esp.img COPY ironic-config/ironic.conf.j2 /etc/ironic/ +COPY ironic-config/inspector.ipxe.j2 ironic-config/httpd-ironic-api.conf.j2 /tmp/ + +# DNSMASQ COPY ironic-config/dnsmasq.conf.j2 /etc/ -COPY ironic-config/inspector.ipxe.j2 ironic-config/ironic-python-agent.ign.j2 /tmp/ # Custom httpd config, removes all but the bare minimum needed modules -COPY ironic-config/httpd.conf /etc/httpd/conf.d/ +COPY ironic-config/httpd.conf.j2 /etc/httpd/conf/ COPY ironic-config/httpd-modules.conf /etc/httpd/conf.modules.d/ -COPY ironic-config/apache2-ironic-api.conf.j2 /etc/httpd-ironic-api.conf.j2 COPY ironic-config/apache2-vmedia.conf.j2 /etc/httpd-vmedia.conf.j2 # IRONIC-INSPECTOR # diff --git a/README.md b/README.md index 85f65400a..d296a29bb 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,9 @@ functionality: - `DNSMASQ_EXCEPT_INTERFACE` - interfaces to exclude when providing DHCP address (default `lo`) - `HTTP_PORT` - port used by http server (default `80`) +- `HTTPD_SERVE_NODE_IMAGES` - used by runhttpd script, controls access + to the `/shared/html/images` directory via the default virtual host + `(HTTP_PORT)`. (default `true`) - `DHCP_RANGE` - dhcp range to use for provisioning (default `172.22.0.10-172.22.0.100`) - `DHCP_HOSTS` - a `;` separated list of `dhcp-host` entries, e.g. known MAC @@ -72,6 +75,8 @@ functionality: - `DNS_IP` - DNS IP address to use for ironic dnsmasq(dhcpd) - `IRONIC_IPA_COLLECTORS` - Use a custom set of collectors to be run on inspection. (default `default,logs`) +- `HTTPD_ENABLE_SENDFILE` - Whether to activate the EnableSendfile apache + directive for httpd `(default, false)` The ironic configuration can be overridden by various environment variables. The following can serve as an example: diff --git a/ironic-config/apache2-vmedia.conf.j2 b/ironic-config/apache2-vmedia.conf.j2 index 3432c1fc3..ec2dd1973 100644 --- a/ironic-config/apache2-vmedia.conf.j2 +++ b/ironic-config/apache2-vmedia.conf.j2 @@ -9,6 +9,15 @@ Listen {{ env.VMEDIA_TLS_PORT }} SSLProtocol {{ env.IRONIC_VMEDIA_SSL_PROTOCOL }} SSLCertificateFile {{ env.IRONIC_VMEDIA_CERT_FILE }} SSLCertificateKeyFile {{ env.IRONIC_VMEDIA_KEY_FILE }} + + + Order deny,allow + deny from all + + + Order allow,deny + allow from all + diff --git a/ironic-config/apache2-ironic-api.conf.j2 b/ironic-config/httpd-ironic-api.conf.j2 similarity index 100% rename from ironic-config/apache2-ironic-api.conf.j2 rename to ironic-config/httpd-ironic-api.conf.j2 diff --git a/ironic-config/httpd-modules.conf b/ironic-config/httpd-modules.conf index 8fee385ab..e2d9e4d40 100644 --- a/ironic-config/httpd-modules.conf +++ b/ironic-config/httpd-modules.conf @@ -18,4 +18,4 @@ LoadModule authn_core_module modules/mod_authn_core.so LoadModule auth_basic_module modules/mod_auth_basic.so LoadModule authn_file_module modules/mod_authn_file.so LoadModule authz_user_module modules/mod_authz_user.so - +LoadModule access_compat_module modules/mod_access_compat.so diff --git a/ironic-config/httpd.conf b/ironic-config/httpd.conf deleted file mode 100644 index e16f7ab56..000000000 --- a/ironic-config/httpd.conf +++ /dev/null @@ -1,8 +0,0 @@ - -# http TRACE can be subjected to abuse and should be disabled -TraceEnable off - -# provide minimal server information -ServerTokens Prod -ServerSignature Off - diff --git a/ironic-config/httpd.conf.j2 b/ironic-config/httpd.conf.j2 new file mode 100644 index 000000000..329274f7f --- /dev/null +++ b/ironic-config/httpd.conf.j2 @@ -0,0 +1,86 @@ +ServerRoot "/etc/httpd" +{%- if env.LISTEN_ALL_INTERFACES | lower == "true" %} +Listen [::]:{{ env.HTTP_PORT }} +{% else %} +Listen {{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }} +{% endif %} +Include conf.modules.d/*.conf +User apache +Group apache + +ServerName {{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }} + + + AllowOverride none + Require all denied + + +DocumentRoot "/shared/html" + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + +{%- if env.HTTPD_SERVE_NODE_IMAGES | lower == "true" %} + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + +{% endif %} + + + DirectoryIndex index.html + + + + Require all denied + + +ErrorLog "/dev/stderr" + +LogLevel warn + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + CustomLog "/dev/stderr" combined + + + + TypesConfig /etc/mime.types + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + AddType text/html .shtml + AddOutputFilter INCLUDES .shtml + + +AddDefaultCharset UTF-8 + + + MIMEMagicFile conf/magic + + +PidFile /var/tmp/httpd.pid + +# EnableSendfile directive could speed up deployments but it could also cause +# issues depending on the underlying file system, to learn more: +# https://httpd.apache.org/docs/current/mod/core.html#enablesendfile +{%- if env.HTTPD_ENABLE_SENDFILE | lower == "true" %} +EnableSendfile on +{% endif %} + +# http TRACE can be subjected to abuse and should be disabled +TraceEnable off + +# provide minimal server information +ServerTokens Prod +ServerSignature Off + +IncludeOptional conf.d/*.conf + diff --git a/scripts/configure-coreos-ipa b/scripts/configure-coreos-ipa deleted file mode 100755 index e0c1e63f8..000000000 --- a/scripts/configure-coreos-ipa +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/bash - -# shellcheck disable=SC1091 -. /bin/ironic-common.sh -. /bin/coreos-ipa-common.sh - -# Base64 encoded pull secret -export IRONIC_AGENT_PULL_SECRET=${IRONIC_AGENT_PULL_SECRET:-} - -set -x - -export IRONIC_INSPECTOR_VLAN_INTERFACES=${IRONIC_INSPECTOR_VLAN_INTERFACES:-all} -export IRONIC_AGENT_IMAGE -export IRONIC_AGENT_PODMAN_FLAGS=${IRONIC_AGENT_PODMAN_FLAGS:---tls-verify=false} - -IRONIC_CERT_FILE=/certs/ironic/tls.crt - -wait_for_interface_or_ip - -if [[ -f "$IRONIC_CERT_FILE" ]]; then - export IRONIC_BASE_URL="https://${IRONIC_URL_HOST}" -else - export IRONIC_BASE_URL="http://${IRONIC_URL_HOST}" -fi - -render_j2_config /tmp/ironic-python-agent.ign.j2 "$IGNITION_FILE" -# Print the generated ignition for debugging purposes. -sed '/authfile/,+1 s/data:.*"/"/' "$IGNITION_FILE" - -if [[ -f "$ISO_FILE" ]]; then - coreos-installer iso ignition embed -i "$IGNITION_FILE" -f "$ISO_FILE" -fi diff --git a/scripts/configure-httpd-ipa.sh b/scripts/configure-httpd-ipa.sh deleted file mode 100755 index 1c90847b4..000000000 --- a/scripts/configure-httpd-ipa.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/bash - -IRONIC_CERT_FILE=${IRONIC_CERT_FILE:-/certs/ironic/tls.crt} -export HTTP_PORT=${HTTP_PORT:-80} - -# Whether to enable fast_track provisioning or not -IRONIC_FAST_TRACK=${IRONIC_FAST_TRACK:-true} - -wait_for_interface_or_ip - -# shellcheck disable=SC2174 -mkdir -pm 0777 /shared/html - -if [[ -f "$IRONIC_CERT_FILE" ]]; then - IRONIC_BASE_URL="https://${IRONIC_URL_HOST}" -else - IRONIC_BASE_URL="http://${IRONIC_URL_HOST}" -fi - -INSPECTOR_EXTRA_ARGS=" ipa-inspection-callback-url=${IRONIC_BASE_URL}:${IRONIC_INSPECTOR_ACCESS_PORT}/v1/continue" -if [[ "$IRONIC_FAST_TRACK" == "true" ]]; then - INSPECTOR_EXTRA_ARGS+=" ipa-api-url=${IRONIC_BASE_URL}:${IRONIC_ACCESS_PORT}" -fi -export INSPECTOR_EXTRA_ARGS - -# Copy files to shared mount -render_j2_config /tmp/inspector.ipxe.j2 /shared/html/inspector.ipxe -cp /tmp/uefi_esp.img /shared/html/ - -sed -i 's/^Listen .*$/Listen [::]:'"$HTTP_PORT"'/' /etc/httpd/conf/httpd.conf -sed -i -e 's|\(^[[:space:]]*\)\(DocumentRoot\)\(.*\)|\1\2 "/shared/html"|' \ - -e 's|||' \ - -e 's|||' /etc/httpd/conf/httpd.conf - -# Log to std out/err -sed -i -e 's%^ \+CustomLog.*% CustomLog /dev/stderr combined%g' /etc/httpd/conf/httpd.conf -sed -i -e 's%^ErrorLog.*%ErrorLog /dev/stderr%g' /etc/httpd/conf/httpd.conf diff --git a/scripts/coreos-ipa-common.sh b/scripts/coreos-ipa-common.sh deleted file mode 100644 index e051a14bb..000000000 --- a/scripts/coreos-ipa-common.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/bash - -ROOTFS_FILE=${ROOTFS_FILE:-/shared/html/images/ironic-python-agent.rootfs} -IGNITION_FILE=${IGNITION_FILE:-/shared/html/ironic-python-agent.ign} -ISO_FILE=${ISO_FILE:-/shared/html/images/ironic-python-agent.iso} - -coreos_kernel_params() -{ - echo -n "coreos.live.rootfs_url=http://${IRONIC_URL_HOST}:$HTTP_PORT/images/ironic-python-agent.rootfs" - if [[ -f "$IGNITION_FILE" ]]; then - echo -n " ignition.config.url=http://${IRONIC_URL_HOST}:$HTTP_PORT/ironic-python-agent.ign" - fi - echo " ignition.firstboot ignition.platform.id=metal" -} - -use_coreos_ipa() -{ - if [[ -f "$ROOTFS_FILE" ]]; then - return 0 - fi - return 1 -} - -if use_coreos_ipa; then - IRONIC_KERNEL_PARAMS="${IRONIC_KERNEL_PARAMS:-} $(coreos_kernel_params)" - export IRONIC_KERNEL_PARAMS -fi diff --git a/scripts/runhttpd b/scripts/runhttpd index fd22952fd..6b84de4d4 100755 --- a/scripts/runhttpd +++ b/scripts/runhttpd @@ -12,9 +12,16 @@ INSPECTOR_RESULT_HTTPD_CONFIG=/etc/httpd/conf.d/ironic-inspector.conf export IRONIC_REVERSE_PROXY_SETUP=${IRONIC_REVERSE_PROXY_SETUP:-false} export INSPECTOR_REVERSE_PROXY_SETUP=${INSPECTOR_REVERSE_PROXY_SETUP:-false} +# In Metal3 context they are called node images in Ironic context they are +# called user images. +export HTTPD_SERVE_NODE_IMAGES="${HTTPD_SERVE_NODE_IMAGES:-true}" + # Whether to enable fast_track provisioning or not IRONIC_FAST_TRACK=${IRONIC_FAST_TRACK:-true} +# Whether to activate the EnableSendfile apache directive for httpd +HTTPD_ENABLE_SENDFILE="${HTTPD_ENABLE_SENDFILE:-false}" + # Set of collectors that should be used with IPA inspection export IRONIC_IPA_COLLECTORS=${IRONIC_IPA_COLLECTORS:-default,logs} @@ -31,12 +38,13 @@ if [[ "$IRONIC_FAST_TRACK" == "true" ]]; then fi export INSPECTOR_EXTRA_ARGS -# shellcheck disable=SC1091 -. /bin/coreos-ipa-common.sh - # Copy files to shared mount render_j2_config /tmp/inspector.ipxe.j2 /shared/html/inspector.ipxe cp /tmp/uefi_esp.img /shared/html/uefi_esp.img +mv /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.example + +# Render the core httpd config +render_j2_config /etc/httpd/conf/httpd.conf.j2 /etc/httpd/conf/httpd.conf if [[ "$IRONIC_INSPECTOR_TLS_SETUP" == "true" ]]; then if [[ "${INSPECTOR_REVERSE_PROXY_SETUP}" == "true" ]]; then @@ -48,7 +56,7 @@ fi if [[ "$IRONIC_TLS_SETUP" == "true" ]]; then if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "true" ]]; then - render_j2_config /etc/httpd-ironic-api.conf.j2 /etc/httpd/conf.d/ironic.conf + render_j2_config /tmp/httpd-ironic-api.conf.j2 /etc/httpd/conf.d/ironic.conf fi else export IRONIC_REVERSE_PROXY_SETUP="false" # If TLS is not used, we have no reason to use the reverse proxy @@ -57,36 +65,21 @@ fi export IRONIC_HTPASSWD=${IRONIC_HTPASSWD:-${HTTP_BASIC_HTPASSWD:-}} export INSPECTOR_HTPASSWD=${INSPECTOR_HTPASSWD:-${HTTP_BASIC_HTPASSWD:-}} -# Configure HTTP basic auth for API server +# Set basic auth credentials for Ironic API server if [[ -n "${IRONIC_HTPASSWD:-}" ]]; then printf "%s\n" "${IRONIC_HTPASSWD}" > /etc/ironic/htpasswd fi +# Set basic auth credentials for Ironic Inspector server if [[ -n "${INSPECTOR_HTPASSWD:-}" ]]; then printf "%s\n" "${INSPECTOR_HTPASSWD}" > /etc/ironic-inspector/htpasswd fi -if [[ "${LISTEN_ALL_INTERFACES}" == "true" ]]; then - sed -i 's/^Listen .*$/Listen [::]:'"$HTTP_PORT"'/' /etc/httpd/conf/httpd.conf -else - sed -i 's/^Listen .*$/Listen '"$IRONIC_URL_HOST"':'"$HTTP_PORT"'/' /etc/httpd/conf/httpd.conf -fi -sed -i -e 's|\(^[[:space:]]*\)\(DocumentRoot\)\(.*\)|\1\2 "/shared/html"|' \ - -e 's|||' \ - -e 's|||' /etc/httpd/conf/httpd.conf - -# Log to std out/err -sed -i -e 's%^ \+CustomLog.*% CustomLog /dev/stderr combined%g' /etc/httpd/conf/httpd.conf -sed -i -e 's%^ErrorLog.*%ErrorLog /dev/stderr%g' /etc/httpd/conf/httpd.conf - -# put pidfile somewhere we can write as nonroot -cat <<'EOF' >>/etc/httpd/conf/httpd.conf -PidFile /var/tmp/httpd.pid -EOF - +# Render httpd TLS configuration for /shared/html/ if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]]; then render_j2_config /etc/httpd-vmedia.conf.j2 /etc/httpd/conf.d/vmedia.conf fi +# Set up inotify to kill the container (restart) whenever cert files for ironic inspector change if [[ "$IRONIC_INSPECTOR_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then # shellcheck disable=SC2034 inotifywait -m -e delete_self "${IRONIC_INSPECTOR_CERT_FILE}" | while read -r file event; do @@ -94,6 +87,7 @@ if [[ "$IRONIC_INSPECTOR_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERT done & fi +# Set up inotify to kill the container (restart) whenever cert files for ironic api change if [[ "$IRONIC_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then # shellcheck disable=SC2034 inotifywait -m -e delete_self "${IRONIC_CERT_FILE}" | while read -r file event; do @@ -101,6 +95,7 @@ if [[ "$IRONIC_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UP done & fi +# Set up inotify to kill the container (restart) whenever cert of httpd for /shared/html/ path change if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then # shellcheck disable=SC2034 inotifywait -m -e delete_self "${IRONIC_VMEDIA_CERT_FILE}" | while read -r file event; do diff --git a/scripts/runironic-api b/scripts/runironic-api index 00a882a60..986a8e357 100755 --- a/scripts/runironic-api +++ b/scripts/runironic-api @@ -7,7 +7,7 @@ export IRONIC_DEPLOYMENT="API" export IRONIC_REVERSE_PROXY_SETUP=false -python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < /etc/httpd-ironic-api.conf.j2 > /etc/httpd/conf.d/ironic.conf +python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < /tmp/httpd-ironic-api.conf.j2 > /etc/httpd/conf.d/ironic.conf # shellcheck disable=SC1091 . /bin/runhttpd