graphvent/policy.go

301 lines
6.7 KiB
Go

2023-07-20 23:19:10 -06:00
package graphvent
import (
"encoding/json"
)
2023-07-21 12:09:29 -06:00
// A policy represents a set of rules attached to a Node that allow principals to perform actions on it
2023-07-20 23:19:10 -06:00
type Policy interface {
Node
2023-07-21 12:09:29 -06:00
// Returns true if the principal is allowed to perform the action on the resource
2023-07-24 01:12:30 -06:00
Allows(node Node, resource string, action string, principal Node) bool
}
type NodeActions map[string][]string
func (actions NodeActions) Allows(resource string, action string) bool {
for _, a := range(actions[""]) {
2023-07-21 12:09:29 -06:00
if a == action || a == "*" {
return true
}
}
resource_actions, exists := actions[resource]
if exists == true {
for _, a := range(resource_actions) {
2023-07-21 12:09:29 -06:00
if a == action || a == "*" {
return true
}
}
}
return false
}
2023-07-21 12:09:29 -06:00
func NewNodeActions(resource_actions NodeActions, wildcard_actions []string) NodeActions {
if resource_actions == nil {
resource_actions = NodeActions{}
}
// Wildcard actions, all actions in "" will be allowed on all resources
if wildcard_actions == nil {
wildcard_actions = []string{}
}
2023-07-21 12:09:29 -06:00
resource_actions[""] = wildcard_actions
return resource_actions
2023-07-20 23:19:10 -06:00
}
type PerNodePolicy struct {
2023-07-24 16:04:56 -06:00
SimpleNode
2023-07-21 13:33:04 -06:00
Actions map[NodeID]NodeActions
2023-07-20 23:19:10 -06:00
}
type PerNodePolicyJSON struct {
2023-07-24 16:04:56 -06:00
SimpleNodeJSON
2023-07-21 13:33:04 -06:00
Actions map[string]map[string][]string `json:"actions"`
2023-07-20 23:19:10 -06:00
}
func (policy *PerNodePolicy) Type() NodeType {
return NodeType("per_node_policy")
}
func (policy *PerNodePolicy) Serialize() ([]byte, error) {
2023-07-21 13:55:27 -06:00
actions := map[string]map[string][]string{}
for principal, resource_actions := range(policy.Actions) {
actions[principal.String()] = resource_actions
2023-07-20 23:19:10 -06:00
}
return json.MarshalIndent(&PerNodePolicyJSON{
2023-07-24 16:04:56 -06:00
SimpleNodeJSON: NewSimpleNodeJSON(&policy.SimpleNode),
2023-07-21 13:55:27 -06:00
Actions: actions,
2023-07-20 23:19:10 -06:00
}, "", " ")
}
2023-07-21 13:33:04 -06:00
func NewPerNodePolicy(id NodeID, actions map[NodeID]NodeActions) PerNodePolicy {
if actions == nil {
actions = map[NodeID]NodeActions{}
2023-07-20 23:19:10 -06:00
}
return PerNodePolicy{
2023-07-24 16:04:56 -06:00
SimpleNode: NewSimpleNode(id),
2023-07-21 13:33:04 -06:00
Actions: actions,
2023-07-20 23:19:10 -06:00
}
}
func LoadPerNodePolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) {
var j PerNodePolicyJSON
err := json.Unmarshal(data, &j)
if err != nil {
return nil, err
}
2023-07-21 13:33:04 -06:00
actions := map[NodeID]NodeActions{}
for principal_str, node_actions := range(j.Actions) {
2023-07-20 23:19:10 -06:00
principal_id, err := ParseID(principal_str)
if err != nil {
return nil, err
}
2023-07-21 13:33:04 -06:00
actions[principal_id] = node_actions
2023-07-20 23:19:10 -06:00
}
2023-07-21 13:33:04 -06:00
policy := NewPerNodePolicy(id, actions)
2023-07-20 23:19:10 -06:00
nodes[id] = &policy
2023-07-24 16:04:56 -06:00
err = RestoreSimpleNode(ctx, &policy.SimpleNode, j.SimpleNodeJSON, nodes)
2023-07-20 23:19:10 -06:00
if err != nil {
return nil, err
}
return &policy, nil
}
2023-07-24 01:12:30 -06:00
func (policy *PerNodePolicy) Allows(node Node, resource string, action string, principal Node) bool {
node_actions, exists := policy.Actions[principal.ID()]
if exists == false {
return false
2023-07-20 23:19:10 -06:00
}
if node_actions.Allows(resource, action) == true {
return true
2023-07-20 23:19:10 -06:00
}
return false
}
2023-07-21 13:33:04 -06:00
type SimplePolicy struct {
2023-07-24 16:04:56 -06:00
SimpleNode
2023-07-21 13:33:04 -06:00
Actions NodeActions
}
type SimplePolicyJSON struct {
2023-07-24 16:04:56 -06:00
SimpleNodeJSON
2023-07-21 13:33:04 -06:00
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{
2023-07-24 16:04:56 -06:00
SimpleNodeJSON: NewSimpleNodeJSON(&policy.SimpleNode),
2023-07-21 13:33:04 -06:00
Actions: policy.Actions,
}, "", " ")
}
func NewSimplePolicy(id NodeID, actions NodeActions) SimplePolicy {
if actions == nil {
actions = NodeActions{}
}
return SimplePolicy{
2023-07-24 16:04:56 -06:00
SimpleNode: NewSimpleNode(id),
2023-07-21 13:33:04 -06:00
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
2023-07-24 16:04:56 -06:00
err = RestoreSimpleNode(ctx, &policy.SimpleNode, j.SimpleNodeJSON, nodes)
2023-07-21 13:33:04 -06:00
if err != nil {
return nil, err
}
return &policy, nil
}
2023-07-24 01:12:30 -06:00
func (policy *SimplePolicy) Allows(node Node, resource string, action string, principal Node) bool {
return policy.Actions.Allows(resource, action)
2023-07-21 13:33:04 -06:00
}
2023-07-24 22:52:15 -06:00
type DependencyPolicy struct {
SimplePolicy
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
func (policy *DependencyPolicy) Type() NodeType {
return NodeType("dependency_policy")
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
func NewDependencyPolicy(id NodeID, actions NodeActions) DependencyPolicy {
return DependencyPolicy{
SimplePolicy: NewSimplePolicy(id, actions),
}
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
func (policy *DependencyPolicy) Allows(node Node, resource string, action string, principal Node) bool {
lockable, ok := node.(LockableNode)
if ok == false {
return false
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
for _, dep := range(lockable.LockableHandle().Dependencies) {
if dep.ID() == principal.ID() {
return policy.Actions.Allows(resource, action)
}
}
return false
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
type RequirementPolicy struct {
SimplePolicy
}
2023-07-21 13:55:27 -06:00
2023-07-24 22:52:15 -06:00
func (policy *RequirementPolicy) Type() NodeType {
return NodeType("dependency_policy")
}
func NewRequirementPolicy(id NodeID, actions NodeActions) RequirementPolicy {
return RequirementPolicy{
SimplePolicy: NewSimplePolicy(id, actions),
2023-07-21 13:55:27 -06:00
}
}
2023-07-24 22:52:15 -06:00
func (policy *RequirementPolicy) Allows(node Node, resource string, action string, principal Node) bool {
lockable_node, ok := node.(LockableNode)
if ok == false {
return false
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
lockable := lockable_node.LockableHandle()
2023-07-21 13:55:27 -06:00
2023-07-24 22:52:15 -06:00
for _, req := range(lockable.Requirements) {
if req.ID() == principal.ID() {
return policy.Actions.Allows(resource, action)
}
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
return false
}
2023-07-21 13:55:27 -06:00
2023-07-24 22:52:15 -06:00
type ParentPolicy struct {
SimplePolicy
}
2023-07-21 13:55:27 -06:00
2023-07-24 22:52:15 -06:00
func (policy *ParentPolicy) Type() NodeType {
return NodeType("parent_policy")
}
func NewParentPolicy(id NodeID, actions NodeActions) ParentPolicy {
return ParentPolicy{
SimplePolicy: NewSimplePolicy(id, actions),
}
2023-07-21 13:55:27 -06:00
}
2023-07-24 22:52:15 -06:00
func (policy *ParentPolicy) Allows(node Node, resource string, action string, principal Node) bool {
thread_node, ok := node.(ThreadNode)
2023-07-21 13:55:27 -06:00
if ok == false {
return false
}
2023-07-24 22:52:15 -06:00
thread := thread_node.ThreadHandle()
2023-07-21 13:55:27 -06:00
2023-07-24 22:52:15 -06:00
if thread.Owner != nil {
if thread.Owner.ID() == principal.ID() {
return policy.Actions.Allows(resource, action)
2023-07-21 13:55:27 -06:00
}
}
2023-07-24 22:52:15 -06:00
2023-07-21 13:55:27 -06:00
return false
}
2023-07-24 22:52:15 -06:00
type ChildrenPolicy struct {
2023-07-24 01:12:30 -06:00
SimplePolicy
}
2023-07-24 22:52:15 -06:00
func (policy *ChildrenPolicy) Type() NodeType {
return NodeType("children_policy")
2023-07-24 01:12:30 -06:00
}
2023-07-24 22:52:15 -06:00
func NewChildrenPolicy(id NodeID, actions NodeActions) ChildrenPolicy {
return ChildrenPolicy{
2023-07-24 01:12:30 -06:00
SimplePolicy: NewSimplePolicy(id, actions),
}
}
2023-07-24 22:52:15 -06:00
func (policy *ChildrenPolicy) Allows(node Node, resource string, action string, principal Node) bool {
thread_node, ok := node.(ThreadNode)
2023-07-24 01:12:30 -06:00
if ok == false {
return false
}
2023-07-24 22:52:15 -06:00
thread := thread_node.ThreadHandle()
2023-07-24 01:12:30 -06:00
2023-07-24 22:52:15 -06:00
for _, info := range(thread.Children) {
if info.Child.ID() == principal.ID() {
2023-07-24 01:12:30 -06:00
return policy.Actions.Allows(resource, action)
}
}
return false
}