Add index authorisation test coverage

pull/9127/head
Edd Robinson 2017-11-15 18:55:55 +00:00
parent 6851db3fc9
commit d4cecd7cc7
2 changed files with 137 additions and 0 deletions

View File

@ -2,11 +2,14 @@ package inmem_test
import (
"fmt"
"reflect"
"strings"
"testing"
"github.com/influxdata/influxdb/internal"
"github.com/influxdata/influxdb/models"
"github.com/influxdata/influxdb/query"
"github.com/influxdata/influxdb/tsdb"
"github.com/influxdata/influxdb/tsdb/index/inmem"
"github.com/influxdata/influxql"
)
@ -145,6 +148,76 @@ func TestMeasurement_TagsSet_Deadlock(t *testing.T) {
}
}
func TestIndex_MeasurementNamesByExpr_Auth(t *testing.T) {
idx := NewIndex()
idx.AddSeries("cpu", map[string]string{"region": "east"})
idx.AddSeries("cpu", map[string]string{"region": "west", "secret": "foo"})
idx.AddSeries("disk", map[string]string{"secret": "foo"})
idx.AddSeries("mem", map[string]string{"region": "west"})
idx.AddSeries("gpu", nil)
authorizer := &internal.AuthorizerMock{
AuthorizeSeriesReadFn: func(database string, measurement []byte, tags models.Tags) bool {
if tags.GetString("secret") != "" {
t.Logf("Rejecting series db=%s, m=%s, tags=%v", database, measurement, tags)
return false
}
return true
},
}
// When no condition is provided, all authorised measurements should be returned.
names, err := idx.MeasurementNamesByExpr(authorizer, nil)
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(names, [][]byte{[]byte("cpu"), []byte("gpu"), []byte("mem")}) {
t.Fatalf("unexpected names: %v", BytesToStrings(names))
}
// When using a tag filter, authorised measurements should be returned that
// match the tag filter.
names, err = idx.MeasurementNamesByExpr(authorizer, influxql.MustParseExpr(`region = 'west'`))
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(names, [][]byte{[]byte("mem")}) {
t.Fatalf("unexpected names: %v", BytesToStrings(names))
}
// When using a regex on a measurement name, all authorised measurements
// should be returned.
names, err = idx.MeasurementNamesByExpr(authorizer, influxql.MustParseExpr(`_name =~ /cpu|disk/`))
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(names, [][]byte{[]byte("cpu")}) {
t.Fatalf("unexpected names: %v", BytesToStrings(names))
}
}
func BytesToStrings(a [][]byte) []string {
s := make([]string, 0, len(a))
for _, v := range a {
s = append(s, string(v))
}
return s
}
type Index struct {
*inmem.ShardIndex
}
func NewIndex() *Index {
options := tsdb.NewEngineOptions()
options.InmemIndex = inmem.NewIndex("db0")
index := inmem.NewShardIndex(0, "db0", "", options).(*inmem.ShardIndex)
return &Index{ShardIndex: index}
}
func (idx *Index) AddSeries(name string, tags map[string]string) error {
t := models.NewTags(tags)
key := fmt.Sprintf("%s,%s", name, t.HashKey())
return idx.CreateSeriesIfNotExists([]byte(key), []byte(name), t)
}
func BenchmarkMeasurement_SeriesIDForExp_EQRegex(b *testing.B) {
m := inmem.NewMeasurement("foo", "cpu")
for i := 0; i < 100000; i++ {

View File

@ -9,6 +9,7 @@ import (
"regexp"
"testing"
"github.com/influxdata/influxdb/internal"
"github.com/influxdata/influxdb/models"
"github.com/influxdata/influxdb/tsdb/index/tsi1"
"github.com/influxdata/influxql"
@ -176,6 +177,61 @@ func TestIndex_MeasurementNamesByExpr(t *testing.T) {
})
}
func TestIndex_MeasurementNamesByExpr_Auth(t *testing.T) {
idx := MustOpenIndex()
defer idx.Close()
// Add series to index.
if err := idx.CreateSeriesSliceIfNotExists([]Series{
{Name: []byte("cpu"), Tags: models.NewTags(map[string]string{"region": "east"})},
{Name: []byte("cpu"), Tags: models.NewTags(map[string]string{"region": "west", "secret": "foo"})},
{Name: []byte("disk"), Tags: models.NewTags(map[string]string{"secret": "foo"})},
{Name: []byte("mem"), Tags: models.NewTags(map[string]string{"region": "west", "country": "us"})},
}); err != nil {
t.Fatal(err)
}
authorizer := &internal.AuthorizerMock{
AuthorizeSeriesReadFn: func(database string, measurement []byte, tags models.Tags) bool {
if tags.GetString("secret") != "" {
t.Logf("Rejecting series db=%s, m=%s, tags=%v", database, measurement, tags)
return false
}
return true
},
}
// Retrieve measurements by expression
idx.Run(t, func(t *testing.T) {
t.Run("No Filter", func(t *testing.T) {
names, err := idx.MeasurementNamesByExpr(authorizer, nil)
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(names, [][]byte{[]byte("cpu"), []byte("mem")}) {
t.Fatalf("unexpected names: %v", BytesToStrings(names))
}
})
t.Run("EQ", func(t *testing.T) {
names, err := idx.MeasurementNamesByExpr(authorizer, influxql.MustParseExpr(`region = 'west'`))
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(names, [][]byte{[]byte("mem")}) {
t.Fatalf("unexpected names: %v", BytesToStrings(names))
}
})
t.Run("EQREGEX", func(t *testing.T) {
names, err := idx.MeasurementNamesByExpr(authorizer, influxql.MustParseExpr(`_name =~ /cpu|disk/`))
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(names, [][]byte{[]byte("cpu")}) {
t.Fatalf("unexpected names: %v", BytesToStrings(names))
}
})
})
}
// Ensure index can return a list of matching measurements.
func TestIndex_MeasurementNamesByRegex(t *testing.T) {
idx := MustOpenIndex()
@ -394,3 +450,11 @@ func (idx *Index) CreateSeriesSliceIfNotExists(a []Series) error {
}
return nil
}
func BytesToStrings(a [][]byte) []string {
s := make([]string, 0, len(a))
for _, v := range a {
s = append(s, string(v))
}
return s
}