Skip to content

Commit

Permalink
sec: implement lvs check
Browse files Browse the repository at this point in the history
  • Loading branch information
pulsejet committed Jan 18, 2025
1 parent 1c3121d commit 76d7cb8
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 21 deletions.
15 changes: 15 additions & 0 deletions std/security/schema/lvs.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,21 @@ func (s *LvsSchema) Match(name enc.Name) []*LvsNode {
return ret
}

func (s *LvsSchema) Check(pkt enc.Name, key enc.Name) bool {
pktNodes := s.Match(pkt)
keyNodes := s.Match(key)
for _, pktNode := range pktNodes {
for _, sc := range pktNode.SignCons {
for _, keyNode := range keyNodes {
if keyNode.Id == sc {
return true
}
}
}
}
return false
}

func (s *LvsSchema) checkCons(
value enc.Component,
context map[uint64]enc.Component,
Expand Down
78 changes: 57 additions & 21 deletions std/security/schema/lvs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ var TEST_MODEL_COMPLEX = []byte{
0x62, 0x67, 0x06, 0x23, 0x01, 0x06, 0x29, 0x01, 0x63,
}

func sname(n string) enc.Name {
return utils.WithoutErr(enc.NameFromStr(n))
}

func TestParseModel(t *testing.T) {
utils.SetTestingT(t)

Expand All @@ -131,43 +135,43 @@ func TestModelSimpleMatch(t *testing.T) {
require.NoError(t, err)

// Test all valid matches
ms := s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog")))
ms := s.Match(sname("/a/blog"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#site", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog/KEY/123/issuer/456")))
ms = s.Match(sname("/a/blog/KEY/123/issuer/456"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#root", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog/article/category/year/month")))
ms = s.Match(sname("/a/blog/article/category/year/month"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#article", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog/author/PANDA/KEY/kid/iss/v=1")))
ms = s.Match(sname("/a/blog/author/PANDA/KEY/kid/iss/v=1"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#author", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog/admin/PANDA/KEY/kid/iss/v=1")))
ms = s.Match(sname("/a/blog/admin/PANDA/KEY/kid/iss/v=1"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#admin", string(ms[0].RuleName[0]))

// Test invalid matches
ms = s.Match(utils.WithoutErr(enc.NameFromStr("/b/blog")))
ms = s.Match(sname("/b/blog"))
require.Equal(t, 0, len(ms))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/b/blog/KEY/123/issuer/456")))
ms = s.Match(sname("/b/blog/KEY/123/issuer/456"))
require.Equal(t, 0, len(ms))

// Test partial matches
ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog/article/category/year/month/extra")))
ms = s.Match(sname("/a/blog/article/category/year/month/extra"))
require.Equal(t, 0, len(ms))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog/article/category/year")))
ms = s.Match(sname("/a/blog/article/category/year"))
require.Equal(t, 1, len(ms))
require.Equal(t, 0, len(ms[0].RuleName)) // no matching rule

// Test invalid expansion value
ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/blog/evil/PANDA/KEY/kid/iss/v=1")))
ms = s.Match(sname("/a/blog/evil/PANDA/KEY/kid/iss/v=1"))
require.Equal(t, 0, len(ms))
}

Expand All @@ -178,46 +182,78 @@ func TestModelComplexMatch(t *testing.T) {
require.NoError(t, err)

// #r1: a/b/c & { c: b, c: a, a: "a"|"x" }
ms := s.Match(utils.WithoutErr(enc.NameFromStr("/a/a/a")))
ms := s.Match(sname("/a/a/a"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#r1", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/x/x/x")))
ms = s.Match(sname("/x/x/x"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#r1", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/a/x")))
ms = s.Match(sname("/a/a/x"))
require.Equal(t, 0, len(ms))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/c/a")))
ms = s.Match(sname("/a/c/a"))
require.Equal(t, 0, len(ms))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/x/x")))
ms = s.Match(sname("/a/x/x"))
require.Equal(t, 0, len(ms))

// #r1: a/b/c & { b: "b"|"y" }
ms = s.Match(utils.WithoutErr(enc.NameFromStr("/a/b/c")))
ms = s.Match(sname("/a/b/c"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#r1", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/p/y/q")))
ms = s.Match(sname("/p/y/q"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#r1", string(ms[0].RuleName[0]))

// #r2: x/y/z & { x: "xxx" }
// #r3: x/y/z & { y: "yyy" }
ms = s.Match(utils.WithoutErr(enc.NameFromStr("/xxx/xxx/zzz")))
ms = s.Match(sname("/xxx/xxx/zzz"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#r2", string(ms[0].RuleName[0]))

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/abc/yyy/zzz")))
ms = s.Match(sname("/abc/yyy/zzz"))
require.Equal(t, 1, len(ms))
require.Equal(t, "#r3", string(ms[0].RuleName[0]))

// Combination
ms = s.Match(utils.WithoutErr(enc.NameFromStr("/xxx/b/zzz")))
ms = s.Match(sname("/xxx/b/zzz"))
require.Equal(t, 2, len(ms)) // r1, r2

ms = s.Match(utils.WithoutErr(enc.NameFromStr("/xxx/yyy/zzz")))
ms = s.Match(sname("/xxx/yyy/zzz"))
require.Equal(t, 2, len(ms)) // r1, r3
}

func TestModelSimpleCheck(t *testing.T) {
utils.SetTestingT(t)

s, err := schema.NewLvsSchema(TEST_MODEL)
require.NoError(t, err)

require.True(t, s.Check(sname("/a/blog/admin/000001/KEY/1/root/1"), sname("/a/blog/KEY/1/self/1")))
require.False(t, s.Check(sname("/a/blog/admin/000001/VAL/1/root/1"), sname("/a/blog/KEY/1/self/1")))
require.False(t, s.Check(sname("/a/blog/admin/000002/KEY/1/root/1"), sname("/a/blog/admin/000001/KEY/1/root/1")))
require.True(t, s.Check(sname("/a/blog/author/100001/KEY/1/000001/1"), sname("/a/blog/admin/000001/KEY/1/root/1")))
require.False(t, s.Check(sname("/a/blog/author/100001/KEY/1/000001/1"), sname("/a/blog/KEY/1/self/1")))
}

func TestModelComplexCheck(t *testing.T) {
utils.SetTestingT(t)

s, err := schema.NewLvsSchema(TEST_MODEL_COMPLEX)
require.NoError(t, err)

require.True(t, s.Check(sname("/a/b/c"), sname("/xxx/yyy/zzz")))
require.True(t, s.Check(sname("/x/y/z"), sname("/xxx/xxx/xxx")))
require.True(t, s.Check(sname("/x/x/x"), sname("/xxx/yyy/zzz")))
require.True(t, s.Check(sname("/a/a/a"), sname("/xxx/xxx/xxx")))
require.True(t, s.Check(sname("/a/b/c"), sname("/xxx/pqr/rst")))

require.False(t, s.Check(sname("/xxx/yyy/zzz"), sname("/xxx/yyy/xxx")))
require.False(t, s.Check(sname("/xxx/yyy/zzz"), sname("/a/b/c")))
require.False(t, s.Check(sname("/a/b/c"), sname("/pqr/pqr/xxx")))
require.False(t, s.Check(sname("/a/b/c"), sname("/xxx/pqr")))
require.False(t, s.Check(sname("/a/b/c"), sname("/xxx/pqr/rst/uvw")))
}

0 comments on commit 76d7cb8

Please sign in to comment.