Skip to content

Commit

Permalink
opentelemetry semconv attributes + linting
Browse files Browse the repository at this point in the history
  • Loading branch information
vodolaz095 committed Dec 9, 2023
1 parent c26e1af commit 213ad20
Show file tree
Hide file tree
Showing 12 changed files with 42 additions and 47 deletions.
9 changes: 5 additions & 4 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"go.opentelemetry.io/otel/trace"
)

Expand Down Expand Up @@ -139,7 +140,8 @@ type Server struct {
EnableXCLIENT bool
// EnableProxyProtocol enables Proxy command support (disabled by default, since it is security risk)
EnableProxyProtocol bool

// HideTransactionHeader hides transaction header
HideTransactionHeader bool
// TLSConfig is used both for STARTTLS and operation over TLS channel
TLSConfig *tls.Config
// ForceTLS requires connections to be encrypted
Expand Down Expand Up @@ -186,9 +188,8 @@ func (srv *Server) startTransaction(c net.Conn) (t *Transaction) {
remoteAddr := c.RemoteAddr().(*net.TCPAddr)
ctxWithTracer, span := srv.Tracer.Start(ctx, "transaction",
trace.WithSpanKind(trace.SpanKindServer), // важно
trace.WithAttributes(attribute.String("remote_addr", c.RemoteAddr().String())),
trace.WithAttributes(attribute.String("remote_ip", remoteAddr.IP.String())),
trace.WithAttributes(attribute.Int("remote_port", remoteAddr.Port)),
trace.WithAttributes(semconv.ClientSocketAddress(remoteAddr.IP.String())),
trace.WithAttributes(semconv.ClientSocketPort(remoteAddr.Port)),
)
t = &Transaction{
ID: span.SpanContext().TraceID().String(),
Expand Down
2 changes: 1 addition & 1 deletion server_counters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestCounters(t *testing.T) {
if srv.lastTransactionStartedAt.IsZero() {
t.Errorf("transaction time is not set")
}
if time.Now().Sub(srv.lastTransactionStartedAt) > 3*time.Second {
if time.Since(srv.lastTransactionStartedAt) > 3*time.Second {
t.Errorf("last transaction time is too old")
}
}
Expand Down
10 changes: 5 additions & 5 deletions transaction_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
)

func (t *Transaction) handleAUTH(cmd command) {
Expand Down Expand Up @@ -58,7 +59,7 @@ func (t *Transaction) handleAUTH(cmd command) {
}
username = string(parts[1])
password = string(parts[2])
break

case "LOGIN":
encodedUsername := ""
if len(cmd.fields) < 3 {
Expand Down Expand Up @@ -87,7 +88,7 @@ func (t *Transaction) handleAUTH(cmd command) {
}
username = string(byteUsername)
password = string(bytePassword)
break

default:
t.LogDebug("unknown authentication mechanism: %s", mechanism)
t.reply(502, "Unknown authentication mechanism")
Expand All @@ -106,8 +107,7 @@ func (t *Transaction) handleAUTH(cmd command) {
// i know saving password here is security risk, but we can implement something like
// Haraka plugin to prevent credential leaks
// https://haraka.github.io/plugins/prevent_credential_leaks
t.Span.SetAttributes(attribute.String("username", username))
t.Span.SetAttributes(attribute.String("password", mask(password)))
t.Span.SetAttributes(semconv.EnduserID(username))
t.Span.SetAttributes(attribute.String("enduser.password", mask(password)))
t.reply(235, "OK, you are now authenticated")
return
}
15 changes: 10 additions & 5 deletions transaction_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var uniqueHeaders = []string{
"Subject",
}

func (t *Transaction) handleDATA(cmd command) {
func (t *Transaction) handleDATA(_ command) {
var checkErr error
var deliverErr error
var createdAt time.Time
Expand Down Expand Up @@ -69,15 +69,21 @@ func (t *Transaction) handleDATA(cmd command) {
}
t.LogDebug("DATA is called...")
t.reply(354, "Ok, you managed to talk me into accepting your message. Go on, end your data with <CR><LF>.<CR><LF>")
t.conn.SetDeadline(time.Now().Add(t.server.DataTimeout))
err := t.conn.SetDeadline(time.Now().Add(t.server.DataTimeout))
if err != nil {
t.LogError(err, "while setting deadline for connection")
return
}
data := bytes.NewBufferString("")
reader := textproto.NewReader(t.reader).DotReader()
_, err := io.CopyN(data, reader, int64(t.server.MaxMessageSize))
_, err = io.CopyN(data, reader, int64(t.server.MaxMessageSize))
if err != nil {
if err == io.EOF {
// EOF was reached before MaxMessageSize, so we can accept and deliver message
t.Body = data.Bytes()
t.AddHeader("MSMTPD-Transaction-Id", t.ID)
if !t.server.HideTransactionHeader {
t.AddHeader("MSMTPD-Transaction-Id", t.ID)
}
t.AddReceivedLine() // will be added as first one
t.LogDebug("Parsing message body with size %v...", data.Len())
t.Span.SetAttributes(attribute.Int("size", data.Len()))
Expand Down Expand Up @@ -205,5 +211,4 @@ func (t *Transaction) handleDATA(cmd command) {
))
t.Hate(tooBigMessagePenalty)
t.reset()
return
}
21 changes: 3 additions & 18 deletions transaction_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,60 +12,45 @@ func (t *Transaction) handle(line string) {
switch cmd.action {
case "PROXY":
t.handlePROXY(cmd)
break
case "HELO":
t.handleHELO(cmd)
break
case "EHLO":
t.handleEHLO(cmd)
break
case "MAIL":
t.handleMAIL(cmd)
break
case "RCPT":
t.handleRCPT(cmd)
break
case "STARTTLS":
t.handleSTARTTLS(cmd)
break
case "DATA":
t.handleDATA(cmd)
break
case "RSET":
t.handleRSET(cmd)
break
case "NOOP":
t.handleNOOP(cmd)
break
case "QUIT":
t.handleQUIT(cmd)
break
case "AUTH":
t.handleAUTH(cmd)
break
case "XCLIENT":
t.handleXCLIENT(cmd)
break
default:
t.Hate(unknownCommandPenalty)
t.LogDebug("Unsupported command received: %s", line)
t.reply(502, "Unsupported command.")
}
}

func (t *Transaction) handleRSET(cmd command) {
func (t *Transaction) handleRSET(_ command) {
t.reset()
t.reply(250, "I forgot everything you have said, go ahead please!")
return
}

func (t *Transaction) handleNOOP(cmd command) {
func (t *Transaction) handleNOOP(_ command) {
t.reply(250, "I'm finishing procrastinating, go ahead please!")
return
}

func (t *Transaction) handleQUIT(cmd command) {
func (t *Transaction) handleQUIT(_ command) {
t.reply(221, fmt.Sprintf("Farewell, my friend! Transaction %s is finished", t.ID))
t.close()
return
}
5 changes: 3 additions & 2 deletions transaction_helo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
)

func (t *Transaction) handleHELO(cmd command) {
Expand All @@ -21,7 +22,7 @@ func (t *Transaction) handleHELO(cmd command) {
t.HeloName = cmd.fields[1]
t.Protocol = SMTP
t.Span.SetAttributes(attribute.String("helo", t.HeloName))
t.Span.SetAttributes(attribute.String("protocol", "SMTP"))
t.Span.SetAttributes(semconv.NetProtocolName("smtp"))
for k := range t.server.HeloCheckers {
err = t.server.HeloCheckers[k](t)
if err != nil {
Expand Down Expand Up @@ -68,7 +69,7 @@ func (t *Transaction) handleEHLO(cmd command) {
t.HeloName = cmd.fields[1]
t.Protocol = ESMTP
t.Span.SetAttributes(attribute.String("ehlo", t.HeloName))
t.Span.SetAttributes(attribute.String("protocol", "ESMTP"))
t.Span.SetAttributes(semconv.NetProtocolName("esmtp"))
for k := range t.server.HeloCheckers {
err = t.server.HeloCheckers[k](t)
if err != nil {
Expand Down
1 change: 0 additions & 1 deletion transaction_mailfrom.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,4 @@ func (t *Transaction) handleMAIL(cmd command) {
)
t.reply(250, "Ok, it makes sense, go ahead please!")
t.Love(commandExecutedProperly)
return
}
4 changes: 2 additions & 2 deletions transaction_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ func (t *Transaction) handlePROXY(cmd command) {
return
}
var (
newAddr net.IP = nil
newTCPPort uint64 = 0
newAddr net.IP
newTCPPort uint64
err error
)
switch cmd.fields[1] {
Expand Down
4 changes: 0 additions & 4 deletions transaction_rcpt_to.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,10 @@ func (t *Transaction) handleRCPT(cmd command) {
switch len(t.RcptTo) {
case 1:
t.LogInfo("Recipient %s will be 1st one in transaction!", addr)
break
case 2:
t.LogInfo("Recipient %s will be 2nd one in transaction!", addr)
break
case 3:
t.LogInfo("Recipient %s will be 3rd one in transaction!", addr)
break
default:
t.LogInfo("Recipient %s will be %dth one in transaction!", addr, len(t.RcptTo))
}
Expand All @@ -86,5 +83,4 @@ func (t *Transaction) handleRCPT(cmd command) {
if len(t.RcptTo) == 1 { // too many recipients should not give too many love for transaction
t.Love(commandExecutedProperly)
}
return
}
12 changes: 10 additions & 2 deletions transaction_startTLS.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
)

func (t *Transaction) handleSTARTTLS(cmd command) {
var err error
if t.Encrypted {
t.LogDebug("Connection is already encrypted!")
t.reply(502, "Already running in TLS")
Expand All @@ -21,7 +22,8 @@ func (t *Transaction) handleSTARTTLS(cmd command) {
t.LogDebug("STARTTLS [%s] is received...", cmd.line)
tlsConn := tls.Server(t.conn, t.server.TLSConfig)
t.reply(220, "Connection is encrypted, we can talk freely now!")
if err := tlsConn.Handshake(); err != nil {
err = tlsConn.Handshake()
if err != nil {
t.LogError(err, "couldn't perform handshake")
t.reply(550, "TLS Handshake error")
return
Expand All @@ -32,7 +34,13 @@ func (t *Transaction) handleSTARTTLS(cmd command) {
t.reset()
// Reset deadlines on the underlying connection before I replace it
// with a TLS connection
t.conn.SetDeadline(time.Time{})
err = t.conn.SetDeadline(time.Time{})
if err != nil {
t.LogError(err, "error setting deadline for encrypted connection")
t.reply(550, "TLS Handshake error")
return
}

// Replace connection with a TLS connection
t.conn = tlsConn
t.reader = bufio.NewReader(tlsConn)
Expand Down
2 changes: 1 addition & 1 deletion transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func TestKarma(t *testing.T) {
if err != nil {
t.Errorf("Data failed: %v", err)
}
_, err = fmt.Fprintf(wc, internal.MakeTestMessage("[email protected]", "[email protected]"))
_, err = fmt.Fprint(wc, internal.MakeTestMessage("[email protected]", "[email protected]"))
if err != nil {
t.Errorf("Data body failed: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions transaction_xclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ func (t *Transaction) handleXCLIENT(cmd command) {
newUsername = value
continue
case "PROTO":
if value == "SMTP" {
if value == string(SMTP) {
newProto = SMTP
} else if value == "ESMTP" {
} else if value == string(ESMTP) {
newProto = ESMTP
}
continue
Expand Down

0 comments on commit 213ad20

Please sign in to comment.