tiredofit / docker-freepbx

Dockerized FreePBX 15 w/Asterisk 17, Seperate MySQL Database support, and Data Persistence and UCP
MIT License
516 stars 236 forks source link

Unable to apply #196

Open fred-gb opened 2 years ago

fred-gb commented 2 years ago

Summary

Unable to apply on GUI

Steps to reproduce

Just apply config

Relevant logs and/or screenshots

Capture d’écran 2022-07-15 à 16 12 17
[tiredofit/debian 14:04:03] # fwconsole reload --verbose
{"message":"Reload Started"}

In Cron.class.php line 281:

  [Whoops\Exception\ErrorException (2)]
  proc_open(/tmp/cron.error): failed to open stream: Permission non accordée

Exception trace:
 () at /var/www/html/admin/libraries/BMO/Cron.class.php:281
 Whoops\Run->handleError() at n/a:n/a
 proc_open() at /var/www/html/admin/libraries/BMO/Cron.class.php:281
 FreePBX\Cron->installCrontab() at /var/www/html/admin/libraries/BMO/Cron.class.php:162
 FreePBX\Cron->remove() at /var/www/html/admin/libraries/BMO/Job.class.php:238
 FreePBX\Job->init() at /var/www/html/admin/libraries/BMO/Job.class.php:91
 FreePBX\Job->add() at /var/www/html/admin/libraries/BMO/Job.class.php:73
 FreePBX\Job->addClass() at /var/www/html/admin/modules/dashboard/Dashboard.class.php:147
 Dashboard->doDialplanHook() at /var/www/html/admin/libraries/BMO/DialplanHooks.class.php:107
 FreePBX\DialplanHooks->processHooks() at /var/www/html/admin/libraries/Console/Reload.class.php:318
 FreePBX\Console\Command\Reload->reload() at /var/www/html/admin/libraries/Console/Reload.class.php:91
 FreePBX\Console\Command\Reload->execute() at /var/www/html/admin/libraries/Composer/vendor/symfony/console/Command/Command.php:255
 Symfony\Component\Console\Command\Command->run() at /var/www/html/admin/libraries/Composer/vendor/symfony/console/Application.php:960
 Symfony\Component\Console\Application->doRunCommand() at /var/www/html/admin/libraries/Composer/vendor/symfony/console/Application.php:255
 Symfony\Component\Console\Application->doRun() at /var/www/html/admin/libraries/Composer/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /data/var/lib/asterisk/bin/fwconsole:163

reload [--json] [--dry-run] [--skip-registry-checks] [--dont-reload-asterisk]
[tiredofit/debian 14:14:23] # cat /tmp/cron.error
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly

Environment

For testing, I set to 777 all mounted directory:

/certs
/var/www/html
/var/log
/data
/assets/custom

same error.

Help! 🆘

bsteimer commented 2 years ago

https://docs.oracle.com/cd/E19253-01/817-0403/sysrescron-23/index.html This should help. You have to configure it for user "asterisk" and reboot the container.

UPDATE: It only seems to solve to problem to reload the config via cli. Probably @tiredofit has any idea wich user must have permission in order to solve the problem for the ui

fred-gb commented 2 years ago

Thanks @bsteimer Hope @tiredofit can help us.

bsteimer commented 2 years ago

Noticed that next time I had a similiar problem, also with the cli command: This seems to resolve my problem this time: https://community.freepbx.org/t/cron-job-error/79943

fred-gb commented 2 years ago

Hi, Already try before. It solve problem for CLI. But GUI issue persist.

After all, I used the official ISO, because there is lot of limitation in manual or docker install of freepbx/asterisk.

But after install iso version, I have issue with others things ! lol

Thanks

jeffgoh commented 2 years ago

I'm on 15-5.1.1 - realised 15-5.2.0 is now available - will see if it happens there too.

problem seems to be busybox, but I really don't want to make /bin/busybox suid

