Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run container as an unprivileged user #679

Open
damienfern opened this issue Oct 22, 2024 · 9 comments
Open

Run container as an unprivileged user #679

damienfern opened this issue Oct 22, 2024 · 9 comments
Labels
documentation Documentation needs adjustment enhancement help wanted

Comments

@damienfern
Copy link

Hi,

Thx for this template, very useful ! 🙏

Many resources suggest using an unprivileged user in container in order to prevent privilege escalation attacks(e.g. OWASP https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-2-set-a-user or Docker docs https://docs.docker.com/build/building/best-practices/#user).

It seems it's not the case on this template with FrankenPHP and based on its doc, FrankenPHP can be used with an unprivileged user. Is it on purpose, or is it a feature that can be added to this template ?

@7-zete-7
Copy link
Contributor

Hi, @damienfern

I'm also interested in this question!

For now I'm using the following edits to run FrankenPHP as the built-in user www-data.

frankenphp/docker-entrypoint.sh

@@ -53,8 +53,9 @@
 		fi
 	fi
 
-	setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var
-	setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var
+	chgrp -R www-data var /data /config
+	setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var /data /config
+	setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var /data /config
 fi
 
-exec docker-php-entrypoint "$@"
+su -c "docker-php-entrypoint $*" -s '/bin/sh' 'www-data'

With this edit the container still runs as root, but FrankenPHP runs as www-data.

I'm not sure if this is the correct way, but in my case it works so far.

I would also be glad if this template contained information about a more correct way to run the container not as an privileged user.

@dunglas
Copy link
Owner

dunglas commented Oct 24, 2024

Modifying the Dockerfile like this should help: https://frankenphp.dev/docs/docker/#running-as-a-non-root-user

A doc PR explaining how to change this template to run as a non-root user is very welcome, however, we'll not do that by default, because this causes many issues.

@maxhelias maxhelias added enhancement help wanted documentation Documentation needs adjustment labels Nov 12, 2024
@7-zete-7
Copy link
Contributor

Found a problem when using the method I described above (using su ... instead of exec ...): when using su ... a chain of subprocesses is created (entrypoint→su→sh→frankenphp), while when using exec ... there is no chain (frankenphp).

Due to the chain, signals sent by Docker do not reach the target process. This primarily negatively affects the Symfony Messenger consumer.

Processes when using exec ...:

PID USER Command
1 root frankenphp run --config /etc/caddy/Caddyfile

Processes when using su ...:

PID USER Command
1 root /bin/sh /usr/local/bin/docker-entrypoint frankenphp run --config /etc/caddy/Caddyfile
33 root `- su -c docker-php-entrypoint frankenphp run --config /etc/caddy/Caddyfile -s /usr/bin/sh www-data
34 www‑data `- sh -c frankenphp run --config /etc/caddy/Caddyfile
35 www‑data `- frankenphp run --config /etc/caddy/Caddyfile

@damienfern
Copy link
Author

Hi @7-zete-7,

You should give a try to https://github.com/tianon/gosu as it uses the same methods to "impersonate" user as Docker, but it uses an exec instead of a subprocess (which, as you pointed, handles the signal better).

@7-zete-7
Copy link
Contributor

Thanks for such a quick response, @damienfern!

I'll try using gosu for this task.

@7-zete-7
Copy link
Contributor

gosu actually changes the user and does not create any subprocesses. Thanks, @damienfern!

@7-zete-7
Copy link
Contributor

7-zete-7 commented Nov 26, 2024

Some update of #679 (comment) to work via gosu.

Dockerfile

@@ -27,8 +27,9 @@
 RUN set -eux; \
 	install-php-extensions \
 		@composer \
 		apcu \
+		gosu \
 		intl \
 		opcache \
 		zip \
 	;

frankenphp/docker-entrypoint.sh

@@ -53,8 +53,9 @@
 		fi
 	fi
 
-	setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var
-	setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var
+	chgrp -R www-data var /data /config
+	setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var /data /config
+	setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var /data /config
 fi
 
-exec docker-php-entrypoint "$@"
+exec /usr/sbin/gosu www-data "$@"

Still not sure if this is the correct way, but it works for now.

@damienfern
Copy link
Author

Have you tried to use gosu directly ? Based on the gosu's README, it already does an exec.

-exec /usr/sbin/gosu www-data "$@"
+/usr/sbin/gosu www-data "$@"

@7-zete-7
Copy link
Contributor

@damienfern, yes, I did this first. I was surprised that there was a chain of processes and tried with exec. With exec the chain was gone.

Using exec /usr/sbin/gosu www-data "$@"
PIDUSERCommand
1www-datafrankenphp run --config /etc/caddy/Caddyfile
Using /usr/sbin/gosu www-data "$@" or gosu www-data "$@"
PIDUSERCommand
1root/bin/sh /usr/local/bin/docker-entrypoint frankenphp run --config /etc/caddy/Caddyfile
20www-data`- frankenphp run --config /etc/caddy/Caddyfile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Documentation needs adjustment enhancement help wanted
Projects
None yet
Development

No branches or pull requests

4 participants