diff --git a/Dockerfile b/Dockerfile index 80d4705719275da25a9dfebd990562f05b77b00a..f3ba2978743e09f2648d753270e8db99adb705d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,59 @@ -FROM hardware/postfixadmin -LABEL maintainer "pinguin@digitalkr.am" +FROM alpine:3.8 + +LABEL description "PostfixAdmin is a web based interface used to manage mailboxes" \ + maintainer="/e/ " + +ARG VERSION=3.2 + +# https://pgp.mit.edu/pks/lookup?search=0xC6A682EA63C82F1C&fingerprint=on&op=index +# pub 4096R/63C82F1C 2005-10-06 Christian Boltz (www.cboltz.de) +ARG GPG_SHORTID="0xC6A682EA63C82F1C" +ARG GPG_FINGERPRINT="70CA A060 DE04 2AAE B1B1 5196 C6A6 82EA 63C8 2F1C" +ARG SHA256_HASH="866d4c0ca870b2cac184e5837a4d201af8fcefecef09bc2c887a6e017a00cefe" + +RUN apk add -t build-dependencies \ + ca-certificates \ + gnupg \ + && apk add \ + su-exec \ + dovecot \ + tini \ + php7 \ + php7-phar \ + php7-fpm \ + php7-imap \ + php7-session \ + php7-mbstring \ + php7-mysqli \ + php7-pdo \ + php7-pdo_mysql \ + php7-openssl \ + openssl \ + && cd /tmp \ + && PFA_TARBALL="postfixadmin-${VERSION}.tar.gz" \ +# TODO: no hash/signature check +# && wget -q https://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-${VERSION}/${PFA_TARBALL} \ +# && wget -q https://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-${VERSION}/${PFA_TARBALL}.asc \ +# && ( \ +# gpg --keyserver pgp.mit.edu --recv-keys ${GPG_SHORTID} || \ +# gpg --keyserver keyserver.pgp.com --recv-keys ${GPG_SHORTID} || \ +# gpg --keyserver ha.pool.sks-keyservers.net --recv-keys ${GPG_SHORTID} \ +# ) \ +# && CHECKSUM=$(sha256sum ${PFA_TARBALL} | awk '{print $1}') \ +# && if [ "${CHECKSUM}" != "${SHA256_HASH}" ]; then echo "ERROR: Checksum does not match!" && exit 1; fi \ +# && FINGERPRINT="$(LANG=C gpg --verify ${PFA_TARBALL}.asc ${PFA_TARBALL} 2>&1 | sed -n "s#Primary key fingerprint: \(.*\)#\1#p")" \ +# && if [ -z "${FINGERPRINT}" ]; then echo "ERROR: Invalid GPG signature!" && exit 1; fi \ +# && if [ "${FINGERPRINT}" != "${GPG_FINGERPRINT}" ]; then echo "ERROR: Wrong GPG fingerprint!" && exit 1; fi \ + && PFA_TARBALL="postfixadmin.tar.gz" \ + && wget "https://github.com/postfixadmin/postfixadmin/archive/d788c6ac9991f60d8256c4f986b72d9fd10ff9d3.tar.gz" -O ${PFA_TARBALL} \ + && mkdir /postfixadmin \ + && tar xzf ${PFA_TARBALL} --strip 1 -C /postfixadmin \ + && apk del build-dependencies \ + && rm -rf /var/cache/apk/* /tmp/* /root/.gnupg ${PFA_TARBALL} COPY bin/run.sh /usr/local/bin -COPY bin/postfixadmin-cli.php /postfixadmin/scripts/postfixadmin-cli.php RUN apk add --no-cache bash openssh \ && adduser -D -s /bin/bash -D pfexec + +EXPOSE 8888 +CMD ["tini", "--", "run.sh"] diff --git a/README.md b/README.md index 429bad23902729c6a8b92a4dfb61dc41a4918446..e1f0e8d37331972361f35f71d4e2a3a3bfb624fe 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # docker-postfixadmin +Based on [hardware/postfixadmin](https://hub.docker.com/r/hardware/postfixadmin) \ No newline at end of file diff --git a/bin/postfixadmin-cli.php b/bin/postfixadmin-cli.php deleted file mode 100755 index 1989943ff7207307a9f948f82fd8b83443c471ff..0000000000000000000000000000000000000000 --- a/bin/postfixadmin-cli.php +++ /dev/null @@ -1,411 +0,0 @@ -#!/usr/bin/php - - * Copyright 2005-2008, Cake Software Foundation, Inc. - * 1785 E. Sahara Avenue, Suite 490-204 - * Las Vegas, Nevada 89104 - * Modified for PostfixAdmin by Valkum 2011 - * Modified for PostfixAdmin by Christian Boltz 2011-2013 - * - * Copyright 2010 - * - * Licensed under The MIT License - * Redistributions of files must retain the above copyright notice. - * - * @filesource - * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. - * @link http://postfixadmin.sourceforge.net/ Postfixadmin on Sourceforge - * @package postfixadmin - * @subpackage - - * @since - - * @version $Revision$ - * @modifiedby $LastChangedBy$ - * @lastmodified $Date$ - * @license http://www.opensource.org/licenses/mit-license.php The MIT License - */ - - -class PostfixAdmin { - /** - * Version - * - * @var string - */ - public $version ='0.2'; - - /** - * Standard input stream. - * - * @var resource - */ - public $stdin; - - /** - * Standard output stream. - * - * @var resource - */ - public $stdout; - - /** - * Standard error stream. - * - * @var resource - */ - public $stderr; - - /** - * Contains command switches parsed from the command line. - * - * @var array - */ - public $params = array(); - - /** - * Contains arguments parsed from the command line. - * - * @var array - */ - public $args = array(); - - /** - * The file name of the shell that was invoked. - * - * @var string - */ - public $shell; - - /** - * The class name of the shell that was invoked. - * - * @var string - */ - public $shellClass; - - /** - * The command called if public methods are available. - * - * @var string - */ - public $shellCommand; - - /** - * The name of the shell in camelized. - * - * @var string - */ - public $shellName; - - /** - * Constructor - * - * @param array $args the argv. - */ - public function __construct($args = array()) { - set_time_limit(0); - $this->__initConstants(); - $this->parseParams($args); - $this->__initEnvironment(); - } - - /** - * Defines core configuration. - */ - private function __initConstants() { - ini_set('display_errors', '1'); - ini_set('error_reporting', '' . E_ALL); - ini_set('html_errors', "0"); - ini_set('implicit_flush', "1"); - ini_set('max_execution_time', "0"); - } - - /** - * Defines current working environment. - */ - private function __initEnvironment() { - $this->stdin = fopen('php://stdin', 'r'); - $this->stdout = fopen('php://stdout', 'w'); - $this->stderr = fopen('php://stderr', 'w'); - - if (basename(__FILE__) != basename($this->args[0])) { - $this->stderr('Warning: the dispatcher may have been loaded incorrectly, which could lead to unexpected results...'); - if ($this->getInput('Continue anyway?', array('y', 'n'), 'y') == 'n') { - exit(1); - } - } - - $this->shiftArgs(); - } - - /** - * Dispatches a CLI request - */ - public function dispatch() { - check_db_version(); # ensure the database layout is up to date - - if (!isset($this->args[0])) { - $this->help(); - return; - } - - $this->shell = $this->args[0]; - $this->shiftArgs(); - $this->shellName = ucfirst($this->shell); - $this->shellClass = $this->shellName . 'Handler'; - - - if ($this->shell == 'help') { - $this->help(); - return; - } - - $command = 'help'; # not the worst default ;-) - if (isset($this->args[0])) { - $command = $this->args[0]; - } - - $this->shellCommand = $command; - $this->shellClass = 'Cli' . ucfirst($command); - - if (ucfirst($command) == 'Add' || ucfirst($command) == 'Update') { - $this->shellClass = 'CliEdit'; - } - - if (!class_exists($this->shellClass)) { - $this->stderr('Unknown task ' . $this->shellCommand); - return; - } - - $shell = new $this->shellClass($this); - - $shell->handler_to_use = ucfirst($this->shell) . 'Handler'; - - if (!class_exists($shell->handler_to_use)) { - $this->stderr('Unknown module ' . $this->shell); - return; - } - - $task = ucfirst($command); - - $shell->new = 0; - if ($task == 'Add') { - $shell->new = 1; - } - - # TODO: add a way to Cli* to signal if the selected handler is supported (for example, not all *Handler support changing the password) - - if (strtolower(get_parent_class($shell)) == 'shell') { - $handler = new $shell->handler_to_use; - if (in_array($task, $handler->taskNames)) { - $this->shiftArgs(); - $shell->startup(); - - if (isset($this->args[0]) && $this->args[0] == 'help') { - if (method_exists($shell, 'help')) { - $shell->help(); - exit(); - } else { - $this->help(); - } - } - - $shell->execute(); - return; - } - } - - $classMethods = get_class_methods($shell); - - $privateMethod = $missingCommand = false; - if ((in_array($command, $classMethods) || in_array(strtolower($command), $classMethods)) && strpos($command, '_', 0) === 0) { - $privateMethod = true; - } - - if (!in_array($command, $classMethods) && !in_array(strtolower($command), $classMethods)) { - $missingCommand = true; - } - - $protectedCommands = array( - 'in', 'out', 'err', 'hr', 'log', - '__construct', 'dispatch', 'stdout', 'stderr' - ); - - if (in_array(strtolower($command), $protectedCommands)) { - $missingCommand = true; - } - - if ($missingCommand && method_exists($shell, 'main')) { - $shell->startup(); - $shell->main(); - } elseif (!$privateMethod && method_exists($shell, $command)) { - $this->shiftArgs(); - $shell->startup(); - $shell->{$command}(); - } else { - $this->stderr("Unknown {$this->shellName} command '$command'.\nFor usage, try 'postfixadmin-cli {$this->shell} help'.\n\n"); - } - } - - /** - * Prompts the user for input, and returns it. - * - * @param string $prompt Prompt text. - * @param mixed $options Array or string of options. - * @param string $default Default input value. - * @return string Either the default value, or the user-provided input. - */ - public function getInput($prompt, $options = null, $default = null) { - if (!is_array($options)) { - $print_options = ''; - } else { - $print_options = '(' . implode('/', $options) . ')'; - } - - if ($default == null) { - $this->stdout($prompt . " $print_options \n" . '> ', false); - } else { - $this->stdout($prompt . " $print_options \n" . "[$default] > ", false); - } - $result = fgets($this->stdin); - - if ($result === false) { - exit(1); - } - $result = trim($result); - - if ($default != null && empty($result)) { - return $default; - } - return $result; - } - - /** - * Outputs to the stdout filehandle. - * - * @param string $string String to output. - * @param boolean $newline If true, the outputs gets an added newline. - */ - public function stdout($string, $newline = true) { - if ($newline) { - fwrite($this->stdout, $string . "\n"); - } else { - fwrite($this->stdout, $string); - } - } - - /** - * Outputs to the stderr filehandle. - * - * @param string $string Error text to output. - */ - public function stderr($string) { - fwrite($this->stderr, 'Error: '. $string . "\n"); - } - - /** - * Parses command line options - * - * @param array $params Parameters to parse - */ - public function parseParams($params) { - $this->__parseParams($params); - } - - /** - * Helper for recursively paraing params - */ - private function __parseParams($params) { - $count = count($params); - for ($i = 0; $i < $count; $i++) { - if (isset($params[$i])) { - if ($params[$i] != '' && $params[$i]{0} === '-') { - $key = substr($params[$i], 1); - $this->params[$key] = true; - unset($params[$i]); - if (isset($params[++$i])) { - # TODO: ideally we should know if a parameter can / must have a value instead of whitelisting known valid values starting with '-' (probably only bool doesn't need a value) - if ($params[$i]{0} !== '-' or $params[$i] != '-1') { - $this->params[$key] = $params[$i]; - unset($params[$i]); - } else { - $i--; - $this->__parseParams($params); - } - } - } else { - $this->args[] = $params[$i]; - unset($params[$i]); - } - } - } - } - - /** - * Removes first argument and shifts other arguments up - * - * @return boolean False if there are no arguments - */ - public function shiftArgs() { - if (empty($this->args)) { - return false; - } - unset($this->args[0]); - $this->args = array_values($this->args); - return true; - } - - /** - * prints help message and exits. - */ - public function help() { - $this->stdout("\nWelcome to Postfixadmin-CLI v" . $this->version); - $this->stdout("---------------------------------------------------------------"); - $this->stdout("Usage:"); - $this->stdout(" postfixadmin-cli [--option value --option2 value]"); - $this->stdout(""); - $this->stdout("Available modules:"); - - $modules = explode(',', 'admin,domain,mailbox,alias,aliasdomain,fetchmail'); - foreach ($modules as $module) { - $this->stdout(" $module"); - } - $this->stdout(""); - $this->stdout("Most modules support the following tasks:"); - $this->stdout(" view View an item"); - $this->stdout(" add Add an item"); - $this->stdout(" update Update an item"); - $this->stdout(" delete Delete an item"); - $this->stdout(" scheme Print database scheme (useful for developers only)"); - $this->stdout(" help Print help output"); - $this->stdout(""); - $this->stdout(""); - $this->stdout("For module-specific help, see:"); - $this->stdout(""); - $this->stdout(" postfixadmin-cli help"); - $this->stdout(" print a detailed list of available commands"); - $this->stdout(""); - $this->stdout(" postfixadmin-cli help"); - $this->stdout(" print a list of available options."); - $this->stdout(""); - - exit(); - } -} - - -define("POSTFIXADMIN_CLI", 1); - -require_once(dirname(__FILE__) . '/../common.php'); - -$dispatcher = new PostfixAdmin($argv); -$dispatcher->dispatch(); - -/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */ \ No newline at end of file diff --git a/bin/run.sh b/bin/run.sh index c26f9eb18ccb07d5322a2210cc697c191a4c104e..1e6943247a43bb616084f48d1d71c53364b9be9b 100755 --- a/bin/run.sh +++ b/bin/run.sh @@ -50,12 +50,15 @@ cat > /postfixadmin/config.local.php <