Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/auth/manager/publicshares/publicshares.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type config struct {
StoreTable string `mapstructure:"store_table"`
StoreUsername string `mapstructure:"store_username"`
StorePassword string `mapstructure:"store_password"`
StoreEnableTLS bool `mapstructure:"store_enable_tls"`
StoreTLSInsecure bool `mapstructure:"store_tls_insecure"`
StoreTLSRootCACert string `mapstructure:"store_tls_root_ca_certificate"`
}

func parseConfig(m map[string]interface{}) (*config, error) {
Expand All @@ -86,6 +89,7 @@ func New(m map[string]interface{}) (auth.Manager, error) {
microstore.Database(mgr.c.StoreDatabase),
microstore.Table(mgr.c.StoreTable),
store.Authentication(mgr.c.StoreUsername, mgr.c.StorePassword),
store.TLS(mgr.c.StoreEnableTLS, mgr.c.StoreTLSInsecure, mgr.c.StoreTLSRootCACert),
)
mgr.bfp = NewBruteForceProtection(revaStore, mgr.c.BruteForceTimeGap, mgr.c.BruteForceMaxAttempts)
return mgr, nil
Expand Down
17 changes: 14 additions & 3 deletions pkg/storage/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package cache
import (
"context"
"fmt"
"strconv"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -51,6 +52,9 @@ type Config struct {
DisablePersistence bool `mapstructure:"cache_disable_persistence"`
AuthUsername string `mapstructure:"cache_auth_username"`
AuthPassword string `mapstructure:"cache_auth_password"`
EnableTLS bool `mapstructure:"cache_enable_tls"`
TLSInsecure bool `mapstructure:"cache_tls_insecure"`
TLSRootCACert string `mapstructure:"cache_tls_root_ca_certificate"`
}

// Cache handles key value operations on caches
Expand Down Expand Up @@ -86,13 +90,19 @@ type FileMetadataCache interface {
RemoveMetadata(path string) error
}

func cacheKey(cfg Config) string {
return strings.Join(append(append([]string{cfg.Store}, cfg.Nodes...),
cfg.Database, cfg.Table,
strconv.FormatBool(cfg.EnableTLS)+":"+strconv.FormatBool(cfg.TLSInsecure)+":"+cfg.TLSRootCACert), ":")
}

// GetStatCache will return an existing StatCache for the given store, nodes, database and table
// If it does not exist yet it will be created, different TTLs are ignored
func GetStatCache(cfg Config) StatCache {
mutex.Lock()
defer mutex.Unlock()

key := strings.Join(append(append([]string{cfg.Store}, cfg.Nodes...), cfg.Database, cfg.Table), ":")
key := cacheKey(cfg)
if statCaches[key] == nil {
statCaches[key] = NewStatCache(cfg)
}
Expand All @@ -105,7 +115,7 @@ func GetProviderCache(cfg Config) ProviderCache {
mutex.Lock()
defer mutex.Unlock()

key := strings.Join(append(append([]string{cfg.Store}, cfg.Nodes...), cfg.Database, cfg.Table), ":")
key := cacheKey(cfg)
if providerCaches[key] == nil {
providerCaches[key] = NewProviderCache(cfg)
}
Expand All @@ -118,7 +128,7 @@ func GetFileMetadataCache(cfg Config) FileMetadataCache {
mutex.Lock()
defer mutex.Unlock()

key := strings.Join(append(append([]string{cfg.Store}, cfg.Nodes...), cfg.Database, cfg.Table), ":")
key := cacheKey(cfg)
if fileMetadataCaches[key] == nil {
fileMetadataCaches[key] = NewFileMetadataCache(cfg)
}
Expand Down Expand Up @@ -202,5 +212,6 @@ func getStore(cfg Config) microstore.Store {
store.Size(cfg.Size),
store.DisablePersistence(cfg.DisablePersistence),
store.Authentication(cfg.AuthUsername, cfg.AuthPassword),
store.TLS(cfg.EnableTLS, cfg.TLSInsecure, cfg.TLSRootCACert),
)
}
1 change: 1 addition & 0 deletions pkg/storage/fs/posix/lookup/store_idcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func NewStoreIDCache(o *options.Options) *StoreIDCache {
microstore.Table(o.IDCache.Table),
store.DisablePersistence(o.IDCache.DisablePersistence),
store.Authentication(o.IDCache.AuthUsername, o.IDCache.AuthPassword),
store.TLS(o.IDCache.EnableTLS, o.IDCache.TLSInsecure, o.IDCache.TLSRootCACert),
),
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/storage/fs/posix/posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func New(m map[string]interface{}, stream events.Stream, log *zerolog.Logger) (s
microstore.Table(o.IDCache.Table),
store.DisablePersistence(o.IDCache.DisablePersistence),
store.Authentication(o.IDCache.AuthUsername, o.IDCache.AuthPassword),
store.TLS(o.IDCache.EnableTLS, o.IDCache.TLSInsecure, o.IDCache.TLSRootCACert),
), log)
if err != nil {
return nil, err
Expand Down
1 change: 1 addition & 0 deletions pkg/storage/utils/decomposedfs/decomposedfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ func NewDefault(m map[string]interface{}, bs tree.Blobstore, es events.Stream, l
microstore.Table(o.IDCache.Table),
store.DisablePersistence(o.IDCache.DisablePersistence),
store.Authentication(o.IDCache.AuthUsername, o.IDCache.AuthPassword),
store.TLS(o.IDCache.EnableTLS, o.IDCache.TLSInsecure, o.IDCache.TLSRootCACert),
), log)

permissionsSelector, err := pool.PermissionsSelector(o.PermissionsSVC, pool.WithTLSMode(o.PermTLSMode))
Expand Down
20 changes: 20 additions & 0 deletions pkg/store/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"go-micro.dev/v4/store"
)

type tlsContextKey struct{}

type typeContextKey struct{}

// Store determines the implementation:
Expand Down Expand Up @@ -103,3 +105,21 @@ func Authentication(username, password string) store.Option {
o.Context = context.WithValue(o.Context, authenticationContextKey{}, []string{username, password})
}
}

type tlsOptions struct {
enable bool
insecure bool
rootCACert string
}

// TLS configures TLS for the nats-js and nats-js-kv store backends.
// enable activates TLS; insecure skips certificate verification (for self-signed certs);
// rootCACert is an optional path to a PEM file used to validate the server certificate.
func TLS(enable bool, insecure bool, rootCACert string) store.Option {
return func(o *store.Options) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, tlsContextKey{}, tlsOptions{enable, insecure, rootCACert})
}
}
35 changes: 35 additions & 0 deletions pkg/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ package store