lrwxrwxrwx 1 root root 12 Feb 15 18:46 /usr/sbin/crontab -> /bin/busybox
[tiredofit/debian:7.3.5 02:37:37] # ls -l /bin/busybox
-rwxr-xr-x 1 root root 1945856 Apr  1  2019 /bin/busybox
[tiredofit/debian:7.3.5 02:38:01] # su - asterisk
asterisk@a9f43e178b2b:~$ crontab
crontab: must be suid to work properly
asterisk@a9f43e178b2b:~$ crontab -e -u asterisk
crontab: must be suid to work properly

Outside the container in my normal host:

# ls -ld /usr/bin/crontab
-rwsr-xr-x. 1 root root 53768 Jan 20  2022 /usr/bin/crontab

Just for kicks, I tried - can't be done:

asterisk@a9f43e178b2b:~$ chmod 4751 /bin/busybox
chmod: changing permissions of '/bin/busybox': Operation not permitted
asterisk@a9f43e178b2b:~$
fcwoknhenuxdfiyv commented 1 year ago

@jeffgoh You were so close! Notice that you're trying to run the chmod command as asterisk. Go back to root, run the command and the problem will be fixed.

jeffgoh commented 1 year ago

You're right - not sure how I missed that. I can confirm that making /bin/busybox setuid allows you to do update via GUI - but that's gotta be a massive security hole. Will go think how to fix this properly, but it's an adequate workaround if your FreePBX instance (both http and SIP) has no exposure to the Internet, I guess.

jeffgoh commented 1 year ago

I went thru a few different images.

# podman image ls
REPOSITORY                   TAG         IMAGE ID      CREATED        SIZE
docker.io/tiredofit/freepbx  15-5.0.7    b799db0118ee  20 months ago  2.08 GB
# podman image ls freepbx
REPOSITORY                      TAG         IMAGE ID      CREATED        SIZE
docker.io/tiredofit/freepbx     15          7a392b8fe0f0  20 months ago  2.08 GB

15-5.0.7 has a standalone binary for crontab which is setgid to crontab, which works:

# ls -l /usr/bin/crontab 
-rwxr-sr-x 1 root crontab 43568 Oct 11  2019 /usr/bin/crontab

15-5.2.0 and 15-5.1.1 have the softlink to /bin/busybox,which doesn't allow the GUI to apply updates:

# podman image ls freepbx
REPOSITORY                   TAG         IMAGE ID      CREATED       SIZE
docker.io/tiredofit/freepbx  15-5.1.1    3bfbf3e0992c  9 months ago  2.07 GB
# podman image ls freepbx
REPOSITORY                      TAG         IMAGE ID      CREATED       SIZE
docker.io/tiredofit/freepbx     5.2.0       4f56953be442  7 months ago  2.07 GB
BeardOverflow commented 1 year ago

My workaround was:

  1. Mount /assets/custom-scripts as persistent storage (ex: ./volumes/freepbx/scripts)
    volumes:
      - ./volumes/freepbx/scripts:/assets/custom-scripts
  2. Create ./volumes/freepbx/scripts/update-suid.sh with the following content:
    #!/bin/bash
    # Workaround: https://github.com/tiredofit/docker-freepbx/issues/196#issuecomment-1337997584
    chmod u+s /bin/busybox
  3. Give executable permission to the previous file
    chmod +x ./volumes/freepbx/scripts/update-suid.sh

During the initialization, you should see this entries in your log output:

freepbx  | 2022-12-05.20:16:28 [INFO] ** [freepbx] Starting Asterisk 17.9.4
freepbx  | 2022-12-05.20:16:28 [WARN] ** [freepbx] Found Custom Scripts to Execute
freepbx  | 2022-12-05.20:16:28 [WARN] ** [freepbx] Running Script /assets/custom-scripts/update-suid.sh
fcwoknhenuxdfiyv commented 1 year ago

You could also create a small Dockerfile:

FROM tiredofit/freepbx:15
RUN chmod u+s /bin/busybox
hobbit378 commented 1 year ago

You're right - not sure how I missed that. I can confirm that making /bin/busybox setuid allows you to do update via GUI - but that's gotta be a massive security hole. Will go think how to fix this properly, but it's an adequate workaround if your FreePBX instance (both http and SIP) has no exposure to the Internet, ...

