GODT-1816: Connect Gluon Logs to bridge Logs

Ensure the IMAP commands and SMTP commands are logged to trace channels
with an entry so they are recognizable as before.
This commit is contained in:
Leander Beernaert
2022-10-11 16:03:28 +02:00
committed by James Houlahan
parent 03e14154a6
commit f01c70e506
10 changed files with 136 additions and 19 deletions

View File

@ -32,6 +32,9 @@ const (
flagNoWindow = "no-window"
flagNonInteractive = "non-interactive"
flagLogIMAP = "log-imap"
flagLogSMTP = "log-smtp"
)
const (
@ -69,6 +72,14 @@ func New() *cli.App {
Usage: "Don't show window after start",
Hidden: true,
},
&cli.StringFlag{
Name: flagLogIMAP,
Usage: "Enable logging of IMAP communications (all|client|server) (may contain decrypted data!)",
},
&cli.BoolFlag{
Name: flagLogSMTP,
Usage: "Enable logging of SMTP communications (may contain decrypted data!)",
},
}
app.Action = run
@ -124,7 +135,7 @@ func run(c *cli.Context) error {
}
// Create the bridge.
bridge, err := newBridge(locations, identifier)
bridge, err := newBridge(c, locations, identifier)
if err != nil {
return fmt.Errorf("could not create bridge: %w", err)
}

View File

