mirror of
https://github.com/gravitational/teleport
synced 2024-10-22 02:03:24 +00:00
Enforce valid UTF8 keys on all backends.
The use of non-UTF8 keys with the DynamoDB back-end causes a failure deep within the AWS request deserialization code, presenting a non-obvious failure to the user. This change adds validation to all backends that requires all keys are valid UTF8 strings. It also adds a warning to the Backend interface declaration that the keys may be constrained to valid UTF8. Other changes include: * Updating the `Backend` conformance test suite to not present binary keys to the various backend implementations. * Adding a `region` value to the DynamoDB configuration test input * Adding missing imports to `_test` files. * Updating build instructions in README
This commit is contained in:
parent
f17625c1a8
commit
3149d0b953
|
@ -34,7 +34,9 @@ const (
|
|||
Forever time.Duration = 0
|
||||
)
|
||||
|
||||
// Backend implements abstraction over local or remote storage backend
|
||||
// Backend implements abstraction over local or remote storage backend.
|
||||
// Item keys are assumed to be valid UTF8, which may be enforced by the
|
||||
// various Backend implementations.
|
||||
type Backend interface {
|
||||
// Create creates item if it does not exist
|
||||
Create(ctx context.Context, i Item) (*Lease, error)
|
||||
|
|
|
@ -10,17 +10,18 @@ WARNING: Using DynamoDB involves reccuring charge from AWS.
|
|||
The table created by the backend will provision 5/5 R/W capacity.
|
||||
It should be covered by the free tier.
|
||||
|
||||
### Building
|
||||
### Running tests
|
||||
|
||||
DynamoDB backend is not enabled by default. To enable it you have to
|
||||
compile Teleport with `dynamo` build flag.
|
||||
|
||||
To build Teleport with DynamoDB enabled, run:
|
||||
The DynamodDB tests are not run by default. To run them locally, try:
|
||||
|
||||
```
|
||||
ADDFLAGS='-tags dynamodb' make teleport
|
||||
go test -tags dynamodb -v ./lib/backend/dynamo
|
||||
```
|
||||
|
||||
*NOTE:* you will need to provide a AWS credentials & a default region
|
||||
(e.g. in your `~/.aws/credentials` & `~/.aws/config` files, or via
|
||||
environment vars) for the tests to work.
|
||||
|
||||
### Quick Start
|
||||
|
||||
Add this storage configuration in `teleport` section of the config file (by default it's `/etc/teleport.yaml`):
|
||||
|
|
|
@ -20,6 +20,7 @@ package dynamo
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -100,5 +101,5 @@ func (s *DynamoDBSuite) TestWatchersClose(c *check.C) {
|
|||
}
|
||||
|
||||
func (s *DynamoDBSuite) TestLocking(c *check.C) {
|
||||
s.suite.Locking(c)
|
||||
s.suite.Locking(c, s.bk)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"context"
|
||||
"regexp"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
|
||||
|
@ -38,7 +39,7 @@ var blacklistPattern = regexp.MustCompile(`//`)
|
|||
|
||||
// isKeySafe checks if the passed in key conforms to whitelist
|
||||
func isKeySafe(s []byte) bool {
|
||||
return whitelistPattern.Match(s) && !blacklistPattern.Match(s)
|
||||
return whitelistPattern.Match(s) && !blacklistPattern.Match(s) && utf8.Valid(s)
|
||||
}
|
||||
|
||||
// Sanitizer wraps a Backend implementation to make sure all values requested
|
||||
|
|
|
@ -46,6 +46,10 @@ func (s *Suite) TestSanitizeBucket(c *check.C) {
|
|||
inKey: RangeEnd([]byte("/")),
|
||||
outError: false,
|
||||
},
|
||||
{
|
||||
inKey: RangeEnd([]byte("Malformed \xf0\x90\x28\xbc UTF8")),
|
||||
outError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
|
|
|
@ -20,6 +20,7 @@ package test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -100,12 +101,20 @@ func (s *BackendSuite) CRUD(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
c.Assert(string(out.Value), check.Equals, string(item.Value))
|
||||
|
||||
// put with binary key and value succeeds
|
||||
key := make([]byte, 1024)
|
||||
rand.Read(key)
|
||||
// put with large key and binary value succeeds.
|
||||
// NB: DynamoDB has a maximum overall key length of 1024 bytes, so
|
||||
// we need to pick a random key size that will still fit in 1KiB
|
||||
// when combined with the (currently) 33-byte prefix prepended
|
||||
// by `prefix()`, so:
|
||||
// (485 bytes * 2 (for hex encoding)) + 33 = 1003
|
||||
// which gives us a little bit of room to spare
|
||||
keyBytes := make([]byte, 485)
|
||||
rand.Read(keyBytes)
|
||||
key := hex.EncodeToString(keyBytes)
|
||||
|
||||
data := make([]byte, 1024)
|
||||
rand.Read(data)
|
||||
item = backend.Item{Key: prefix(string(key)), Value: data}
|
||||
item = backend.Item{Key: prefix(key), Value: data}
|
||||
_, err = s.B.Put(ctx, item)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
|
Loading…
Reference in a new issue