diff --git a/e2e/newenemy/newenemy_test.go b/e2e/newenemy/newenemy_test.go index 1619b4d09f..74b558bc7d 100644 --- a/e2e/newenemy/newenemy_test.go +++ b/e2e/newenemy/newenemy_test.go @@ -24,18 +24,16 @@ import ( ) type SchemaData struct { - Prefixes []string + Prefix string } const schemaText = ` -{{ range .Prefixes }} -definition {{.}}/user {} -definition {{.}}/resource { - relation direct: {{.}}/user - relation excluded: {{.}}/user +definition {{.Prefix}}/user {} +definition {{.Prefix}}/resource { + relation direct: {{.Prefix}}/user + relation excluded: {{.Prefix}}/user permission allowed = direct - excluded } -{{ end }} ` var ( @@ -53,7 +51,7 @@ func TestMain(m *testing.M) { const ( createDb = "CREATE DATABASE %s;" - setSmallRanges = "ALTER DATABASE %s CONFIGURE ZONE USING range_min_bytes = 0, range_max_bytes = 65536, num_replicas = 1, gc.ttlseconds = 5;" + setSmallRanges = "ALTER DATABASE %s CONFIGURE ZONE USING range_min_bytes = 0, range_max_bytes = 65536, num_replicas = 1;" dbName = "spicedbnetest" ) @@ -93,21 +91,6 @@ func TestNoNewEnemy(t *testing.T) { "--datastore-tx-overlap-strategy=insecure")) require.NoError(vulnerableSpiceDb.Connect(ctx, os.Stdout)) - t.Log("create initial test schema") - schemaData := generateSchemaData(1500) - require.NoError(initSchema(schemaData, vulnerableSpiceDb[0].Client().V1Alpha1().Schema())) - - t.Log("filling with data to span multiple ranges") - rand.Seed(time.Now().UnixNano()) - fill(require, vulnerableSpiceDb[0].Client().V0().ACL(), schemaData, 4000, 100) - - // restart vulnerable spicedb to clear caches - require.NoError(vulnerableSpiceDb.Stop(os.Stdout)) - vulnerableSpiceDb = spice.NewClusterFromCockroachCluster(crdb, spice.WithDbName(dbName)) - require.NoError(vulnerableSpiceDb.Start(ctx, os.Stdout, "vulnerable", - "--datastore-tx-overlap-strategy=insecure")) - require.NoError(vulnerableSpiceDb.Connect(ctx, os.Stdout)) - t.Log("start protected spicedb cluster") protectedSpiceDb := spice.NewClusterFromCockroachCluster(crdb, spice.WithGrpcPort(50061), @@ -124,6 +107,14 @@ func TestNoNewEnemy(t *testing.T) { fmt.Sprintf(setSmallRanges, dbName), )) + t.Log("fill with schemas to span multiple ranges") + schemaData := generateSchemaData(4000) + require.NoError(fillSchema(schemaData, vulnerableSpiceDb[1].Client().V1Alpha1().Schema())) + + t.Log("filling with data to span multiple ranges") + rand.Seed(time.Now().UnixNano()) + fill(require, vulnerableSpiceDb[0].Client().V0().ACL(), schemaData, 4000, 100) + t.Log("modifying time") timeDelay := 100 * time.Millisecond require.NoError(crdb.TimeDelay(ctx, e2e.MustFile(ctx, t, "timeattack.log"), 1, -1*timeDelay)) @@ -137,7 +128,7 @@ func TestNoNewEnemy(t *testing.T) { for i := 0; i < sampleSize; i++ { t.Log(i, "check vulnerability with mitigations disabled") - checkCtx, checkCancel := context.WithTimeout(ctx, 30*time.Minute) + checkCtx, checkCancel := context.WithTimeout(ctx, 3*time.Minute) protected, attempts := checkNoNewEnemy(checkCtx, t, schemaData, vulnerableSpiceDb, -1) require.NotNil(protected, "unable to determine if spicedb displays newenemy when mitigations are disabled within the time limit") require.False(*protected) @@ -170,7 +161,7 @@ func TestNoNewEnemy(t *testing.T) { } // checkNoNewEnemy returns true if the service is protected, false if it is vulnerable, and nil if we couldn't determine -func checkNoNewEnemy(ctx context.Context, t testing.TB, schemaData SchemaData, spicedb spice.Cluster, candidateCount int) (*bool, int) { +func checkNoNewEnemy(ctx context.Context, t testing.TB, schemaData []SchemaData, spicedb spice.Cluster, candidateCount int) (*bool, int) { var attempts int for { attempts++ @@ -194,7 +185,7 @@ func checkNoNewEnemy(ctx context.Context, t testing.TB, schemaData SchemaData, s continue } - canHas, err := spicedb[2].Client().V0().ACL().Check(context.Background(), &v0.CheckRequest{ + canHas, err := spicedb[1].Client().V0().ACL().Check(context.Background(), &v0.CheckRequest{ TestUserset: &v0.ObjectAndRelation{ Namespace: directs[0].Tuple.ObjectAndRelation.Namespace, ObjectId: directs[0].Tuple.ObjectAndRelation.ObjectId, @@ -276,7 +267,7 @@ func BenchmarkConflictingTupleWrites(b *testing.B) { checkNoNewEnemy(ctx, b, schemaData, spicedb, b.N) } -func fill(require *require.Assertions, client v0.ACLServiceClient, schemaData SchemaData, fillerCount, batchSize int) { +func fill(require *require.Assertions, client v0.ACLServiceClient, schemaData []SchemaData, fillerCount, batchSize int) { directs, excludes := generateTuples(schemaData, fillerCount) for i := 0; i < fillerCount/batchSize; i++ { fmt.Println("filling ", i*batchSize, "to", (i+1)*batchSize) @@ -291,31 +282,51 @@ func fill(require *require.Assertions, client v0.ACLServiceClient, schemaData Sc } } -func initSchema(data SchemaData, schemaClient v1alpha1.SchemaServiceClient) error { +func fillSchema(data []SchemaData, schemaClient v1alpha1.SchemaServiceClient) error { var b strings.Builder - err := schemaTpl.Execute(&b, data) - if err != nil { - return err + batchSize := 100 + for i := 0; i < len(data)/batchSize; i++ { + fmt.Println("filling ", i*batchSize, "to", (i+1)*batchSize) + batch := data[i*batchSize : (i+1)*batchSize] + schema := "" + for _, d := range batch { + b.Reset() + err := schemaTpl.Execute(&b, d) + if err != nil { + return err + } + schema += b.String() + "\n" + } + var err error + for i := 0; i < 3; i++ { + _, err = schemaClient.WriteSchema(context.Background(), &v1alpha1.WriteSchemaRequest{ + Schema: schema, + }) + if err != nil { + fmt.Println("failed") + continue + } + } + if err != nil { + return err + } } - _, err = schemaClient.WriteSchema(context.Background(), &v1alpha1.WriteSchemaRequest{ - Schema: b.String(), - }) - return err + return nil } -func generateSchemaData(n int) (data SchemaData) { - data = SchemaData{Prefixes: make([]string, 0, n)} +func generateSchemaData(n int) (data []SchemaData) { + data = make([]SchemaData, 0, n) for i := 0; i < n; i++ { - data.Prefixes = append(data.Prefixes, randNamespacePrefix()) + data = append(data, SchemaData{Prefix: randNamespacePrefix()}) } return } -func generateTuples(schemaData SchemaData, n int) (directs []*v0.RelationTupleUpdate, excludes []*v0.RelationTupleUpdate) { +func generateTuples(schemaData []SchemaData, n int) (directs []*v0.RelationTupleUpdate, excludes []*v0.RelationTupleUpdate) { directs = make([]*v0.RelationTupleUpdate, 0, n) excludes = make([]*v0.RelationTupleUpdate, 0, n) for i := 0; i < n; i++ { - prefix := schemaData.Prefixes[rand.Intn(len(schemaData.Prefixes))] + prefix := schemaData[rand.Intn(len(schemaData))].Prefix user := &v0.User{ UserOneof: &v0.User_Userset{ Userset: &v0.ObjectAndRelation{ diff --git a/e2e/spice/spicedb.go b/e2e/spice/spicedb.go index 5fbf11966c..2f7eea46e7 100644 --- a/e2e/spice/spicedb.go +++ b/e2e/spice/spicedb.go @@ -76,6 +76,7 @@ func (s *Node) Start(ctx context.Context, logprefix string, args ...string) erro "./spicedb", "serve", "--log-level=debug", + "--datastore-request-hedging=false", "--grpc-preshared-key=" + s.PresharedKey, "--datastore-engine=" + s.Datastore, "--datastore-conn-uri=" + s.URI,