@ -3,6 +3,7 @@ package app
import (
"encoding/base64"
"fmt"
"github.com/urfave/cli/v2"
"os"
"runtime"
@ -25,7 +26,7 @@ import (
const vaultSecretName = "bridge-vault-key"
func newBridge(locations *locations.Locations, identifier *useragent.UserAgent) (*bridge.Bridge, error) {
func newBridge(c *cli.Context, locations *locations.Locations, identifier *useragent.UserAgent) (*bridge.Bridge, error) {
// Create the underlying dialer used by the bridge.
// It only connects to trusted servers and reports any untrusted servers it finds.
pinningDialer := dialer.NewPinningTLSDialer(
@ -92,6 +93,9 @@ func newBridge(locations *locations.Locations, identifier *useragent.UserAgent)
autostarter,
updater,
version,
c.String(flagLogIMAP) == "client" || c.String(flagLogIMAP) == "all",
c.String(flagLogIMAP) == "server" || c.String(flagLogIMAP) == "all",
c.Bool(flagLogSMTP),
)
if err != nil {
return nil, fmt.Errorf("could not create bridge: %w", err)

View File

@ -72,6 +72,10 @@ type Bridge struct {
// stopCh is used to stop ongoing goroutines when the bridge is closed.
stopCh chan struct{}
logIMAPClientCommands bool
logIMAPServerCommands bool
logSMTPCommands bool
}
// New creates a new bridge.
@ -86,6 +90,9 @@ func New(
autostarter Autostarter, // the autostarter to manage autostart settings
updater Updater, // the updater to fetch and install updates
curVersion *semver.Version, // the current version of the bridge
logIMAPClientCommands bool,
logIMAPServerCommands bool,
logSMTPCommands bool,
) (*Bridge, error) {
if vault.GetProxyAllowed() {
proxyCtl.AllowProxy()
@ -116,7 +123,7 @@ func New(
return nil, fmt.Errorf("failed to get Gluon directory: %w", err)
}
imapServer, err := newIMAPServer(gluonDir, curVersion, tlsConfig)
imapServer, err := newIMAPServer(gluonDir, curVersion, tlsConfig, logIMAPClientCommands, logIMAPServerCommands)
if err != nil {
return nil, fmt.Errorf("failed to create IMAP server: %w", err)
}
@ -126,7 +133,7 @@ func New(
return nil, fmt.Errorf("failed to create SMTP backend: %w", err)
}
smtpServer, err := newSMTPServer(smtpBackend, tlsConfig)
smtpServer, err := newSMTPServer(smtpBackend, tlsConfig, logSMTPCommands)
if err != nil {
return nil, fmt.Errorf("failed to create SMTP server: %w", err)
}
@ -159,6 +166,10 @@ func New(
locator: locator,
stopCh: make(chan struct{}),
logIMAPClientCommands: logIMAPClientCommands,
logIMAPServerCommands: logIMAPServerCommands,
logSMTPCommands: logSMTPCommands,
}
api.AddStatusObserver(func(status liteapi.Status) {

View File

@ -426,6 +426,9 @@ func withBridge(
mocks.Autostarter,
mocks.Updater,
v2_3_0,
false,
false,
false,
)
require.NoError(t, err)

View File

@ -5,6 +5,8 @@ import (
"crypto/tls"
"errors"
"fmt"
"github.com/ProtonMail/proton-bridge/v2/internal/logging"
"io"
"io/fs"
"net"
"os"
@ -111,7 +113,29 @@ func getGluonDir(encVault *vault.Vault) (string, error) {
return encVault.GetGluonDir(), nil
}
func newIMAPServer(gluonDir string, version *semver.Version, tlsConfig *tls.Config) (*gluon.Server, error) {
func newIMAPServer(gluonDir string, version *semver.Version, tlsConfig *tls.Config, logIMAPCommandsClient, logImapCommandsServer bool) (*gluon.Server, error) {
var imapClientLog io.Writer
var imapServerLog io.Writer
if logIMAPCommandsClient || logImapCommandsServer {
log := logrus.WithField("protocol", "IMAP")
log.Warning("================================================")
log.Warning("THIS LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
log.Warning("================================================")
}
if logIMAPCommandsClient {
imapClientLog = logging.NewIMAPLogger()
} else {
imapClientLog = io.Discard
}
if logImapCommandsServer {
imapServerLog = logging.NewIMAPLogger()
} else {
imapClientLog = io.Discard
}
imapServer, err := gluon.New(
gluon.WithTLS(tlsConfig),
gluon.WithDataDir(gluonDir),
@ -124,8 +148,8 @@ func newIMAPServer(gluonDir string, version *semver.Version, tlsConfig *tls.Conf
"TODO",
),
gluon.WithLogger(
logrus.StandardLogger().WriterLevel(logrus.TraceLevel),
logrus.StandardLogger().WriterLevel(logrus.TraceLevel),
imapClientLog,
imapServerLog,
),
)
if err != nil {

View File

@ -112,7 +112,7 @@ func (bridge *Bridge) SetGluonDir(ctx context.Context, newGluonDir string) error
return fmt.Errorf("failed to set new gluon dir: %w", err)
}
imapServer, err := newIMAPServer(bridge.vault.GetGluonDir(), bridge.curVersion, bridge.tlsConfig)
imapServer, err := newIMAPServer(bridge.vault.GetGluonDir(), bridge.curVersion, bridge.tlsConfig, bridge.logIMAPClientCommands, bridge.logIMAPServerCommands)
if err != nil {
return fmt.Errorf("failed to create new IMAP server: %w", err)
}

View File

@ -3,6 +3,7 @@ package bridge
import (
"crypto/tls"
"fmt"
"github.com/ProtonMail/proton-bridge/v2/internal/logging"
"net"
"strconv"
@ -48,7 +49,7 @@ func (bridge *Bridge) restartSMTP() error {
return err
}
smtpServer, err := newSMTPServer(bridge.smtpBackend, bridge.tlsConfig)
smtpServer, err := newSMTPServer(bridge.smtpBackend, bridge.tlsConfig, bridge.logSMTPCommands)
if err != nil {
return err
}
@ -68,13 +69,22 @@ func (bridge *Bridge) closeSMTP() error {
return nil
}
func newSMTPServer(smtpBackend *smtpBackend, tlsConfig *tls.Config) (*smtp.Server, error) {
func newSMTPServer(smtpBackend *smtpBackend, tlsConfig *tls.Config, shouldLog bool) (*smtp.Server, error) {
smtpServer := smtp.NewServer(smtpBackend)
smtpServer.TLSConfig = tlsConfig
smtpServer.Domain = constants.Host
smtpServer.AllowInsecureAuth = true
smtpServer.MaxLineLength = 1 << 16
smtpServer.ErrorLog = logging.NewSMTPLogger()
if shouldLog {
log := logrus.WithField("protocol", "SMTP")
log.Warning("================================================")
log.Warning("THIS LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
log.Warning("================================================")
smtpServer.Debug = logging.NewSMTPDebugLogger()
}
smtpServer.EnableAuth(sasl.Login, func(conn *smtp.Conn) sasl.Server {
return sasl.NewLoginServer(func(address, password string) error {

View File

@ -0,0 +1,16 @@
package logging
import "github.com/sirupsen/logrus"
// IMAPLogger implements the writer interface for Gluon IMAP logs
type IMAPLogger struct {
l *logrus.Entry
}
func NewIMAPLogger() *IMAPLogger {
return &IMAPLogger{l: logrus.WithField("pkg", "IMAP")}
}
func (l *IMAPLogger) Write(p []byte) (n int, err error) {
return l.l.WriterLevel(logrus.TraceLevel).Write(p)
}

View File

@ -0,0 +1,35 @@
package logging
import (
"github.com/sirupsen/logrus"
)
// SMTPErrorLogger implements go-smtp/logger interface.
type SMTPErrorLogger struct {
l *logrus.Entry
}
func NewSMTPLogger() *SMTPErrorLogger {
return &SMTPErrorLogger{l: logrus.WithField("pkg", "SMTP")}
}
func (s *SMTPErrorLogger) Printf(format string, args ...interface{}) {
s.l.Errorf(format, args...)
}
func (s *SMTPErrorLogger) Println(args ...interface{}) {
s.l.Errorln(args...)
}
// SMTPDebugLogger implements the writer interface for debug SMTP logs
type SMTPDebugLogger struct {
l *logrus.Entry
}
func NewSMTPDebugLogger() *SMTPDebugLogger {
return &SMTPDebugLogger{l: logrus.WithField("pkg", "SMTP")}
}
func (l *SMTPDebugLogger) Write(p []byte) (n int, err error) {
return l.l.WriterLevel(logrus.TraceLevel).Write(p)
}

View File

@ -48,6 +48,9 @@ func (t *testCtx) startBridge() error {
t.mocks.Autostarter,
t.mocks.Updater,
t.version,
false,
false,
false,
)
if err != nil {
return err