From 6cf2d2d957e105c909c3dc80719ffc3729bec71d Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Fri, 21 Jul 2023 13:33:04 -0600 Subject: [PATCH] Added SimplePolicy --- context.go | 4 +++ gql.go | 2 +- gql_test.go | 19 ++++------- policy.go | 93 +++++++++++++++++++++++++++++++++++++++-------------- user.go | 8 +++-- 5 files changed, 85 insertions(+), 41 deletions(-) diff --git a/context.go b/context.go index 6cee835..cb09963 100644 --- a/context.go +++ b/context.go @@ -192,6 +192,10 @@ func NewContext(db * badger.DB, log Logger) * Context { if err != nil { panic(err) } + err = ctx.RegisterNodeType(NewNodeDef((*SimplePolicy)(nil), LoadSimplePolicy, GQLTypeGraphNode())) + if err != nil { + panic(err) + } ctx.AddGQLType(GQLTypeSignal()) diff --git a/gql.go b/gql.go index 628ba35..9673bd6 100644 --- a/gql.go +++ b/gql.go @@ -203,7 +203,7 @@ func AuthHandler(ctx *Context, server *GQLThread) func(http.ResponseWriter, *htt } else { ctx.Log.Logf("gql", "AUTHORIZING NEW USER %s - %s", key_id, shared) - new_user := NewUser(fmt.Sprintf("GQL_USER %s", key_id.String()), time.Now(), remote_id, shared) + new_user := NewUser(fmt.Sprintf("GQL_USER %s", key_id.String()), time.Now(), remote_id, shared, []string{"gql"}) err := UpdateStates(ctx, []Node{server, &new_user}, func(nodes NodeMap) error { server.Users[key_id] = &new_user return nil diff --git a/gql_test.go b/gql_test.go index 88420d7..b57df18 100644 --- a/gql_test.go +++ b/gql_test.go @@ -23,9 +23,6 @@ func TestGQLThread(t * testing.T) { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) fatalErr(t, err) - p1_r := NewPerNodePolicy(RandID(), nil, NewNodeActions(nil, []string{"enumerate"})) - p1 := &p1_r - gql_t_r := NewGQLThread(RandID(), "GQL Thread", "init", ":0", ecdh.P256(), key, nil, nil) gql_t := &gql_t_r @@ -34,13 +31,9 @@ func TestGQLThread(t * testing.T) { t2_r := NewSimpleThread(RandID(), "Test thread 2", "init", nil, BaseThreadActions, BaseThreadHandlers) t2 := &t2_r - err = UpdateStates(ctx, []Node{gql_t, t1, t2, p1}, func(nodes NodeMap) error { - err := gql_t.AddPolicy(p1) - if err != nil { - return err - } + err = UpdateStates(ctx, []Node{gql_t, t1, t2}, func(nodes NodeMap) error { i1 := NewParentThreadInfo(true, "start", "restore") - err = LinkThreads(ctx, gql_t, t1, &i1, nodes) + err := LinkThreads(ctx, gql_t, t1, &i1, nodes) if err != nil { return err } @@ -76,10 +69,10 @@ func TestGQLDBLoad(t * testing.T) { u1_shared := []byte{0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x23, 0x45, 0x67} - u1_r := NewUser("Test User", time.Now(), &u1_key.PublicKey, u1_shared) + u1_r := NewUser("Test User", time.Now(), &u1_key.PublicKey, u1_shared, []string{"gql"}) u1 := &u1_r - p1_r := NewPerNodePolicy(RandID(), nil, NewNodeActions(nil, []string{"enumerate"})) + p1_r := NewSimplePolicy(RandID(), NewNodeActions(nil, []string{"enumerate"})) p1 := &p1_r key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -160,11 +153,11 @@ func TestGQLDBLoad(t * testing.T) { } func TestGQLAuth(t * testing.T) { - ctx := logTestContext(t, []string{"test", "gql", "db"}) + ctx := logTestContext(t, []string{"test", "gql"}) key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) fatalErr(t, err) - p1_r := NewPerNodePolicy(RandID(), nil, NewNodeActions(nil, []string{"*"})) + p1_r := NewSimplePolicy(RandID(), NewNodeActions(nil, []string{"*"})) p1 := &p1_r gql_t_r := NewGQLThread(RandID(), "GQL Thread", "init", ":0", ecdh.P256(), key, nil, nil) diff --git a/policy.go b/policy.go index 6ddbbbb..4804784 100644 --- a/policy.go +++ b/policy.go @@ -45,14 +45,12 @@ func NewNodeActions(resource_actions NodeActions, wildcard_actions []string) Nod type PerNodePolicy struct { GraphNode - NodeActions map[NodeID]NodeActions - WildcardActions NodeActions + Actions map[NodeID]NodeActions } type PerNodePolicyJSON struct { GraphNodeJSON - NodeActions map[string]map[string][]string `json:"allowed_actions"` - WildcardActions map[string][]string `json:"wildcard_actions"` + Actions map[string]map[string][]string `json:"actions"` } func (policy *PerNodePolicy) Type() NodeType { @@ -61,30 +59,24 @@ func (policy *PerNodePolicy) Type() NodeType { func (policy *PerNodePolicy) Serialize() ([]byte, error) { allowed_actions := map[string]map[string][]string{} - for principal, actions := range(policy.NodeActions) { + for principal, actions := range(policy.Actions) { allowed_actions[principal.String()] = actions } return json.MarshalIndent(&PerNodePolicyJSON{ GraphNodeJSON: NewGraphNodeJSON(&policy.GraphNode), - NodeActions: allowed_actions, - WildcardActions: policy.WildcardActions, + Actions: allowed_actions, }, "", " ") } -func NewPerNodePolicy(id NodeID, node_actions map[NodeID]NodeActions, wildcard_actions NodeActions) PerNodePolicy { - if node_actions == nil { - node_actions = map[NodeID]NodeActions{} - } - - if wildcard_actions == nil { - wildcard_actions = NewNodeActions(nil, nil) +func NewPerNodePolicy(id NodeID, actions map[NodeID]NodeActions) PerNodePolicy { + if actions == nil { + actions = map[NodeID]NodeActions{} } return PerNodePolicy{ GraphNode: NewGraphNode(id), - NodeActions: node_actions, - WildcardActions: wildcard_actions, + Actions: actions, } } @@ -95,17 +87,17 @@ func LoadPerNodePolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Nod return nil, err } - allowed_actions := map[NodeID]NodeActions{} - for principal_str, actions := range(j.NodeActions) { + actions := map[NodeID]NodeActions{} + for principal_str, node_actions := range(j.Actions) { principal_id, err := ParseID(principal_str) if err != nil { return nil, err } - allowed_actions[principal_id] = actions + actions[principal_id] = node_actions } - policy := NewPerNodePolicy(id, allowed_actions, j.WildcardActions) + policy := NewPerNodePolicy(id, actions) nodes[id] = &policy err = RestoreGraphNode(ctx, &policy.GraphNode, j.GraphNodeJSON, nodes) @@ -117,11 +109,7 @@ func LoadPerNodePolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Nod } func (policy *PerNodePolicy) Allows(action string, resource string, principal NodeID) bool { - if policy.WildcardActions.Allows(action, resource) == true { - return true - } - - node_actions, exists := policy.NodeActions[principal] + node_actions, exists := policy.Actions[principal] if exists == false { return false } @@ -132,3 +120,58 @@ func (policy *PerNodePolicy) Allows(action string, resource string, principal No return false } + +type SimplePolicy struct { + GraphNode + Actions NodeActions +} + +type SimplePolicyJSON struct { + GraphNodeJSON + Actions map[string][]string `json:"actions"` +} + +func (policy *SimplePolicy) Type() NodeType { + return NodeType("simple_policy") +} + +func (policy *SimplePolicy) Serialize() ([]byte, error) { + return json.MarshalIndent(&SimplePolicyJSON{ + GraphNodeJSON: NewGraphNodeJSON(&policy.GraphNode), + Actions: policy.Actions, + }, "", " ") +} + +func NewSimplePolicy(id NodeID, actions NodeActions) SimplePolicy { + if actions == nil { + actions = NodeActions{} + } + + return SimplePolicy{ + GraphNode: NewGraphNode(id), + Actions: actions, + } +} + +func LoadSimplePolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) { + var j SimplePolicyJSON + err := json.Unmarshal(data, &j) + if err != nil { + return nil, err + } + + policy := NewSimplePolicy(id, j.Actions) + nodes[id] = &policy + + err = RestoreGraphNode(ctx, &policy.GraphNode, j.GraphNodeJSON, nodes) + if err != nil { + return nil, err + } + + return &policy, nil +} + +func (policy *SimplePolicy) Allows(action string, resource string, principal NodeID) bool { + return policy.Actions.Allows(action, resource) +} + diff --git a/user.go b/user.go index 9f1fd98..7c3db43 100644 --- a/user.go +++ b/user.go @@ -14,6 +14,7 @@ type User struct { Granted time.Time Pubkey *ecdsa.PublicKey Shared []byte + Tags []string } type UserJSON struct { @@ -21,6 +22,7 @@ type UserJSON struct { Granted time.Time `json:"granted"` Pubkey []byte `json:"pubkey"` Shared []byte `json:"shared"` + Tags []string `json:"tags"` } func (user *User) Type() NodeType { @@ -39,6 +41,7 @@ func (user *User) Serialize() ([]byte, error) { Granted: user.Granted, Shared: user.Shared, Pubkey: pubkey, + Tags: user.Tags, }, "", " ") } @@ -62,7 +65,7 @@ func LoadUser(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) return nil, fmt.Errorf("Invalid key type") } - user := NewUser(j.Name, j.Granted, pubkey, j.Shared) + user := NewUser(j.Name, j.Granted, pubkey, j.Shared, j.Tags) nodes[id] = &user err = RestoreSimpleLockable(ctx, &user, j.SimpleLockableJSON, nodes) @@ -73,12 +76,13 @@ func LoadUser(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) return &user, nil } -func NewUser(name string, granted time.Time, pubkey *ecdsa.PublicKey, shared []byte) User { +func NewUser(name string, granted time.Time, pubkey *ecdsa.PublicKey, shared []byte, tags []string) User { id := KeyID(pubkey) return User{ SimpleLockable: NewSimpleLockable(id, name), Granted: granted, Pubkey: pubkey, Shared: shared, + Tags: tags, } }