Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRUD for policies #3

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 93 additions & 89 deletions coverage.txt
Original file line number Diff line number Diff line change
@@ -1,44 +1,4 @@
mode: atomic
github.com/siadat/leges/leges.go:27.43,29.2 1 0
github.com/siadat/leges/leges.go:31.43,33.2 1 0
github.com/siadat/leges/leges.go:41.47,43.2 1 0
github.com/siadat/leges/leges.go:45.47,47.2 1 0
github.com/siadat/leges/leges.go:59.66,62.51 2 3
github.com/siadat/leges/leges.go:66.2,66.53 1 3
github.com/siadat/leges/leges.go:70.2,70.19 1 3
github.com/siadat/leges/leges.go:62.51,64.3 1 0
github.com/siadat/leges/leges.go:66.53,68.3 1 0
github.com/siadat/leges/leges.go:73.55,76.24 2 3
github.com/siadat/leges/leges.go:80.2,80.12 1 3
github.com/siadat/leges/leges.go:76.24,78.3 1 0
github.com/siadat/leges/leges.go:85.54,88.33 2 3
github.com/siadat/leges/leges.go:112.2,112.12 1 3
github.com/siadat/leges/leges.go:88.33,89.43 1 6
github.com/siadat/leges/leges.go:93.3,93.47 1 6
github.com/siadat/leges/leges.go:97.3,98.17 2 6
github.com/siadat/leges/leges.go:106.3,109.4 1 6
github.com/siadat/leges/leges.go:89.43,91.4 1 0
github.com/siadat/leges/leges.go:93.47,95.4 1 0
github.com/siadat/leges/leges.go:98.17,104.4 1 0
github.com/siadat/leges/leges.go:116.62,120.34 2 3
github.com/siadat/leges/leges.go:125.2,128.46 3 3
github.com/siadat/leges/leges.go:133.2,133.12 1 3
github.com/siadat/leges/leges.go:120.34,122.3 1 0
github.com/siadat/leges/leges.go:128.46,131.3 2 0
github.com/siadat/leges/leges.go:137.63,138.43 1 3
github.com/siadat/leges/leges.go:142.2,144.43 2 3
github.com/siadat/leges/leges.go:164.2,164.24 1 1
github.com/siadat/leges/leges.go:138.43,140.3 1 0
github.com/siadat/leges/leges.go:144.43,145.61 1 6
github.com/siadat/leges/leges.go:149.3,150.17 2 2
github.com/siadat/leges/leges.go:159.3,159.20 1 2
github.com/siadat/leges/leges.go:145.61,146.12 1 4
github.com/siadat/leges/leges.go:150.17,157.4 1 0
github.com/siadat/leges/leges.go:159.20,161.4 1 2
github.com/siadat/leges/leges.go:167.56,168.29 1 6
github.com/siadat/leges/leges.go:173.2,173.14 1 4
github.com/siadat/leges/leges.go:168.29,169.21 1 6
github.com/siadat/leges/leges.go:169.21,171.4 1 2
github.com/siadat/leges/policy.go:24.34,25.16 1 6
github.com/siadat/leges/policy.go:28.2,28.12 1 6
github.com/siadat/leges/policy.go:25.16,27.3 1 0
Expand Down Expand Up @@ -81,17 +41,48 @@ github.com/siadat/leges/httpserver/httpserver.go:92.16,94.3 1 3
github.com/siadat/leges/httpserver/httpserver.go:98.47,101.16 3 15
github.com/siadat/leges/httpserver/httpserver.go:104.2,104.21 1 15
github.com/siadat/leges/httpserver/httpserver.go:101.16,102.13 1 0
github.com/siadat/leges/policy.go:24.34,25.16 1 63
github.com/siadat/leges/policy.go:28.2,28.12 1 61
github.com/siadat/leges/policy.go:25.16,27.3 1 2
github.com/siadat/leges/policy.go:31.57,33.2 1 59
github.com/siadat/leges/request.go:21.35,22.43 1 10019
github.com/siadat/leges/request.go:25.2,25.45 1 10017
github.com/siadat/leges/request.go:28.2,28.20 1 10015
github.com/siadat/leges/request.go:31.2,31.12 1 10014
github.com/siadat/leges/request.go:22.43,24.3 1 2
github.com/siadat/leges/request.go:25.45,27.3 1 2
github.com/siadat/leges/request.go:28.20,30.3 1 1
github.com/siadat/leges/leges.go:31.43,33.2 1 0
github.com/siadat/leges/leges.go:35.43,37.2 1 0
github.com/siadat/leges/leges.go:45.47,47.2 1 0
github.com/siadat/leges/leges.go:49.47,51.2 1 0
github.com/siadat/leges/leges.go:63.66,66.51 2 3
github.com/siadat/leges/leges.go:70.2,70.53 1 3
github.com/siadat/leges/leges.go:74.2,74.19 1 3
github.com/siadat/leges/leges.go:66.51,68.3 1 0
github.com/siadat/leges/leges.go:70.53,72.3 1 0
github.com/siadat/leges/leges.go:77.55,80.24 2 3
github.com/siadat/leges/leges.go:84.2,84.12 1 3
github.com/siadat/leges/leges.go:80.24,82.3 1 0
github.com/siadat/leges/leges.go:89.54,92.33 2 3
github.com/siadat/leges/leges.go:98.2,98.12 1 3
github.com/siadat/leges/leges.go:92.33,93.45 1 6
github.com/siadat/leges/leges.go:93.45,95.4 1 0
github.com/siadat/leges/leges.go:101.48,105.42 3 6
github.com/siadat/leges/leges.go:109.2,109.46 1 6
github.com/siadat/leges/leges.go:113.2,114.16 2 6
github.com/siadat/leges/leges.go:122.2,127.12 2 6
github.com/siadat/leges/leges.go:105.42,107.3 1 0
github.com/siadat/leges/leges.go:109.46,111.3 1 0
github.com/siadat/leges/leges.go:114.16,120.3 1 0
github.com/siadat/leges/leges.go:131.62,135.34 2 3
github.com/siadat/leges/leges.go:140.2,143.46 3 3
github.com/siadat/leges/leges.go:148.2,148.12 1 3
github.com/siadat/leges/leges.go:135.34,137.3 1 0
github.com/siadat/leges/leges.go:143.46,146.3 2 0
github.com/siadat/leges/leges.go:152.63,153.43 1 3
github.com/siadat/leges/leges.go:157.2,159.43 2 3
github.com/siadat/leges/leges.go:179.2,179.24 1 1
github.com/siadat/leges/leges.go:153.43,155.3 1 0
github.com/siadat/leges/leges.go:159.43,160.61 1 5
github.com/siadat/leges/leges.go:164.3,165.17 2 2
github.com/siadat/leges/leges.go:174.3,174.20 1 2
github.com/siadat/leges/leges.go:160.61,161.12 1 3
github.com/siadat/leges/leges.go:165.17,172.4 1 0
github.com/siadat/leges/leges.go:174.20,176.4 1 2
github.com/siadat/leges/leges.go:182.56,183.29 1 5
github.com/siadat/leges/leges.go:188.2,188.14 1 3
github.com/siadat/leges/leges.go:183.29,184.21 1 5
github.com/siadat/leges/leges.go:184.21,186.4 1 2
github.com/siadat/leges/httpserver/httpserver.go:21.70,25.16 3 0
github.com/siadat/leges/httpserver/httpserver.go:32.2,33.16 2 0
github.com/siadat/leges/httpserver/httpserver.go:40.2,47.16 3 0
Expand Down Expand Up @@ -123,43 +114,56 @@ github.com/siadat/leges/cmd/leges/main.go:37.12,43.54 5 0
github.com/siadat/leges/cmd/leges/main.go:46.3,46.25 1 0
github.com/siadat/leges/cmd/leges/main.go:43.54,44.14 1 0
github.com/siadat/leges/cmd/leges/main.go:51.62,52.13 1 0
github.com/siadat/leges/leges.go:27.43,29.2 1 0
github.com/siadat/leges/leges.go:31.43,33.2 1 0
github.com/siadat/leges/leges.go:41.47,43.2 1 0
github.com/siadat/leges/leges.go:35.43,37.2 1 0
github.com/siadat/leges/leges.go:45.47,47.2 1 0
github.com/siadat/leges/leges.go:59.66,62.51 2 19
github.com/siadat/leges/leges.go:66.2,66.53 1 19
github.com/siadat/leges/leges.go:70.2,70.19 1 16
github.com/siadat/leges/leges.go:62.51,64.3 1 0
github.com/siadat/leges/leges.go:66.53,68.3 1 3
github.com/siadat/leges/leges.go:73.55,76.24 2 19
github.com/siadat/leges/leges.go:80.2,80.12 1 19
github.com/siadat/leges/leges.go:76.24,78.3 1 4
github.com/siadat/leges/leges.go:85.54,88.33 2 19
github.com/siadat/leges/leges.go:112.2,112.12 1 16
github.com/siadat/leges/leges.go:88.33,89.43 1 61
github.com/siadat/leges/leges.go:93.3,93.47 1 60
github.com/siadat/leges/leges.go:97.3,98.17 2 59
github.com/siadat/leges/leges.go:106.3,109.4 1 58
github.com/siadat/leges/leges.go:89.43,91.4 1 1
github.com/siadat/leges/leges.go:93.47,95.4 1 1
github.com/siadat/leges/leges.go:98.17,104.4 1 1
github.com/siadat/leges/leges.go:116.62,120.34 2 10013
github.com/siadat/leges/leges.go:125.2,128.46 3 10013
github.com/siadat/leges/leges.go:133.2,133.12 1 10013
github.com/siadat/leges/leges.go:120.34,122.3 1 20002
github.com/siadat/leges/leges.go:128.46,131.3 2 0
github.com/siadat/leges/leges.go:137.63,138.43 1 10015
github.com/siadat/leges/leges.go:142.2,144.43 2 10013
github.com/siadat/leges/leges.go:164.2,164.24 1 5
github.com/siadat/leges/leges.go:138.43,140.3 1 2
github.com/siadat/leges/leges.go:144.43,145.61 1 26102
github.com/siadat/leges/leges.go:149.3,150.17 2 10014
github.com/siadat/leges/leges.go:159.3,159.20 1 10013
github.com/siadat/leges/leges.go:145.61,146.12 1 16088
github.com/siadat/leges/leges.go:150.17,157.4 1 1
github.com/siadat/leges/leges.go:159.20,161.4 1 10007
github.com/siadat/leges/leges.go:167.56,168.29 1 26102
github.com/siadat/leges/leges.go:173.2,173.14 1 16088
github.com/siadat/leges/leges.go:168.29,169.21 1 63662
github.com/siadat/leges/leges.go:169.21,171.4 1 10014
github.com/siadat/leges/leges.go:49.47,51.2 1 0
github.com/siadat/leges/leges.go:63.66,66.51 2 20
github.com/siadat/leges/leges.go:70.2,70.53 1 20
github.com/siadat/leges/leges.go:74.2,74.19 1 17
github.com/siadat/leges/leges.go:66.51,68.3 1 0
github.com/siadat/leges/leges.go:70.53,72.3 1 3
github.com/siadat/leges/leges.go:77.55,80.24 2 20
github.com/siadat/leges/leges.go:84.2,84.12 1 20
github.com/siadat/leges/leges.go:80.24,82.3 1 4
github.com/siadat/leges/leges.go:89.54,92.33 2 20
github.com/siadat/leges/leges.go:98.2,98.12 1 17
github.com/siadat/leges/leges.go:92.33,93.45 1 61
github.com/siadat/leges/leges.go:93.45,95.4 1 3
github.com/siadat/leges/leges.go:101.48,105.42 3 562
github.com/siadat/leges/leges.go:109.2,109.46 1 561
github.com/siadat/leges/leges.go:113.2,114.16 2 560
github.com/siadat/leges/leges.go:122.2,127.12 2 559
github.com/siadat/leges/leges.go:105.42,107.3 1 1
github.com/siadat/leges/leges.go:109.46,111.3 1 1
github.com/siadat/leges/leges.go:114.16,120.3 1 1
github.com/siadat/leges/leges.go:131.62,135.34 2 10015
github.com/siadat/leges/leges.go:140.2,143.46 3 10015
github.com/siadat/leges/leges.go:148.2,148.12 1 10015
github.com/siadat/leges/leges.go:135.34,137.3 1 20002
github.com/siadat/leges/leges.go:143.46,146.3 2 0
github.com/siadat/leges/leges.go:152.63,153.43 1 10017
github.com/siadat/leges/leges.go:157.2,159.43 2 10015
github.com/siadat/leges/leges.go:179.2,179.24 1 6
github.com/siadat/leges/leges.go:153.43,155.3 1 2
github.com/siadat/leges/leges.go:159.43,160.61 1 26521
github.com/siadat/leges/leges.go:164.3,165.17 2 10014
github.com/siadat/leges/leges.go:174.3,174.20 1 10013
github.com/siadat/leges/leges.go:160.61,161.12 1 16507
github.com/siadat/leges/leges.go:165.17,172.4 1 1
github.com/siadat/leges/leges.go:174.20,176.4 1 10008
github.com/siadat/leges/leges.go:182.56,183.29 1 26521
github.com/siadat/leges/leges.go:188.2,188.14 1 16507
github.com/siadat/leges/leges.go:183.29,184.21 1 64056
github.com/siadat/leges/leges.go:184.21,186.4 1 10014
github.com/siadat/leges/policy.go:24.34,25.16 1 564
github.com/siadat/leges/policy.go:28.2,28.12 1 562
github.com/siadat/leges/policy.go:25.16,27.3 1 2
github.com/siadat/leges/policy.go:31.57,33.2 1 560
github.com/siadat/leges/request.go:21.35,22.43 1 10021
github.com/siadat/leges/request.go:25.2,25.45 1 10019
github.com/siadat/leges/request.go:28.2,28.20 1 10017
github.com/siadat/leges/request.go:31.2,31.12 1 10016
github.com/siadat/leges/request.go:22.43,24.3 1 2
github.com/siadat/leges/request.go:25.45,27.3 1 2
github.com/siadat/leges/request.go:28.20,30.3 1 1
45 changes: 30 additions & 15 deletions leges.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
"sync"
)