Not sure, whether this tip here: https://unix.stackexchange.com/questions/279223/how-do-i-set-up-busybox-to-allow-a-non-root-user-to-set-the-date#279230 works with the busybox in the docker image to help to further restrict the required setuid to 'crontab' only. Yet worth giving it a try...

BeardOverflow commented 1 year ago

This bug was introduced for first time since this commit on the parent image tiredofit/docker-debian:

According to the cron applet's documentation:

Crontab manipulates the crontab for a particular user. Only the superuser may specify a different user and/or crontab directory. Note that busybox binary must be setuid root for this applet to work properly.

So, nothing should be wrong for setting up the suid permission.

My thoughts:

  1. As an alternative, tiredofit/docker-debian might ship supercronic and be configurable through CONTAINER_SCHEDULING_BACKEND=supercronic.
  2. The parent image destroys the original cron (rm -rf instead of apt uninstall cron) — I don't understand this decision, and because of it, anyone cannot go back to the previous scheduling backend. I think that the parent image should preserve both cron's debian packaging and cron's busybox, so could be elegible through CONTAINER_SCHEDULING_BACKEND and fulfill its function!
tiredofit commented 1 year ago

Looks like there has been some good problem solving here.

I'm doing the bare minimum on this image for maintenance as I haven't used it in production since 2018, so I appreciate the sleuthing to find out where things have gone wrong. I'm willing to put a patch to make this start saving configuration again, but not much more unless I have better incentives.

There are a few options:

1 - I get a working build of tiredofit/freepbx going with adding SUID bit to busybox as shown in this thread. It works, it doesn't feel right, although I'm more concerned about this image running PHP 5.6 for anyone exposing this to the outside world.

2 - You could investigate the /etc/busybox.conf file that talks about providing poormans SUID to specific applications - This seems the most logical without too much bending.

        bool "Enable SUID configuration via /etc/busybox.conf"
        default y
        depends on FEATURE_SUID
        help
        Allow the SUID/SGID state of an applet to be determined at runtime
        by checking /etc/busybox.conf. (This is sort of a poor man's sudo.)
        The format of this file is as follows:

        APPLET = [Ssx-][Ssx-][x-] [USER.GROUP]

        s: USER or GROUP is allowed to execute APPLET.
           APPLET will run under USER or GROUP
           (regardless of who's running it).
        S: USER or GROUP is NOT allowed to execute APPLET.
           APPLET will run under USER or GROUP.
           This option is not very sensical.
        x: USER/GROUP/others are allowed to execute APPLET.
           No UID/GID change will be done when it is run.
        -: USER/GROUP/others are not allowed to execute APPLET.

        An example might help:

        |[SUID]
        |su = ssx root.0 # applet su can be run by anyone and runs with
        |                # euid=0,egid=0
        |su = ssx        # exactly the same
        |
        |mount = sx- root.disk # applet mount can be run by root and members
        |                      # of group disk (but not anyone else)
        |                      # and runs with euid=0 (egid is not changed)
        |
        |cp = --- # disable applet cp for everyone

        The file has to be owned by user root, group root and has to be
        writeable only by root:
                (chown 0.0 /etc/busybox.conf; chmod 600 /etc/busybox.conf)
        The busybox executable has to be owned by user root, group
        root and has to be setuid root for this to work:
                (chown 0.0 /bin/busybox; chmod 4755 /bin/busybox)

        Robert 'sandman' Griebl has more information here:
        <url: http://www.softforge.de/bb/suid.html >.

3 - Busybox could be compiled from source (twice), 1st package with everything BUT crontab and crond and the second build inversed with those binaries SUID. This is possible just needs understanding how to properly automate it. Busybox uses archaic .config files and I've yet to find a way to flip features on and off like the way I do with configuring FreePBX when configured. I'd be open to some sleuthing on that. I know make defconfig and make allnoconfig but not a make CONFIG_CRON=YES or something of the sort.

4 - The base image could be refactored as BeardOverflow (nice username btw, elicited a morning grin) stated to add a new type of cron management via the functionality I built into the base images.. This at this time I'd leave to the community or would need to be commissioned this type of feature addon.

I'm heading away for a break for a week and will see the responses upon return.