mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
trace: Use request tracing in auth and domaininfo
This patch adds tracing for the auth and domaininfo modules. In the latter, we replace the long-running event with the short-term request tracing, which is more practical and useful. There are no logic changes, it only adds tracing instrumentation to help troubleshooting.
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"blitiri.com.ar/go/chasquid/internal/normalize"
|
"blitiri.com.ar/go/chasquid/internal/normalize"
|
||||||
|
"blitiri.com.ar/go/chasquid/internal/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backend is the common interface for all authentication backends.
|
// Backend is the common interface for all authentication backends.
|
||||||
@@ -65,6 +66,9 @@ func (a *Authenticator) Register(domain string, be Backend) {
|
|||||||
|
|
||||||
// Authenticate the user@domain with the given password.
|
// Authenticate the user@domain with the given password.
|
||||||
func (a *Authenticator) Authenticate(user, domain, password string) (bool, error) {
|
func (a *Authenticator) Authenticate(user, domain, password string) (bool, error) {
|
||||||
|
tr := trace.New("Auth.Authenticate", user+"@"+domain)
|
||||||
|
defer tr.Finish()
|
||||||
|
|
||||||
// Make sure the call takes a.AuthDuration + 0-20% regardless of the
|
// Make sure the call takes a.AuthDuration + 0-20% regardless of the
|
||||||
// outcome, to prevent basic timing attacks.
|
// outcome, to prevent basic timing attacks.
|
||||||
defer func(start time.Time) {
|
defer func(start time.Time) {
|
||||||
@@ -79,31 +83,42 @@ func (a *Authenticator) Authenticate(user, domain, password string) (bool, error
|
|||||||
|
|
||||||
if be, ok := a.backends[domain]; ok {
|
if be, ok := a.backends[domain]; ok {
|
||||||
ok, err := be.Authenticate(user, password)
|
ok, err := be.Authenticate(user, password)
|
||||||
|
tr.Debugf("Backend: %v %v", ok, err)
|
||||||
if ok || err != nil {
|
if ok || err != nil {
|
||||||
return ok, err
|
return ok, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Fallback != nil {
|
if a.Fallback != nil {
|
||||||
return a.Fallback.Authenticate(user+"@"+domain, password)
|
ok, err := a.Fallback.Authenticate(user+"@"+domain, password)
|
||||||
|
tr.Debugf("Fallback: %v %v", ok, err)
|
||||||
|
return ok, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr.Debugf("Rejected by default")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exists checks that user@domain exists.
|
// Exists checks that user@domain exists.
|
||||||
func (a *Authenticator) Exists(user, domain string) (bool, error) {
|
func (a *Authenticator) Exists(user, domain string) (bool, error) {
|
||||||
|
tr := trace.New("Auth.Exists", user+"@"+domain)
|
||||||
|
defer tr.Finish()
|
||||||
|
|
||||||
if be, ok := a.backends[domain]; ok {
|
if be, ok := a.backends[domain]; ok {
|
||||||
ok, err := be.Exists(user)
|
ok, err := be.Exists(user)
|
||||||
|
tr.Debugf("Backend: %v %v", ok, err)
|
||||||
if ok || err != nil {
|
if ok || err != nil {
|
||||||
return ok, err
|
return ok, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Fallback != nil {
|
if a.Fallback != nil {
|
||||||
return a.Fallback.Exists(user + "@" + domain)
|
ok, err := a.Fallback.Exists(user + "@" + domain)
|
||||||
|
tr.Debugf("Fallback: %v %v", ok, err)
|
||||||
|
return ok, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr.Debugf("Rejected by default")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,16 +127,22 @@ func (a *Authenticator) Reload() error {
|
|||||||
msgs := []string{}
|
msgs := []string{}
|
||||||
|
|
||||||
for domain, be := range a.backends {
|
for domain, be := range a.backends {
|
||||||
|
tr := trace.New("Auth.Reload", domain)
|
||||||
err := be.Reload()
|
err := be.Reload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tr.Error(err)
|
||||||
msgs = append(msgs, fmt.Sprintf("%q: %v", domain, err))
|
msgs = append(msgs, fmt.Sprintf("%q: %v", domain, err))
|
||||||
}
|
}
|
||||||
|
tr.Finish()
|
||||||
}
|
}
|
||||||
if a.Fallback != nil {
|
if a.Fallback != nil {
|
||||||
|
tr := trace.New("Auth.Reload", "<fallback>")
|
||||||
err := a.Fallback.Reload()
|
err := a.Fallback.Reload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tr.Error(err)
|
||||||
msgs = append(msgs, fmt.Sprintf("<fallback>: %v", err))
|
msgs = append(msgs, fmt.Sprintf("<fallback>: %v", err))
|
||||||
}
|
}
|
||||||
|
tr.Finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(msgs) > 0 {
|
if len(msgs) > 0 {
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ type DB struct {
|
|||||||
|
|
||||||
info map[string]*Domain
|
info map[string]*Domain
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
ev *trace.EventLog
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New opens a domain information database on the given dir, creating it if
|
// New opens a domain information database on the given dir, creating it if
|
||||||
@@ -36,7 +34,6 @@ func New(dir string) (*DB, error) {
|
|||||||
store: st,
|
store: st,
|
||||||
info: map[string]*Domain{},
|
info: map[string]*Domain{},
|
||||||
}
|
}
|
||||||
l.ev = trace.NewEventLog("DomainInfo", dir)
|
|
||||||
|
|
||||||
err = l.Reload()
|
err = l.Reload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -48,6 +45,9 @@ func New(dir string) (*DB, error) {
|
|||||||
|
|
||||||
// Reload the database from disk.
|
// Reload the database from disk.
|
||||||
func (db *DB) Reload() error {
|
func (db *DB) Reload() error {
|
||||||
|
tr := trace.New("DomainInfo.Reload", "reload")
|
||||||
|
defer tr.Finish()
|
||||||
|
|
||||||
db.Lock()
|
db.Lock()
|
||||||
defer db.Unlock()
|
defer db.Unlock()
|
||||||
|
|
||||||
@@ -56,6 +56,7 @@ func (db *DB) Reload() error {
|
|||||||
|
|
||||||
ids, err := db.store.ListIDs()
|
ids, err := db.store.ListIDs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tr.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,28 +64,36 @@ func (db *DB) Reload() error {
|
|||||||
d := &Domain{}
|
d := &Domain{}
|
||||||
_, err := db.store.Get(id, d)
|
_, err := db.store.Get(id, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tr.Errorf("id %q: %v", id, err)
|
||||||
return fmt.Errorf("error loading %q: %v", id, err)
|
return fmt.Errorf("error loading %q: %v", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.info[d.Name] = d
|
db.info[d.Name] = d
|
||||||
}
|
}
|
||||||
|
|
||||||
db.ev.Debugf("loaded %d domains", len(ids))
|
tr.Debugf("loaded %d domains", len(ids))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) write(d *Domain) {
|
func (db *DB) write(d *Domain) {
|
||||||
|
tr := trace.New("DomainInfo.write", d.Name)
|
||||||
|
defer tr.Finish()
|
||||||
|
|
||||||
err := db.store.Put(d.Name, d)
|
err := db.store.Put(d.Name, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
db.ev.Errorf("%s error saving: %v", d.Name, err)
|
tr.Error(err)
|
||||||
} else {
|
} else {
|
||||||
db.ev.Debugf("%s saved", d.Name)
|
tr.Debugf("saved")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncomingSecLevel checks an incoming security level for the domain.
|
// IncomingSecLevel checks an incoming security level for the domain.
|
||||||
// Returns true if allowed, false otherwise.
|
// Returns true if allowed, false otherwise.
|
||||||
func (db *DB) IncomingSecLevel(domain string, level SecLevel) bool {
|
func (db *DB) IncomingSecLevel(domain string, level SecLevel) bool {
|
||||||
|
tr := trace.New("DomainInfo.Incoming", domain)
|
||||||
|
defer tr.Finish()
|
||||||
|
tr.Debugf("incoming at level %s", level)
|
||||||
|
|
||||||
db.Lock()
|
db.Lock()
|
||||||
defer db.Unlock()
|
defer db.Unlock()
|
||||||
|
|
||||||
@@ -96,15 +105,15 @@ func (db *DB) IncomingSecLevel(domain string, level SecLevel) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if level < d.IncomingSecLevel {
|
if level < d.IncomingSecLevel {
|
||||||
db.ev.Errorf("%s incoming denied: %s < %s",
|
tr.Errorf("%s incoming denied: %s < %s",
|
||||||
d.Name, level, d.IncomingSecLevel)
|
d.Name, level, d.IncomingSecLevel)
|
||||||
return false
|
return false
|
||||||
} else if level == d.IncomingSecLevel {
|
} else if level == d.IncomingSecLevel {
|
||||||
db.ev.Debugf("%s incoming allowed: %s == %s",
|
tr.Debugf("%s incoming allowed: %s == %s",
|
||||||
d.Name, level, d.IncomingSecLevel)
|
d.Name, level, d.IncomingSecLevel)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
db.ev.Printf("%s incoming level raised: %s > %s",
|
tr.Printf("%s incoming level raised: %s > %s",
|
||||||
d.Name, level, d.IncomingSecLevel)
|
d.Name, level, d.IncomingSecLevel)
|
||||||
d.IncomingSecLevel = level
|
d.IncomingSecLevel = level
|
||||||
if exists {
|
if exists {
|
||||||
@@ -117,6 +126,10 @@ func (db *DB) IncomingSecLevel(domain string, level SecLevel) bool {
|
|||||||
// OutgoingSecLevel checks an incoming security level for the domain.
|
// OutgoingSecLevel checks an incoming security level for the domain.
|
||||||
// Returns true if allowed, false otherwise.
|
// Returns true if allowed, false otherwise.
|
||||||
func (db *DB) OutgoingSecLevel(domain string, level SecLevel) bool {
|
func (db *DB) OutgoingSecLevel(domain string, level SecLevel) bool {
|
||||||
|
tr := trace.New("DomainInfo.Outgoing", domain)
|
||||||
|
defer tr.Finish()
|
||||||
|
tr.Debugf("outgoing at level %s", level)
|
||||||
|
|
||||||
db.Lock()
|
db.Lock()
|
||||||
defer db.Unlock()
|
defer db.Unlock()
|
||||||
|
|
||||||
@@ -128,15 +141,15 @@ func (db *DB) OutgoingSecLevel(domain string, level SecLevel) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if level < d.OutgoingSecLevel {
|
if level < d.OutgoingSecLevel {
|
||||||
db.ev.Errorf("%s outgoing denied: %s < %s",
|
tr.Errorf("%s outgoing denied: %s < %s",
|
||||||
d.Name, level, d.OutgoingSecLevel)
|
d.Name, level, d.OutgoingSecLevel)
|
||||||
return false
|
return false
|
||||||
} else if level == d.OutgoingSecLevel {
|
} else if level == d.OutgoingSecLevel {
|
||||||
db.ev.Debugf("%s outgoing allowed: %s == %s",
|
tr.Debugf("%s outgoing allowed: %s == %s",
|
||||||
d.Name, level, d.OutgoingSecLevel)
|
d.Name, level, d.OutgoingSecLevel)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
db.ev.Printf("%s outgoing level raised: %s > %s",
|
tr.Printf("%s outgoing level raised: %s > %s",
|
||||||
d.Name, level, d.OutgoingSecLevel)
|
d.Name, level, d.OutgoingSecLevel)
|
||||||
d.OutgoingSecLevel = level
|
d.OutgoingSecLevel = level
|
||||||
if exists {
|
if exists {
|
||||||
|
|||||||
Reference in New Issue
Block a user