Change docker user and some minor improvements

This commit is contained in:
Xiaonan Shen
2022-05-28 17:28:20 +08:00
parent c38ac6fbb5
commit 1c64b99201
6 changed files with 125 additions and 52 deletions

View File

@@ -11,7 +11,7 @@ COPY build.sh /build/
COPY http_rest_frontend /build/http_rest_frontend
RUN bash build.sh
FROM ubuntu:bionic
FROM krallin/ubuntu-tini:bionic
LABEL maintainer="Xiaonan Shen <s@sxn.dev>"
EXPOSE 25/tcp
@@ -19,13 +19,15 @@ EXPOSE 143/tcp
# Install dependencies and protonmail bridge
RUN apt-get update \
&& apt-get install -y --no-install-recommends socat pass libsecret-1-0 ca-certificates dbus-x11 \
&& apt-get install -y --no-install-recommends socat pass libsecret-1-0 ca-certificates curl gosu \
&& rm -rf /var/lib/apt/lists/*
# Copy bash scripts
COPY gpgparams entrypoint.sh /srv/protonmail/
COPY gpgparams entrypoint.sh run_protonmail_bridge.sh cli.sh /protonmail/bin/
# Copy protonmail
COPY --from=build /build/proton-bridge/proton-bridge /srv/protonmail/
COPY --from=build /build/proton-bridge/proton-bridge /protonmail/bin
ENV PATH "/protonmail/bin:${PATH}"
ENTRYPOINT ["bash", "/srv/protonmail/entrypoint.sh"]
VOLUME [ "/protonmail/data" ]
ENTRYPOINT ["/usr/local/bin/tini", "--", "/protonmail/bin/entrypoint.sh"]

6
cli.sh
View File

@@ -2,7 +2,7 @@
set -e
URL_BASE=http://127.0.0.1:1080
URL_BASE=http://127.0.0.1:${PROTON_MANAGEMENT_PORT:-1080}
print_help() {
echo "Available commands:"
@@ -24,12 +24,14 @@ account_login() {
echo
read -p "2FA Code (leave empty if not set): " TWO_FACTOR
read -p "Mailbox Password (leave empty if not set): " MAILBOX_PASSWORD
read -p "Address Mode (combined / split): " ADDRESS_MODE
curl ${URL_BASE}/accounts -XPUT \
--data-urlencode "username=${USERNAME}" \
--data-urlencode "password=${PASSWORD}" \
--data-urlencode "two-factor=${TWO_FACTOR}" \
--data-urlencode "mailbox-password=${MAILBOX_PASSWORD}"
--data-urlencode "mailbox-password=${MAILBOX_PASSWORD}" \
--data-urlencode "address-mode=${ADDRESS_MODE}"
}
account_delete() {

41
entrypoint.sh Normal file → Executable file
View File

@@ -2,36 +2,15 @@
set -e
# Generate gpg keys
if [ ! -f ${HOME}/.gnupg ]; then
echo "Generateing gpg keys..."
# set GNUPGHOME as a workaround for
#
# gpg-agent[106]: error binding socket to '/root/.gnupg/S.gpg-agent': File name too long
#
# when using docker volume mount
#
# ref: https://dev.gnupg.org/T2964
#
export GNUPGHOME=/tmp/gnupg
mkdir ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
gpg --generate-key --batch /srv/protonmail/gpgparams
pkill gpg-agent
mv ${GNUPGHOME} ${HOME}/.gnupg
export GNUPGHOME=""
fi
echo "Welcome to ProtonMail Bridge Docker 2.0. This version comes with plently of"
echo "improvements. This version is not compatible with old configs and data volumes."
echo "If you are coming from the old version, please clean up your volumes and set up"
echo "everything from scratch. For more information about the new version, check"
echo "https://github.com/shenxn/protonmail-bridge-docker"
echo
# Initialize pass
if [ ! -f ${HOME}/.password-store/.gpg-id ]; then
echo "Initializing pass"
pass init pass-key
fi
groupadd -g ${PROTON_GID:-1001} proton
useradd -g proton -u ${PROTON_UID:-1001} -m proton
chown proton:proton -R /protonmail/data
# socat will make the conn appear to come from 127.0.0.1
# ProtonMail Bridge currently expects that.
# It also allows us to bind to the real ports :)
socat TCP-LISTEN:25,fork TCP:127.0.0.1:1025 &
socat TCP-LISTEN:143,fork TCP:127.0.0.1:1143 &
/srv/protonmail/proton-bridge --cli $@
exec gosu proton:proton run_protonmail_bridge.sh "$@"

View File

@@ -6,11 +6,13 @@ import (
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/ProtonMail/proton-bridge/internal/config/settings"
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
"github.com/julienschmidt/httprouter"
"github.com/sirupsen/logrus"
)
func (f *frontendCLI) loginAccount(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
@@ -23,33 +25,38 @@ func (f *frontendCLI) loginAccount(w http.ResponseWriter, r *http.Request, _ htt
password := r.FormValue("password")
twoFactor := r.FormValue("two-factor")
mailboxPassword := r.FormValue("mailbox-password")
addressMode := r.FormValue("address-mode")
if addressMode == "" {
addressMode = "combined"
}
if addressMode != "combined" && addressMode != "split" {
http.Error(w, fmt.Sprintf("%s is not a valid address mode. Choose from 'combined' and 'split'."), http.StatusBadRequest)
return
}
client, auth, err := f.bridge.Login(username, []byte(password))
if err != nil {
f.processAPIError(err)
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "Server error:", err.Error())
http.Error(w, fmt.Sprintf("Server error: %s", err.Error()), http.StatusUnauthorized)
return
}
if auth.HasTwoFactor() {
if twoFactor == "" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "2FA enabled for the account but a 2FA code was not provided.")
http.Error(w, "2FA enabled for the account but a 2FA code was not provided.", http.StatusUnauthorized)
return
}
err = client.Auth2FA(context.Background(), twoFactor)
if err != nil {
f.processAPIError(err)
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "Server error:", err.Error())
http.Error(w, fmt.Sprintf("Server error: %s", err.Error()), http.StatusUnauthorized)
return
}
}
if auth.HasMailboxPassword() {
if mailboxPassword == "" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "Two password mode enabled but a mailbox password was not provided.")
http.Error(w, "Two password mode enabled but a mailbox password was not provided.", http.StatusUnauthorized)
return
}
} else {
@@ -58,11 +65,20 @@ func (f *frontendCLI) loginAccount(w http.ResponseWriter, r *http.Request, _ htt
user, err := f.bridge.FinishLogin(client, auth, []byte(mailboxPassword))
if err != nil {
f.processAPIError(err)
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "Server error:", err.Error())
http.Error(w, fmt.Sprintf("Server error: %s", err.Error()), http.StatusUnauthorized)
return
}
fmt.Fprintf(w, "Account %s was added successfully.\n", user.Username())
if addressMode == "split" {
err = user.SwitchAddressMode()
if err != nil {
logrus.Errorf("Failed to switch address mode of %s to split: %s", user.Username(), err.Error())
http.Error(w, "Failed to switch address mode to split", http.StatusInternalServerError)
return
}
}
f.printAccountInfo(w, user)
}
@@ -135,10 +151,10 @@ func (f *frontendCLI) printAccountAddressInfo(w io.Writer, user types.User, addr
if f.settings.GetBool(settings.SMTPSSLKey) {
smtpSecurity = "SSL"
}
fmt.Fprintf(w, "IMAP port: %d\nIMAP security: %s\nSMTP port: %d\nSMTP security: %s\nUsername: %s\nPassword: %s\n",
143,
fmt.Fprintf(w, "IMAP port: %s\nIMAP security: %s\nSMTP port: %s\nSMTP security: %s\nUsername: %s\nPassword: %s\n",
os.Getenv("PROTON_IMAP_PORT"),
"STARTTLS",
25,
os.Getenv("PROTON_SMTP_PORT"),
smtpSecurity,
address,
user.GetBridgePassword(),

View File

@@ -146,7 +146,11 @@ func (f *frontendCLI) watchEvents() {
func (f *frontendCLI) Loop() error {
f.loginWithEnv()
http.ListenAndServe(":1080", f)
managementPort := os.Getenv("PROTON_MANAGEMENT_PORT")
if managementPort == "" {
managementPort = "1080"
}
http.ListenAndServe(":"+managementPort, f)
return nil
}

70
run_protonmail_bridge.sh Executable file
View File

@@ -0,0 +1,70 @@
#!/bin/bash
set -e
# Generate gpg keys
GNUPG_PATH=/protonmail/data/gnupg
export GNUPGHOME=${GNUPG_PATH}
if [ ! -f ${GNUPG_PATH} ]; then
echo "Generateing gpg keys..."
# set GNUPGHOME to a temp directory as a workaround for
#
# gpg-agent[106]: error binding socket to '/root/.gnupg/S.gpg-agent': File name too long
#
# when using docker volume mount
#
# ref: https://dev.gnupg.org/T2964
#
export GNUPGHOME=/tmp/gnupg
mkdir ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
gpg --generate-key --batch /protonmail/bin/gpgparams
pkill gpg-agent
mv ${GNUPGHOME} ${GNUPG_PATH}
export GNUPGHOME=${GNUPG_PATH}
fi
# Initialize pass
PASSWORD_STORE=/protonmail/data/password-store
if [ ! -f ${PASSWORD_STORE} ]; then
echo "Initializing pass..."
pass init pass-key
# Move password store to /protonmail/data
mv ${HOME}/.password-store ${PASSWORD_STORE}
fi
# Link the password store back to ~/.password-store
# There is no easy way to change the path used by pass
ln -s ${PASSWORD_STORE} ${HOME}/.password-store
# Link config and cache folders to /protonmail/data
PROTON_CONFIG_PATH=/protonmail/data/config
PROTON_CACHE_PATH=/protonmail/data/cache
mkdir -p ${PROTON_CONFIG_PATH}
mkdir -p ${HOME}/.config
ln -s ${PROTON_CONFIG_PATH} ${HOME}/.config/protonmail
mkdir -p ${PROTON_CACHE_PATH}
mkdir ${HOME}/.cache
ln -s ${PROTON_CACHE_PATH} ${HOME}/.cache/protonmail
# Generateing perfs.json
mkdir -p ${PROTON_CONFIG_PATH}/bridge
if [ ${PROTON_SMTP_SECURITY:-STARTTLS} == "SSL" ]; then
PROTON_SSL_SMTP="true"
else
PROTON_SSL_SMTP="false"
fi
cat <<EOF > ${PROTON_CONFIG_PATH}/bridge/prefs.json
{
"allow_proxy": "${PROTON_ALLOW_PROXY:-true}",
"autoupdate": "false",
"user_ssl_smtp": "${PROTON_SSL_SMTP}"
}
EOF
# socat will make the conn appear to come from 127.0.0.1
# ProtonMail Bridge currently expects that.
# It also allows us to bind to the real ports :)
socat TCP-LISTEN:${PROTON_SMTP_PORT:=25},fork TCP:127.0.0.1:1025 &
socat TCP-LISTEN:${PROTON_IMAP_PORT:=143},fork TCP:127.0.0.1:1143 &
exec proton-bridge --cli "$@"