Added more policy types, removed tags

graph-rework-2
noah metz 2023-07-24 22:52:15 -06:00
parent f118dde221
commit 59df9f04d5
5 changed files with 84 additions and 67 deletions

@ -203,11 +203,15 @@ func NewContext(db * badger.DB, log Logger) * Context {
if err != nil {
panic(err)
}
err = ctx.RegisterNodeType(NewNodeDef((*PerTagPolicy)(nil), LoadPerTagPolicy, GQLTypeSimpleNode.Type))
err = ctx.RegisterNodeType(NewNodeDef((*DependencyPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type))
if err != nil {
panic(err)
}
err = ctx.RegisterNodeType(NewNodeDef((*DependencyPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type))
err = ctx.RegisterNodeType(NewNodeDef((*ParentPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type))
if err != nil {
panic(err)
}
err = ctx.RegisterNodeType(NewNodeDef((*ChildrenPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type))
if err != nil {
panic(err)
}

@ -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, []string{"gql"})
new_user := NewUser(fmt.Sprintf("GQL_USER %s", key_id.String()), time.Now(), remote_id, shared)
context := NewWriteContext(ctx)
err := UpdateStates(context, server, NewLockMap(LockMap{
server.ID(): LockInfo{

@ -31,7 +31,7 @@ func TestGQLDBLoad(t * testing.T) {
u1_key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
fatalErr(t, err)
u1 := NewUser("Test User", time.Now(), &u1_key.PublicKey, []byte{}, []string{"gql"})
u1 := NewUser("Test User", time.Now(), &u1_key.PublicKey, []byte{})
ctx.Log.Logf("test", "U1_ID: %s", u1.ID().String())
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
@ -137,13 +137,12 @@ func TestGQLAuth(t * testing.T) {
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
fatalErr(t, err)
p1 := NewPerTagPolicy(RandID(), map[string]NodeActions{"gql": NewNodeActions(nil, []string{"read"})})
p2 := NewSimplePolicy(RandID(), NewNodeActions(NodeActions{
"signal": []string{"status"},
}, nil))
l1 := NewListener(RandID(), "GQL Thread")
err = AttachPolicies(ctx, &l1, &p1, &p2)
err = AttachPolicies(ctx, &l1, &p2)
fatalErr(t, err)
p3 := NewPerNodePolicy(RandID(), map[NodeID]NodeActions{
@ -151,7 +150,7 @@ func TestGQLAuth(t * testing.T) {
})
gql := NewGQLThread(RandID(), "GQL Thread", "init", ":0", ecdh.P256(), key, nil, nil)
err = AttachPolicies(ctx, &gql, &p1, &p2, &p3)
err = AttachPolicies(ctx, &gql, &p2, &p3)
context := NewWriteContext(ctx)
err = LinkLockables(context, &l1, &l1, []LockableNode{&gql})

@ -175,106 +175,123 @@ func (policy *SimplePolicy) Allows(node Node, resource string, action string, pr
return policy.Actions.Allows(resource, action)
}
type PerTagPolicy struct {
SimpleNode
Actions map[string]NodeActions
type DependencyPolicy struct {
SimplePolicy
}
type PerTagPolicyJSON struct {
SimpleNodeJSON
Actions map[string]map[string][]string `json:"json"`
func (policy *DependencyPolicy) Type() NodeType {
return NodeType("dependency_policy")
}
func (policy *PerTagPolicy) Type() NodeType {
return NodeType("per_tag_policy")
func NewDependencyPolicy(id NodeID, actions NodeActions) DependencyPolicy {
return DependencyPolicy{
SimplePolicy: NewSimplePolicy(id, actions),
}
}
func (policy *PerTagPolicy) Serialize() ([]byte, error) {
actions := map[string]map[string][]string{}
for tag, tag_actions := range(policy.Actions) {
actions[tag] = tag_actions
func (policy *DependencyPolicy) Allows(node Node, resource string, action string, principal Node) bool {
lockable, ok := node.(LockableNode)
if ok == false {
return false
}
return json.MarshalIndent(&PerTagPolicyJSON{
SimpleNodeJSON: NewSimpleNodeJSON(&policy.SimpleNode),
Actions: actions,
}, "", " ")
for _, dep := range(lockable.LockableHandle().Dependencies) {
if dep.ID() == principal.ID() {
return policy.Actions.Allows(resource, action)
}
}
return false
}
func NewPerTagPolicy(id NodeID, actions map[string]NodeActions) PerTagPolicy {
if actions == nil {
actions = map[string]NodeActions{}
}
type RequirementPolicy struct {
SimplePolicy
}
return PerTagPolicy{
SimpleNode: NewSimpleNode(id),
Actions: actions,
func (policy *RequirementPolicy) Type() NodeType {
return NodeType("dependency_policy")
}
func NewRequirementPolicy(id NodeID, actions NodeActions) RequirementPolicy {
return RequirementPolicy{
SimplePolicy: NewSimplePolicy(id, actions),
}
}
func LoadPerTagPolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) {
var j PerTagPolicyJSON
err := json.Unmarshal(data, &j)
if err != nil {
return nil, err
func (policy *RequirementPolicy) Allows(node Node, resource string, action string, principal Node) bool {
lockable_node, ok := node.(LockableNode)
if ok == false {
return false
}
lockable := lockable_node.LockableHandle()
actions := map[string]NodeActions{}
for tag, tag_actions := range(j.Actions) {
actions[tag] = tag_actions
for _, req := range(lockable.Requirements) {
if req.ID() == principal.ID() {
return policy.Actions.Allows(resource, action)
}
}
policy := NewPerTagPolicy(id, actions)
nodes[id] = &policy
return false
}
err = RestoreSimpleNode(ctx, &policy.SimpleNode, j.SimpleNodeJSON, nodes)
if err != nil {
return nil, err
}
type ParentPolicy struct {
SimplePolicy
}
return &policy, nil
func (policy *ParentPolicy) Type() NodeType {
return NodeType("parent_policy")
}
func NewParentPolicy(id NodeID, actions NodeActions) ParentPolicy {
return ParentPolicy{
SimplePolicy: NewSimplePolicy(id, actions),
}
}
func (policy *PerTagPolicy) Allows(node Node, resource string, action string, principal Node) bool {
user, ok := principal.(*User)
func (policy *ParentPolicy) Allows(node Node, resource string, action string, principal Node) bool {
thread_node, ok := node.(ThreadNode)
if ok == false {
return false
}
thread := thread_node.ThreadHandle()
for _, tag := range(user.Tags) {
tag_actions, exists := policy.Actions[tag]
if exists == true {
if tag_actions.Allows(resource, action) == true {
return true
}
if thread.Owner != nil {
if thread.Owner.ID() == principal.ID() {
return policy.Actions.Allows(resource, action)
}
}
return false
}
type DependencyPolicy struct {
type ChildrenPolicy struct {
SimplePolicy
}
func (policy *DependencyPolicy) Type() NodeType {
return NodeType("parent_policy")
func (policy *ChildrenPolicy) Type() NodeType {
return NodeType("children_policy")
}
func NewDependencyPolicy(id NodeID, actions NodeActions) DependencyPolicy {
return DependencyPolicy{
func NewChildrenPolicy(id NodeID, actions NodeActions) ChildrenPolicy {
return ChildrenPolicy{
SimplePolicy: NewSimplePolicy(id, actions),
}
}
func (policy *DependencyPolicy) Allows(node Node, resource string, action string, principal Node) bool {
lockable, ok := node.(LockableNode)
func (policy *ChildrenPolicy) Allows(node Node, resource string, action string, principal Node) bool {
thread_node, ok := node.(ThreadNode)
if ok == false {
return false
}
thread := thread_node.ThreadHandle()
for _, dep := range(lockable.LockableHandle().Dependencies) {
if dep.ID() == principal.ID() {
for _, info := range(thread.Children) {
if info.Child.ID() == principal.ID() {
return policy.Actions.Allows(resource, action)
}
}

@ -22,7 +22,6 @@ 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 {
@ -41,7 +40,6 @@ func (user *User) Serialize() ([]byte, error) {
Granted: user.Granted,
Shared: user.Shared,
Pubkey: pubkey,
Tags: user.Tags,
}, "", " ")
}
@ -66,7 +64,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, j.Tags)
user := NewUser(j.Name, j.Granted, pubkey, j.Shared)
nodes[id] = &user
err = RestoreLockable(ctx, &user.Lockable, j.LockableJSON, nodes)
@ -77,13 +75,12 @@ 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, tags []string) User {
func NewUser(name string, granted time.Time, pubkey *ecdsa.PublicKey, shared []byte) User {
id := KeyID(pubkey)
return User{
Lockable: NewLockable(id, name),
Granted: granted,
Pubkey: pubkey,
Shared: shared,
Tags: tags,
}
}