Add RBAC option to disable functions eg. count
This commit is contained in:
parent
4a8af69dd0
commit
34867a2733
|
@ -164,7 +164,7 @@ roles:
|
|||
limit: 50
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
columns: ["id", "name", "description" ]
|
||||
disable_aggregation: false
|
||||
disable_functions: false
|
||||
|
||||
insert:
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
|
|
|
@ -152,7 +152,7 @@ roles:
|
|||
limit: 50
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
columns: ["id", "name", "description" ]
|
||||
disable_aggregation: false
|
||||
disable_functions: false
|
||||
|
||||
insert:
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
|
|
|
@ -1206,7 +1206,7 @@ roles:
|
|||
limit: 50
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
columns: ["id", "name", "description" ]
|
||||
disable_aggregation: false
|
||||
disable_functions: false
|
||||
|
||||
insert:
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
|
|
29
jsn/fuzz.go
29
jsn/fuzz.go
|
@ -1,32 +1,9 @@
|
|||
// +build gofuzz
|
||||
|
||||
package jsn
|
||||
|
||||
import "bytes"
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
err1 := Validate(string(data))
|
||||
|
||||
var b1 bytes.Buffer
|
||||
err2 := Filter(&b1, data, []string{"id", "full_name", "embed"})
|
||||
|
||||
path1 := [][]byte{[]byte("data"), []byte("users")}
|
||||
Strip(data, path1)
|
||||
|
||||
from := []Field{
|
||||
{[]byte("__twitter_id"), []byte(`[{ "name": "hello" }, { "name": "world"}]`)},
|
||||
{[]byte("__twitter_id"), []byte(`"ABC123"`)},
|
||||
}
|
||||
|
||||
to := []Field{
|
||||
{[]byte("__twitter_id"), []byte(`"1234567890"`)},
|
||||
{[]byte("some_list"), []byte(`[{"id":1,"embed":{"id":8}},{"id":2},{"id":3},{"id":4},{"id":5},{"id":6},{"id":7},{"id":8},{"id":9},{"id":10},{"id":11},{"id":12},{"id":13}]`)},
|
||||
}
|
||||
|
||||
var b2 bytes.Buffer
|
||||
err3 := Replace(&b2, data, from, to)
|
||||
|
||||
Keys(data)
|
||||
|
||||
if err1 != nil || err2 != nil || err3 != nil {
|
||||
if err := unifiedTest(data); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package jsn
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFuzzCrashers(t *testing.T) {
|
||||
var crashers = []string{
|
||||
|
@ -53,6 +55,6 @@ func TestFuzzCrashers(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, f := range crashers {
|
||||
Fuzz([]byte(f))
|
||||
unifiedTest([]byte(f))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package jsn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
)
|
||||
|
||||
func unifiedTest(data []byte) error {
|
||||
err1 := Validate(string(data))
|
||||
|
||||
var b1 bytes.Buffer
|
||||
err2 := Filter(&b1, data, []string{"id", "full_name", "embed"})
|
||||
|
||||
path1 := [][]byte{[]byte("data"), []byte("users")}
|
||||
Strip(data, path1)
|
||||
|
||||
from := []Field{
|
||||
{[]byte("__twitter_id"), []byte(`[{ "name": "hello" }, { "name": "world"}]`)},
|
||||
{[]byte("__twitter_id"), []byte(`"ABC123"`)},
|
||||
}
|
||||
|
||||
to := []Field{
|
||||
{[]byte("__twitter_id"), []byte(`"1234567890"`)},
|
||||
{[]byte("some_list"), []byte(`[{"id":1,"embed":{"id":8}},{"id":2},{"id":3},{"id":4},{"id":5},{"id":6},{"id":7},{"id":8},{"id":9},{"id":10},{"id":11},{"id":12},{"id":13}]`)},
|
||||
}
|
||||
|
||||
var b2 bytes.Buffer
|
||||
err3 := Replace(&b2, data, from, to)
|
||||
|
||||
Keys(data)
|
||||
|
||||
if err1 != nil || err2 != nil || err3 != nil {
|
||||
return errors.New("there was an error")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -68,7 +68,8 @@ func TestMain(m *testing.M) {
|
|||
|
||||
qcompile.AddRole("bad_dude", "users", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Filters: []string{"false"},
|
||||
Filters: []string{"false"},
|
||||
DisableFunctions: true,
|
||||
},
|
||||
Insert: qcode.InsertConfig{
|
||||
Filters: []string{"false"},
|
||||
|
|
|
@ -373,16 +373,18 @@ func (c *compilerContext) renderJoinTable(sel *qcode.Select) error {
|
|||
func (c *compilerContext) renderColumns(sel *qcode.Select, ti *DBTableInfo) {
|
||||
i := 0
|
||||
for _, col := range sel.Cols {
|
||||
if len(sel.Allowed) != 0 {
|
||||
n := funcPrefixLen(col.Name)
|
||||
if n != 0 {
|
||||
if sel.Functions == false {
|
||||
continue
|
||||
}
|
||||
n := funcPrefixLen(col.Name)
|
||||
if n != 0 {
|
||||
if sel.Functions == false {
|
||||
continue
|
||||
}
|
||||
if len(sel.Allowed) != 0 {
|
||||
if _, ok := sel.Allowed[col.Name[n:]]; !ok {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if len(sel.Allowed) != 0 {
|
||||
if _, ok := sel.Allowed[col.Name]; !ok {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -389,6 +389,7 @@ func TestCompileQuery(t *testing.T) {
|
|||
t.Run("syntheticTables", syntheticTables)
|
||||
t.Run("queryWithVariables", queryWithVariables)
|
||||
t.Run("blockedQuery", blockedQuery)
|
||||
t.Run("blockedFunctions", blockedFunctions)
|
||||
}
|
||||
|
||||
var benchGQL = []byte(`query {
|
||||
|
@ -435,6 +436,26 @@ func blockedQuery(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func blockedFunctions(t *testing.T) {
|
||||
gql := `query {
|
||||
users {
|
||||
count_id
|
||||
email
|
||||
}
|
||||
}`
|
||||
|
||||
sql := `SELECT json_object_agg('users', users) FROM (SELECT coalesce(json_agg("sel_json_0"), '[]') AS "users" FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "users_0"."email" AS "email") AS "sel_0")) AS "sel_json_0" FROM (SELECT "users"."email" FROM "users" WHERE (false) LIMIT ('20') :: integer) AS "users_0" LIMIT ('20') :: integer) AS "sel_json_agg_0") AS "done_1337"`
|
||||
|
||||
resSQL, err := compileGQLToPSQL(gql, nil, "bad_dude")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if string(resSQL) != sql {
|
||||
t.Fatal(errNotExpected)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompile(b *testing.B) {
|
||||
w := &bytes.Buffer{}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build gofuzz
|
||||
|
||||
package qcode
|
||||
|
||||
// FuzzerEntrypoint for Fuzzbuzz
|
||||
|
|
|
@ -293,11 +293,12 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
|
|||
trv := com.getRole(role, field.Name)
|
||||
|
||||
selects = append(selects, Select{
|
||||
ID: id,
|
||||
ParentID: parentID,
|
||||
Table: field.Name,
|
||||
Children: make([]int32, 0, 5),
|
||||
Allowed: trv.allowedColumns(action),
|
||||
ID: id,
|
||||
ParentID: parentID,
|
||||
Table: field.Name,
|
||||
Children: make([]int32, 0, 5),
|
||||
Allowed: trv.allowedColumns(action),
|
||||
Functions: true,
|
||||
})
|
||||
s := &selects[(len(selects) - 1)]
|
||||
|
||||
|
|
|
@ -105,11 +105,11 @@ type configRole struct {
|
|||
Name string
|
||||
|
||||
Query struct {
|
||||
Limit int
|
||||
Filters []string
|
||||
Columns []string
|
||||
DisableAggregation bool `mapstructure:"disable_aggregation"`
|
||||
Block bool
|
||||
Limit int
|
||||
Filters []string
|
||||
Columns []string
|
||||
DisableFunctions bool `mapstructure:"disable_functions"`
|
||||
Block bool
|
||||
}
|
||||
|
||||
Insert struct {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build gofuzz
|
||||
|
||||
package serv
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
|
|
|
@ -38,7 +38,7 @@ func initCompilers(c *config) (*qcode.Compiler, *psql.Compiler, error) {
|
|||
Limit: t.Query.Limit,
|
||||
Filters: t.Query.Filters,
|
||||
Columns: t.Query.Columns,
|
||||
DisableFunctions: t.Query.DisableAggregation,
|
||||
DisableFunctions: t.Query.DisableFunctions,
|
||||
}
|
||||
|
||||
if t.Query.Block {
|
||||
|
|
|
@ -164,7 +164,7 @@ roles:
|
|||
limit: 50
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
columns: ["id", "name", "description" ]
|
||||
disable_aggregation: false
|
||||
disable_functions: false
|
||||
|
||||
insert:
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
|
|
|
@ -152,7 +152,7 @@ roles:
|
|||
limit: 50
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
columns: ["id", "name", "description" ]
|
||||
disable_aggregation: false
|
||||
disable_functions: false
|
||||
|
||||
insert:
|
||||
filters: ["{ user_id: { eq: $user_id } }"]
|
||||
|
|
Loading…
Reference in New Issue