Wrap storage calls with encoding checks (#5819)
* Add encoding backend * More work on encoding checks * Update error message * Update physical/encoding.go * Disable key checks if configured
This commit is contained in:
parent
c16f7485e7
commit
33776b89c2
|
@ -552,6 +552,7 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
DisableIndexing: config.DisableIndexing,
|
||||
AllLoggers: allLoggers,
|
||||
BuiltinRegistry: builtinplugins.Registry,
|
||||
DisableKeyEncodingChecks: config.DisablePrintableCheck,
|
||||
}
|
||||
if c.flagDev {
|
||||
coreConfig.DevToken = c.flagDevRootTokenID
|
||||
|
|
|
@ -639,7 +639,10 @@ func TestHandler_nonPrintableChars(t *testing.T) {
|
|||
}
|
||||
|
||||
func testNonPrintable(t *testing.T, disable bool) {
|
||||
core, _, token := vault.TestCoreUnsealed(t)
|
||||
core, _, token := vault.TestCoreUnsealedWithConfig(t, &vault.CoreConfig{
|
||||
Seal: vault.NewTestSeal(t, nil),
|
||||
DisableKeyEncodingChecks: disable,
|
||||
})
|
||||
ln, addr := TestListener(t)
|
||||
props := &vault.HandlerProperties{
|
||||
Core: core,
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
package physical
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var ErrNonUTF8 = errors.New("key contains invalid UTF-8 characters")
|
||||
var ErrNonPrintable = errors.New("key contains non-printable characters")
|
||||
|
||||
// StorageEncoding is used to add errors into underlying physical requests
|
||||
type StorageEncoding struct {
|
||||
Backend
|
||||
}
|
||||
|
||||
// TransactionalStorageEncoding is the transactional version of the error
|
||||
// injector
|
||||
type TransactionalStorageEncoding struct {
|
||||
*StorageEncoding
|
||||
Transactional
|
||||
}
|
||||
|
||||
// Verify StorageEncoding satisfies the correct interfaces
|
||||
var _ Backend = (*StorageEncoding)(nil)
|
||||
var _ Transactional = (*TransactionalStorageEncoding)(nil)
|
||||
|
||||
// NewStorageEncoding returns a wrapped physical backend and verifies the key
|
||||
// encoding
|
||||
func NewStorageEncoding(b Backend) Backend {
|
||||
enc := &StorageEncoding{
|
||||
Backend: b,
|
||||
}
|
||||
|
||||
if bTxn, ok := b.(Transactional); ok {
|
||||
return TransactionalStorageEncoding{
|
||||
StorageEncoding: enc,
|
||||
Transactional: bTxn,
|
||||
}
|
||||
}
|
||||
|
||||
return enc
|
||||
}
|
||||
|
||||
func (e *StorageEncoding) containsNonPrintableChars(key string) bool {
|
||||
idx := strings.IndexFunc(key, func(c rune) bool {
|
||||
return !unicode.IsPrint(c)
|
||||
})
|
||||
|
||||
return idx != -1
|
||||
}
|
||||
|
||||
func (e *StorageEncoding) Put(ctx context.Context, entry *Entry) error {
|
||||
if !utf8.ValidString(entry.Key) {
|
||||
return ErrNonUTF8
|
||||
}
|
||||
|
||||
if e.containsNonPrintableChars(entry.Key) {
|
||||
return ErrNonPrintable
|
||||
}
|
||||
|
||||
return e.Backend.Put(ctx, entry)
|
||||
}
|
||||
|
||||
func (e *StorageEncoding) Delete(ctx context.Context, key string) error {
|
||||
if !utf8.ValidString(key) {
|
||||
return ErrNonUTF8
|
||||
}
|
||||
|
||||
if e.containsNonPrintableChars(key) {
|
||||
return ErrNonPrintable
|
||||
}
|
||||
|
||||
return e.Backend.Delete(ctx, key)
|
||||
}
|
||||
|
||||
func (e *TransactionalStorageEncoding) Transaction(ctx context.Context, txns []*TxnEntry) error {
|
||||
for _, txn := range txns {
|
||||
if !utf8.ValidString(txn.Entry.Key) {
|
||||
return ErrNonUTF8
|
||||
}
|
||||
|
||||
if e.containsNonPrintableChars(txn.Entry.Key) {
|
||||
return ErrNonPrintable
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return e.Transactional.Transaction(ctx, txns)
|
||||
}
|
||||
|
||||
func (e *StorageEncoding) Purge(ctx context.Context) {
|
||||
if purgeable, ok := e.Backend.(ToggleablePurgemonster); ok {
|
||||
purgeable.Purge(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *StorageEncoding) SetEnabled(enabled bool) {
|
||||
if purgeable, ok := e.Backend.(ToggleablePurgemonster); ok {
|
||||
purgeable.SetEnabled(enabled)
|
||||
}
|
||||
}
|
|
@ -466,6 +466,7 @@ type CoreConfig struct {
|
|||
|
||||
DisablePerformanceStandby bool
|
||||
DisableIndexing bool
|
||||
DisableKeyEncodingChecks bool
|
||||
|
||||
AllLoggers []log.Logger
|
||||
}
|
||||
|
|
|
@ -31,6 +31,10 @@ func coreInit(c *Core, conf *CoreConfig) error {
|
|||
}
|
||||
c.physicalCache = c.physical.(physical.ToggleablePurgemonster)
|
||||
|
||||
// Wrap in encoding checks
|
||||
if !conf.DisableKeyEncodingChecks {
|
||||
c.physical = physical.NewStorageEncoding(c.physical)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ func TestCoreWithSealAndUI(t testing.T, opts *CoreConfig) *Core {
|
|||
conf.EnableRaw = opts.EnableRaw
|
||||
conf.Seal = opts.Seal
|
||||
conf.LicensingConfig = opts.LicensingConfig
|
||||
conf.DisableKeyEncodingChecks = opts.DisableKeyEncodingChecks
|
||||
|
||||
c, err := NewCore(conf)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue