← Back to team overview

wordpress-charmers team mailing list archive

Re: [Merge] ~tcuthbert/charm-k8s-wordpress:container-hardening into charm-k8s-wordpress:container-hardening

 

A few comments inline, but also just wondering why you're merging this into a different branch than the current master?

Diff comments:

> diff --git a/Dockerfile b/Dockerfile
> index a338c56..e2451e0 100644
> --- a/Dockerfile
> +++ b/Dockerfile
> @@ -35,85 +46,141 @@ RUN apt-get update && apt-get -y dist-upgrade \
>              php-xml \
>              pwgen \
>              python3 \
> +            python3-urllib3 \
>              python3-yaml \
>              ssl-cert \
> -            wget \
> -        && sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS" \
> -        && . "$APACHE_ENVVARS" \
> -        && for dir in "$APACHE_LOCK_DIR" "$APACHE_RUN_DIR" "$APACHE_LOG_DIR"; do rm -rvf "$dir"; mkdir -p "$dir"; chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; chmod 777 "$dir";  done \
> -        && ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log" \
> -        && ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log" \
> -        && ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log" \
> -        && chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
> +            wget
> +
> +# Reconfigure apache so it can be run as non-root
> +RUN set -eux; \
> +        sed -i \
> +          -e "s/APACHE_RUN_USER=.*$/APACHE_RUN_USER=$USERNAME/" \
> +          -e "s/APACHE_RUN_GROUP=.*$/APACHE_RUN_GROUP=$GROUPNAME/" \
> +          "$APACHE_ENVVARS"; \
> +        . "$APACHE_ENVVARS"; \
> +        sed -i \
> +          -e 's/Listen 80/Listen 8000/' \
> +          -e 's/Listen 443/Listen 8433/' \
> +          -e 's/:80>$/:8000>/' \
> +          -e 's/:443>$/:8443>/' \
> +            /etc/apache2/ports.conf \
> +            /etc/apache2/sites-available/000-default.conf; \
> +        for dir in "$APACHE_LOCK_DIR" "$APACHE_RUN_DIR" "$APACHE_LOG_DIR"; do \
> +          rm -rvf "$dir"; \
> +          mkdir -p "$dir"; \
> +          chmod 2750 "$dir"; \
> +          chown -R "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
> +        done; \
> +        chown -R "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_CONFDIR" ; \
> +        ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
> +        ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
> +        ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
> +        chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
> +
> +# Test apache configuration works
> +RUN set -eux; /usr/sbin/apache2ctl -S;
>  
>  # Configure PHP and apache2 - mod_php requires us to use mpm_prefork
> -COPY ./image-builder/files/docker-php.conf $APACHE_CONFDIR/conf-available/docker-php.conf
> -COPY ./image-builder/files/docker-php-swift-proxy.conf $APACHE_CONFDIR/conf-available/docker-php-swift-proxy.conf
> -RUN a2enconf docker-php \
> -    && a2dismod mpm_event \
> -    && a2enmod headers \
> -    && a2enmod mpm_prefork \
> -    && a2enmod proxy \
> -    && a2enmod proxy_http \
> -    && a2enmod rewrite \
> -    && a2enmod ssl
> +ADD ./image-builder/files /files
> +RUN set -eux; \
> +        cp /files/docker-php.conf $APACHE_CONFDIR/conf-available/docker-php.conf; \
> +        cp /files/docker-php-swift-proxy.conf $APACHE_CONFDIR/conf-available/docker-php-swift-proxy.conf; \
> +        a2enconf docker-php; \
> +        a2dismod mpm_event; \
> +        a2enmod headers; \
> +        a2enmod mpm_prefork; \
> +        a2enmod proxy; \
> +        a2enmod proxy_http; \
> +        a2enmod rewrite; \
> +        a2enmod ssl
>  
>  
>  FROM base as plugins
> -
> +ARG USERNAME=wordpress
> +ARG GROUPNAME=${USERNAME}
>  # Download themes and plugins. This will eventually be separated into new container.
> -COPY ./image-builder/src/fetcher.py /
> +ADD ./image-builder/src/fetcher.py /fetcher.py
> +RUN bash -c 'set -eux; mkdir -p /var/www/html/wp-content/{themes,plugins}'
>  WORKDIR /var/www/html/wp-content/
> -RUN mkdir themes plugins && /fetcher.py
> +RUN set -eux; \
> +        /fetcher.py && chown "$USERNAME:$GROUPNAME" -R /var/www/html
>  VOLUME /var/www/html/wp-content
>  
>  FROM base As install
> -ARG VERSION
> -
> +ARG USERNAME=wordpress
> +ARG GROUPNAME=${USERNAME}
> +ARG VERSION=latest
> +ARG WORDPRESS_URL=https://wordpress.org/wordpress-${VERSION}.tar.gz
>  # TODO: replace downloading the source wordpress code with copying it from the upstream wordpress container,
>  # which should speed builds up:
>  #   COPY --from=wordpress-${VERSION}:fpm /usr/src/wordpress /usr/src/wordpress
>  # Install the main Wordpress code, this will be our only site so /var/www/html is fine
> -RUN wget -O wordpress.tar.gz -t 3 -r "https://wordpress.org/wordpress-${VERSION}.tar.gz"; \
> -    && tar -xzf wordpress.tar.gz -C /usr/src/ \
> -    && rm wordpress.tar.gz \
> -    && chown -R www-data:www-data /usr/src/wordpress \
> -    && rm -rf /var/www/html \
> -    && mv /usr/src/wordpress /var/www/html
> -
> -COPY ./image-builder/files/ /files/
> -# wp-info.php contains template variables which our ENTRYPOINT script will populate
> -RUN install -D /files/wp-info.php /var/www/html/wp-info.php
> -RUN install -D /files/wp-config.php /var/www/html/wp-config.php
> -RUN chown -R www-data:www-data /var/www/html
> -
> -# Copy our helper scripts and their wrapper into their own directory
> -RUN install /files/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
> -
> -RUN install -t /srv/wordpress-helpers/ -D /files/_add_option.php \
> -    /files/_enable_plugin.php \
> -    /files/_get_option.php \
> -    /files/plugin_handler.py \
> -    /files/ready.sh
> -
> -# Make the wrapper executable
> -RUN chmod 0755 /srv/wordpress-helpers/plugin_handler.py
> -RUN chmod 0755 /srv/wordpress-helpers/ready.sh
> -RUN chmod 0755 /usr/local/bin/docker-entrypoint.sh
> +RUN set -eux; \
> +        wget -O wordpress.tar.gz -t 3 -r "https://wordpress.org/wordpress-${VERSION}.tar.gz";; \
> +        tar -xzf /wordpress.tar.gz --owner=$USERNAME --group="$GROUPNAME" --strip-components=1 -C /var/www/html; \
> +        rm /wordpress.tar.gz
> +
> +RUN set -eux; \
> +        install --owner="$USERNAME" --group="$GROUPNAME" -d /srv/wordpress-helpers; \
> +        install --mode="700" --owner="$USERNAME" --group="$GROUPNAME" /files/wp-config.php /var/www/html/wp-config.php; \
> +        install --mode="700" --owner="$USERNAME" --group="$GROUPNAME" -t /srv/wordpress-helpers/ -D \
> +            /files/_add_option.php \
> +            /files/_enable_plugin.php \
> +            /files/_get_option.php \
> +            /files/plugin_handler.py \
> +            /files/ready.sh
>  
>  FROM install as wordpress
> +ARG USERNAME=wordpress
> +ARG GROUPNAME=${USERNAME}
>  ARG VERSION
>  
>  LABEL maintainer="wordpress-charmers@xxxxxxxxxxxxxxxxxxx"
>  # Used by Launchpad OCI Recipe to tag version
> -LABEL org.label-schema.version=${VERSION:-5.8.3}
> -
> -# Port 80 only, TLS will terminate elsewhere
> -EXPOSE 80
> +LABEL org.label-schema.version=${VERSION:-5.9.3}
>  
>  # Copy plugins from the plugin stage into the WordPress content directory.
> -COPY ./image-builder/src/fetcher.py /
> -COPY --chown=www-data:www-data --from=plugins /var/www/html/wp-content/plugins/ /var/www/html/wp-content/plugins/
> -COPY --chown=www-data:www-data --from=plugins /var/www/html/wp-content/themes/ /var/www/html/wp-content/themes/
> +COPY --chown="$USERNAME":"$GROUPNAME" --from=plugins /var/www/html/wp-content/plugins/ /var/www/html/wp-content/plugins/
> +COPY --chown="$USERNAME":"$GROUPNAME" --from=plugins /var/www/html/wp-content/themes/ /var/www/html/wp-content/themes/
> +
> +# Copy our helper scripts and their wrapper into their own directory
> +COPY --chown="$USERNAME":"$GROUPNAME" ./image-builder/files/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
> +COPY --chown="$USERNAME":"$GROUPNAME" ./image-builder/files/wp-info.php /var/www/html/wp-info.php
> +
> +# Make the wrapper executable
> +RUN chmod 0500 /srv/wordpress-helpers/plugin_handler.py
> +RUN chmod 0500 /srv/wordpress-helpers/ready.sh
> +RUN chmod 0500 /usr/local/bin/docker-entrypoint.sh
> +
> +RUN set -eux; \
> +        chmod 0500 /usr/local/bin/docker-entrypoint.sh; \
> +        sed -i -e 's/max_execution_time = 30/max_execution_time = 300/' \
> +            -i -e 's/upload_max_filesize = 2M/upload_max_filesize = 10M/' \
> +              /etc/php/7.[24]/apache2/php.ini
> +
> +# Ensure remote users are unable to upload potentially malicious content into the container
> +RUN set -eux; \
> +        find /var/www/html \
> +          -exec chown "$USERNAME:$GROUPNAME" {} \+ \
> +          -exec chmod o-rxw {} \+ \
> +          -type d -exec chmod g=srx {} \; \
> +          -or \
> +          -type f -name '*.php' -exec chmod u=rx,g=r {} \;; \
> +        chmod u+w /var/www/html/wp-includes/functions.php /var/www/html/wp-info.php; \
> +        touch /var/log/wordpress-plugin-handler.log; \
> +        chown "$USERNAME:$GROUPNAME" /var/log/wordpress-plugin-handler.log
> +
> +# Make sure we don't leave any build run time state behind
> +RUN set -eux; . "$APACHE_ENVVARS"; \
> +      for dir in "$APACHE_LOCK_DIR" "$APACHE_RUN_DIR"; do \
> +          rm -rvf "$dir/*"; \
> +      done; \
> +      apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
> +      rm -rf /var/lib/apt/lists/*;
> +
> +# Unprivileged port 8000 only, TLS will terminate elsewhere
> +EXPOSE 8000

So don't we need to update the ingress servicePort as a result?

> +USER ${USERNAME}:${GROUPNAME}
> +WORKDIR /var/www/html
>  ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
> -CMD apachectl -D FOREGROUND
> +CMD /usr/sbin/apache2ctl -D FOREGROUND
> diff --git a/src/charm.py b/src/charm.py
> index cba136a..a7234e0 100755
> --- a/src/charm.py
> +++ b/src/charm.py
> @@ -261,6 +262,16 @@ class WordpressCharm(CharmBase):
>                  ]
>              },
>          }
> +        if self.model.config["use_nginx_ingress_modsec"]:
> +            modsec_annotations = {
> +                "nginx.ingress.kubernetes.io/enable-modsecurity": "true",
> +                "nginx.ingress.kubernetes.io/enable-owasp-modsecurity-crs": "true",
> +                "nginx.ingress.kubernetes.io/modsecurity-snippet":
> +                    ("SecRuleEngine On\n"
> +                     "SecAction \"id:900130,phase:1,nolog,pass,t:none,setvar:tx.crs_exclusions_wordpress=1\"\n"
> +                     "Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf"),

We were setting some mod-security options before but they caused issues with logins I believe. Are we sure these are different/won't cause the same issues?

> +            }
> +            resources["kubernetesResources"]["ingressResources"][0]["annotations"].update(modsec_annotations)
>  
>          if self.model.config["additional_hostnames"]:
>              additional_hostnames = juju_setting_to_list(self.model.config["additional_hostnames"])


-- 
https://code.launchpad.net/~tcuthbert/charm-k8s-wordpress/+git/charm-k8s-wordpress-1/+merge/414162
Your team Wordpress Charmers is requested to review the proposed merge of ~tcuthbert/charm-k8s-wordpress:container-hardening into charm-k8s-wordpress:container-hardening.



References