var ErrDuplicatePolicyID = errors.New("duplicate policies with id")
Expand All @@ -15,6 +16,9 @@ type Leges struct {
cachedPolicies map[string]cachedPolicy
// environment are a set of attributes that are always merged with the request
environment Attributes

// lock provides mutex for cachedPolicies
lock sync.Mutex
}

type ErrExprRunFailed struct {
Expand Down Expand Up @@ -86,29 +90,40 @@ func (l *Leges) loadPolicies(polices []Policy) error {
l.cachedPolicies = make(map[string]cachedPolicy, len(polices))

for _, policy := range polices {
if err := policy.Validate(); err != nil {
if err := l.AddPolicy(policy); err != nil {
return err
}
}

if _, ok := l.cachedPolicies[policy.ID]; ok {
return fmt.Errorf("id=%q: %w", policy.ID, ErrDuplicatePolicyID)
}
return nil
}

program, err := policy.compileCondition()
if err != nil {
return &ErrExprCompileFailed{
Environment: l.environment,
Policy: policy,
Err: err,
}
}
func (l *Leges) AddPolicy(policy Policy) error {
l.lock.Lock()
defer l.lock.Unlock()

if err := policy.Validate(); err != nil {
return err
}

l.cachedPolicies[policy.ID] = cachedPolicy{
policy: policy,
program: program,
if _, ok := l.cachedPolicies[policy.ID]; ok {
return fmt.Errorf("id=%q: %w", policy.ID, ErrDuplicatePolicyID)
}

program, err := policy.compileCondition()
if err != nil {
return &ErrExprCompileFailed{
Environment: l.environment,
Policy: policy,
Err: err,
}
}

l.cachedPolicies[policy.ID] = cachedPolicy{
policy: policy,
program: program,
}

return nil
}

Expand Down
68 changes: 68 additions & 0 deletions leges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,74 @@ func TestSimplePolicy(t *testing.T) {

}

func TestLeges_AddPolicy(t *testing.T) {
rules := mustNewLeges(t, []leges.Policy{}, nil)
request := leges.Request{
Action: "UPDATE",
Subject: leges.Attributes{
"id": "user1",
},
Object: leges.Attributes{
"type": "account",
"owner_id": "user1",
},
}

t.Run("no policies matches", func(t *testing.T) {
ok, _, err := rules.Match(request)
require.NoError(t, err)
require.Equal(t, false, ok)
})

t.Run("policy1 matches", func(t *testing.T) {
policy1 := leges.Policy{
ID: "policy1",
Condition: `
object.type == "account"
and object.owner_id == subject.id
`,
Actions: []string{
"PUBLIC_VIEW",
"GET",
"UPDATE",
"MY_ACTION",
},
}
rules.AddPolicy(policy1)
ok, policy, err := rules.Match(request)
require.NoError(t, err)
require.Equal(t, true, ok)
require.Equal(t, "policy1", policy.ID)
})

t.Run("add policies concurrently to check for race conditions", func(t *testing.T) {
wg := sync.WaitGroup{}
for i := 0; i < 500; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
policy := leges.Policy{
ID: fmt.Sprintf("policy%d", i+2),
Condition: `
object.type == "account"
and object.owner_id == subject.id
`,
Actions: []string{
"PUBLIC_VIEW",
"GET",
"UPDATE",
"MY_ACTION",
},
}
err := rules.AddPolicy(policy)
require.NoError(t, err)
}(i)
}
wg.Wait()
})

}

func mustNewLeges(t *testing.T, policies []leges.Policy, sharedEnv leges.Attributes) *leges.Leges {
t.Helper()
rules, err := leges.NewLeges(policies, sharedEnv)
Expand Down