import (
"context"
"crypto/tls"
"crypto/x509"
"os"
"strings"
"time"

Expand Down Expand Up @@ -66,6 +69,12 @@ func Create(opts ...microstore.Option) microstore.Store {

storeType, _ := options.Context.Value(typeContextKey{}).(string)

if tlsOpts, ok := options.Context.Value(tlsContextKey{}).(tlsOptions); ok && tlsOpts.enable &&
storeType != TypeNatsJS && storeType != TypeNatsJSKV {
logger.Logf(logger.WarnLevel,
"reva-store: TLS requested but store type %q does not support TLS — settings ignored", storeType)
}

switch storeType {
case TypeNoop:
return microstore.NewNoopStore(opts...)
Expand Down Expand Up @@ -174,6 +183,10 @@ func defaultNatsOptions(options *microstore.Options) nats.Options {
natsOptions.User = auth[0]
natsOptions.Password = auth[1]
}
if tlsOpts, ok := options.Context.Value(tlsContextKey{}).(tlsOptions); ok && tlsOpts.enable {
natsOptions.TLSConfig = BuildNatsTLSConfig(tlsOpts.insecure, tlsOpts.rootCACert)
natsOptions.Secure = true
}
natsOptions.DisconnectedErrCB = func(_ *nats.Conn, err error) {
logger.Logf(logger.WarnLevel, "reva-store: nats connection disconnected: %v", err)
}
Expand All @@ -185,3 +198,25 @@ func defaultNatsOptions(options *microstore.Options) nats.Options {
}
return natsOptions
}

// BuildNatsTLSConfig constructs a tls.Config for NATS client connections.
// insecure skips certificate verification; rootCACert is an optional path to a
// PEM file whose CA is used to validate the server certificate.
func BuildNatsTLSConfig(insecure bool, rootCACert string) *tls.Config {
tlsConf := &tls.Config{MinVersion: tls.VersionTLS12, InsecureSkipVerify: insecure} //nolint:gosec
if rootCACert != "" {
b, err := os.ReadFile(rootCACert)
if err != nil {
logger.Logf(logger.WarnLevel, "reva-store: failed to read TLS root CA cert %q: %v", rootCACert, err)
} else {
pool := x509.NewCertPool()
if pool.AppendCertsFromPEM(b) {
tlsConf.RootCAs = pool
tlsConf.InsecureSkipVerify = false
} else {
logger.Logf(logger.WarnLevel, "reva-store: no valid PEM certificates found in %q", rootCACert)
}
}
}
return tlsConf
}