From 00cd1c59fc3a9fb4be3ad2dd5b789689ee247bc8 Mon Sep 17 00:00:00 2001 From: Robert Volkmann <20912167+robertvolkmann@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:55:27 +0100 Subject: [PATCH] Support authentication against Redis (#137) --- cmd/internal/switcher/sonic/db/appldb.go | 6 +- cmd/internal/switcher/sonic/db/asicdb.go | 4 +- cmd/internal/switcher/sonic/db/client.go | 7 +- cmd/internal/switcher/sonic/db/configdb.go | 6 +- cmd/internal/switcher/sonic/db/countersdb.go | 6 +- cmd/internal/switcher/sonic/db/db.go | 69 ++++++++++++++++++-- cmd/internal/switcher/sonic/sonic.go | 5 +- 7 files changed, 81 insertions(+), 22 deletions(-) diff --git a/cmd/internal/switcher/sonic/db/appldb.go b/cmd/internal/switcher/sonic/db/appldb.go index e8d2ca2b..e16c3478 100644 --- a/cmd/internal/switcher/sonic/db/appldb.go +++ b/cmd/internal/switcher/sonic/db/appldb.go @@ -2,15 +2,17 @@ package db import ( "context" + + "github.com/redis/go-redis/v9" ) type ApplDB struct { c *Client } -func newApplDB(addr string, id int, sep string) *ApplDB { +func newApplDB(rdb *redis.Client, sep string) *ApplDB { return &ApplDB{ - c: NewClient(addr, id, sep), + c: NewClient(rdb, sep), } } diff --git a/cmd/internal/switcher/sonic/db/asicdb.go b/cmd/internal/switcher/sonic/db/asicdb.go index 398a5d34..809d6172 100644 --- a/cmd/internal/switcher/sonic/db/asicdb.go +++ b/cmd/internal/switcher/sonic/db/asicdb.go @@ -13,9 +13,9 @@ type AsicDB struct { type OID string -func newAsicDB(addr string, id int, sep string) *AsicDB { +func newAsicDB(rdb *redis.Client, sep string) *AsicDB { return &AsicDB{ - c: NewClient(addr, id, sep), + c: NewClient(rdb, sep), } } diff --git a/cmd/internal/switcher/sonic/db/client.go b/cmd/internal/switcher/sonic/db/client.go index 619349ef..e25e8d15 100644 --- a/cmd/internal/switcher/sonic/db/client.go +++ b/cmd/internal/switcher/sonic/db/client.go @@ -21,12 +21,7 @@ type Client struct { sep string } -func NewClient(addr string, id int, sep string) *Client { - rdb := redis.NewClient(&redis.Options{ - Addr: addr, - DB: id, - PoolSize: 1, - }) +func NewClient(rdb *redis.Client, sep string) *Client { return &Client{ rdb: rdb, sep: sep, diff --git a/cmd/internal/switcher/sonic/db/configdb.go b/cmd/internal/switcher/sonic/db/configdb.go index 3f7f8754..5549f102 100644 --- a/cmd/internal/switcher/sonic/db/configdb.go +++ b/cmd/internal/switcher/sonic/db/configdb.go @@ -3,6 +3,8 @@ package db import ( "context" "fmt" + + "github.com/redis/go-redis/v9" ) const ( @@ -29,9 +31,9 @@ type Port struct { Mtu string } -func newConfigDB(addr string, id int, sep string) *ConfigDB { +func newConfigDB(rdb *redis.Client, sep string) *ConfigDB { return &ConfigDB{ - c: NewClient(addr, id, sep), + c: NewClient(rdb, sep), } } diff --git a/cmd/internal/switcher/sonic/db/countersdb.go b/cmd/internal/switcher/sonic/db/countersdb.go index c0b2d99a..e79356ff 100644 --- a/cmd/internal/switcher/sonic/db/countersdb.go +++ b/cmd/internal/switcher/sonic/db/countersdb.go @@ -2,15 +2,17 @@ package db import ( "context" + + "github.com/redis/go-redis/v9" ) type CountersDB struct { c *Client } -func newCountersDB(addr string, id int, sep string) *CountersDB { +func newCountersDB(rdb *redis.Client, sep string) *CountersDB { return &CountersDB{ - c: NewClient(addr, id, sep), + c: NewClient(rdb, sep), } } diff --git a/cmd/internal/switcher/sonic/db/db.go b/cmd/internal/switcher/sonic/db/db.go index a3177c13..ec0b2062 100644 --- a/cmd/internal/switcher/sonic/db/db.go +++ b/cmd/internal/switcher/sonic/db/db.go @@ -1,5 +1,12 @@ package db +import ( + "fmt" + "os" + + "github.com/redis/go-redis/v9" +) + type Config struct { Databases map[string]database `json:"DATABASES"` Instances map[string]instance `json:"INSTANCES"` @@ -12,7 +19,8 @@ type database struct { } type instance struct { - Addr string `json:"unix_socket_path"` + Addr string `json:"unix_socket_path"` + PasswordPath string `json:"password_path"` } type DB struct { @@ -22,16 +30,63 @@ type DB struct { Counters *CountersDB } -func New(cfg *Config) *DB { +func New(cfg *Config) (*DB, error) { applDB := cfg.Databases["APPL_DB"] asicDB := cfg.Databases["ASIC_DB"] configDB := cfg.Databases["CONFIG_DB"] countersDB := cfg.Databases["COUNTERS_DB"] - return &DB{ - Appl: newApplDB(cfg.Instances[applDB.Instance].Addr, applDB.Id, applDB.Separator), - Asic: newAsicDB(cfg.Instances[asicDB.Instance].Addr, asicDB.Id, asicDB.Separator), - Config: newConfigDB(cfg.Instances[configDB.Instance].Addr, configDB.Id, configDB.Separator), - Counters: newCountersDB(cfg.Instances[countersDB.Instance].Addr, countersDB.Id, countersDB.Separator), + applClient, err := newRedisClient(cfg.Instances[applDB.Instance], applDB.Id) + if err != nil { + return nil, fmt.Errorf("could not create client for APPL_DB: %w", err) + } + + asicClient, err := newRedisClient(cfg.Instances[asicDB.Instance], asicDB.Id) + if err != nil { + return nil, fmt.Errorf("could not create client for ASIC_DB: %w", err) + } + + configClient, err := newRedisClient(cfg.Instances[configDB.Instance], configDB.Id) + if err != nil { + return nil, fmt.Errorf("could not create client for CONFIG_DB: %w", err) + } + + countersClient, err := newRedisClient(cfg.Instances[countersDB.Instance], countersDB.Id) + if err != nil { + return nil, fmt.Errorf("could not create client for COUNTERS_DB: %w", err) + } + + db := &DB{ + Appl: newApplDB(applClient, applDB.Separator), + Asic: newAsicDB(asicClient, asicDB.Separator), + Config: newConfigDB(configClient, configDB.Separator), + Counters: newCountersDB(countersClient, countersDB.Separator), + } + return db, nil +} + +func newRedisClient(redisInstance instance, redisDatabase int) (*redis.Client, error) { + if redisInstance.PasswordPath != "" { + return newRedisClientWithAuth(redisInstance, redisDatabase) + } + rdb := redis.NewClient(&redis.Options{ + Addr: redisInstance.Addr, + DB: redisDatabase, + PoolSize: 1, + }) + return rdb, nil +} + +func newRedisClientWithAuth(redisInstance instance, redisDatabase int) (*redis.Client, error) { + passwd, err := os.ReadFile(redisInstance.PasswordPath) + if err != nil { + return nil, fmt.Errorf("could not read password from %s: %w", redisInstance.PasswordPath, err) } + rdb := redis.NewClient(&redis.Options{ + Addr: redisInstance.Addr, + DB: redisDatabase, + PoolSize: 1, + Password: string(passwd), + }) + return rdb, nil } diff --git a/cmd/internal/switcher/sonic/sonic.go b/cmd/internal/switcher/sonic/sonic.go index c2c4c532..151ffdb2 100644 --- a/cmd/internal/switcher/sonic/sonic.go +++ b/cmd/internal/switcher/sonic/sonic.go @@ -44,7 +44,10 @@ func New(log *slog.Logger, frrTplFile string) (*Sonic, error) { if err != nil { return nil, fmt.Errorf("failed to load database config for SONiC: %w", err) } - sonicDb := db.New(cfg) + sonicDb, err := db.New(cfg) + if err != nil { + return nil, fmt.Errorf("failed to connect to SONiC databases: %w", err) + } return &Sonic{ db: sonicDb,