mirror of
https://github.com/mochi-mqtt/server.git
synced 2025-09-27 04:26:23 +08:00

* Begin adding new slog calls * Fixed unit tests * Add leveler example * Add debug log level to Redis example * Change location of server.Close() and add logs to example/hooks * Begin removing references to zerolog * Removed final references to zerolog * Change where server.Close() occurs in main * Change to 1.21 to remove x dependency * Add slog * Update references to 1.21 * Begin change of LogAttrs to standard logging interface * Change the rest of LogAttrs to default * Fix bad log * Update badger.go Changing "data" to "key" or "id" here might be more appropriate. * Update badger.go Changing "data" to "key" or "id" here might be more appropriate. * Update server.go Not checking if err is equal to nil * Update server.go printing information for ID or error is missing. * Change references of err.Error() to err in slog * Remove missed removal of Error() references for logging --------- Co-authored-by: Derek Duncan <dduncan@atlassian.com> Co-authored-by: Derek Duncan <derekduncan@gmail.com> Co-authored-by: JB <28275108+mochi-co@users.noreply.github.com> Co-authored-by: werbenhu <werben@qq.com>
104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
// SPDX-License-Identifier: MIT
|
|
// SPDX-FileCopyrightText: 2022 mochi-mqtt, mochi-co
|
|
// SPDX-FileContributor: mochi-co
|
|
|
|
package auth
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
mqtt "github.com/mochi-mqtt/server/v2"
|
|
"github.com/mochi-mqtt/server/v2/packets"
|
|
)
|
|
|
|
// Options contains the configuration/rules data for the auth ledger.
|
|
type Options struct {
|
|
Data []byte
|
|
Ledger *Ledger
|
|
}
|
|
|
|
// Hook is an authentication hook which implements an auth ledger.
|
|
type Hook struct {
|
|
mqtt.HookBase
|
|
config *Options
|
|
ledger *Ledger
|
|
}
|
|
|
|
// ID returns the ID of the hook.
|
|
func (h *Hook) ID() string {
|
|
return "auth-ledger"
|
|
}
|
|
|
|
// Provides indicates which hook methods this hook provides.
|
|
func (h *Hook) Provides(b byte) bool {
|
|
return bytes.Contains([]byte{
|
|
mqtt.OnConnectAuthenticate,
|
|
mqtt.OnACLCheck,
|
|
}, []byte{b})
|
|
}
|
|
|
|
// Init configures the hook with the auth ledger to be used for checking.
|
|
func (h *Hook) Init(config any) error {
|
|
if _, ok := config.(*Options); !ok && config != nil {
|
|
return mqtt.ErrInvalidConfigType
|
|
}
|
|
|
|
if config == nil {
|
|
config = new(Options)
|
|
}
|
|
|
|
h.config = config.(*Options)
|
|
|
|
var err error
|
|
if h.config.Ledger != nil {
|
|
h.ledger = h.config.Ledger
|
|
} else if len(h.config.Data) > 0 {
|
|
h.ledger = new(Ledger)
|
|
err = h.ledger.Unmarshal(h.config.Data)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if h.ledger == nil {
|
|
h.ledger = &Ledger{
|
|
Auth: AuthRules{},
|
|
ACL: ACLRules{},
|
|
}
|
|
}
|
|
|
|
h.Log.Info("loaded auth rules",
|
|
"authentication", len(h.ledger.Auth),
|
|
"acl", len(h.ledger.ACL))
|
|
|
|
return nil
|
|
}
|
|
|
|
// OnConnectAuthenticate returns true if the connecting client has rules which provide access
|
|
// in the auth ledger.
|
|
func (h *Hook) OnConnectAuthenticate(cl *mqtt.Client, pk packets.Packet) bool {
|
|
if _, ok := h.ledger.AuthOk(cl, pk); ok {
|
|
return true
|
|
}
|
|
|
|
h.Log.Info("client failed authentication check",
|
|
"username", string(pk.Connect.Username),
|
|
"remote", cl.Net.Remote)
|
|
return false
|
|
}
|
|
|
|
// OnACLCheck returns true if the connecting client has matching read or write access to subscribe
|
|
// or publish to a given topic.
|
|
func (h *Hook) OnACLCheck(cl *mqtt.Client, topic string, write bool) bool {
|
|
if _, ok := h.ledger.ACLOk(cl, topic, write); ok {
|
|
return true
|
|
}
|
|
|
|
h.Log.Debug("client failed allowed ACL check",
|
|
"client", cl.ID,
|
|
"username", string(cl.Properties.Username),
|
|
"topic", topic)
|
|
|
|
return false
|
|
}
|