graphvent/policy.go

310 lines
7.2 KiB
Go

2023-07-20 23:19:10 -06:00
package graphvent
import (
"encoding/json"
"fmt"
2023-07-20 23:19:10 -06:00
)
const (
UserOfPolicyType = PolicyType("USER_OF")
RequirementOfPolicyType = PolicyType("REQUIREMENT_OF")
PerNodePolicyType = PolicyType("PER_NODE")
AllNodesPolicyType = PolicyType("ALL_NODES")
)
2023-07-20 23:19:10 -06:00
type Policy interface {
Serializable[PolicyType]
Allows(principal_id NodeID, action Action, node *Node)(Messages, error)
// Merge with another policy of the same underlying type
Merge(Policy) Policy
2023-08-01 20:55:15 -06:00
// Make a copy of this policy
Copy() Policy
}
func (policy AllNodesPolicy) Allows(principal_id NodeID, action Action, node *Node)(Messages, error) {
return nil, policy.Actions.Allows(action)
}
func (policy PerNodePolicy) Allows(principal_id NodeID, action Action, node *Node)(Messages, error) {
for id, actions := range(policy.NodeActions) {
if id != principal_id {
continue
}
return nil, actions.Allows(action)
}
return nil, fmt.Errorf("%s is not in per node policy of %s", principal_id, node.ID)
}
func (policy *RequirementOfPolicy) Allows(principal_id NodeID, action Action, node *Node)(Messages, error) {
lockable_ext, err := GetExt[*LockableExt](node)
if err != nil {
return nil, err
}
for id, _ := range(lockable_ext.Requirements) {
if id == principal_id {
return nil, policy.Actions.Allows(action)
}
}
return nil, fmt.Errorf("%s is not a requirement of %s", principal_id, node.ID)
}
type UserOfPolicy struct {
PerNodePolicy
}
func (policy *UserOfPolicy) Type() PolicyType {
return UserOfPolicyType
}
func NewUserOfPolicy(group_actions NodeActions) UserOfPolicy {
return UserOfPolicy{
PerNodePolicy: NewPerNodePolicy(group_actions),
}
}
// Send a read signal to Group to check if principal_id is a member of it
func (policy *UserOfPolicy) Allows(principal_id NodeID, action Action, node *Node) (Messages, error) {
// Send a read signal to each of the groups in the map
// Check for principal_id in any of the returned member lists(skipping errors)
// Return an error in the default case
return nil, fmt.Errorf("NOT_IMPLEMENTED")
}
func (policy *UserOfPolicy) Merge(p Policy) Policy {
other := p.(*UserOfPolicy)
policy.NodeActions = MergeNodeActions(policy.NodeActions, other.NodeActions)
return policy
}
func (policy *UserOfPolicy) Copy() Policy {
new_actions := CopyNodeActions(policy.NodeActions)
return &UserOfPolicy{
PerNodePolicy: NewPerNodePolicy(new_actions),
}
}
type RequirementOfPolicy struct {
AllNodesPolicy
}
func (policy *RequirementOfPolicy) Type() PolicyType {
return RequirementOfPolicyType
}
func NewRequirementOfPolicy(actions Actions) RequirementOfPolicy {
return RequirementOfPolicy{
AllNodesPolicy: NewAllNodesPolicy(actions),
}
}
func MergeActions(first Actions, second Actions) Actions {
ret := second
for _, action := range(first) {
ret = append(ret, action)
}
return ret
}
2023-08-01 20:55:15 -06:00
func CopyNodeActions(actions NodeActions) NodeActions {
ret := NodeActions{}
for id, a := range(actions) {
ret[id] = a
}
return ret
}
func MergeNodeActions(first NodeActions, second NodeActions) NodeActions {
merged := NodeActions{}
for id, actions := range(first) {
merged[id] = actions
}
for id, actions := range(second) {
existing, exists := merged[id]
if exists {
merged[id] = MergeActions(existing, actions)
} else {
merged[id] = actions
}
}
return merged
}
2023-08-01 20:55:15 -06:00
func (policy *PerNodePolicy) Merge(p Policy) Policy {
other := p.(*PerNodePolicy)
policy.NodeActions = MergeNodeActions(policy.NodeActions, other.NodeActions)
return policy
}
2023-08-01 20:55:15 -06:00
func (policy *PerNodePolicy) Copy() Policy {
new_actions := CopyNodeActions(policy.NodeActions)
return &PerNodePolicy{
NodeActions: new_actions,
}
}
func (policy *AllNodesPolicy) Merge(p Policy) Policy {
other := p.(*AllNodesPolicy)
policy.Actions = MergeActions(policy.Actions, other.Actions)
return policy
}
2023-08-01 20:55:15 -06:00
func (policy *AllNodesPolicy) Copy() Policy {
new_actions := policy.Actions
return &AllNodesPolicy {
Actions: new_actions,
}
}
func (policy *RequirementOfPolicy) Merge(p Policy) Policy {
other := p.(*RequirementOfPolicy)
policy.Actions = MergeActions(policy.Actions, other.Actions)
return policy
}
2023-08-01 20:55:15 -06:00
func (policy *RequirementOfPolicy) Copy() Policy {
new_actions := policy.Actions
return &RequirementOfPolicy{
AllNodesPolicy {
Actions: new_actions,
},
}
}
type Action []string
func MakeAction(parts ...interface{}) Action {
action := make(Action, len(parts))
for i, part := range(parts) {
stringer, ok := part.(fmt.Stringer)
if ok == false {
switch p := part.(type) {
case string:
action[i] = p
default:
panic("%s can not be part of an action")
}
} else {
action[i] = stringer.String()
}
}
return action
}
func (action Action) Allows(test Action) bool {
action_len := len(action)
for i, part := range(test) {
if i >= action_len {
return false
} else if action[i] == part || action[i] == "*" {
continue
} else if action[i] == "+" {
break
} else {
return false
}
}
return true
}
type Actions []Action
func (actions Actions) Allows(action Action) error {
for _, a := range(actions) {
if a.Allows(action) == true {
return nil
}
}
return fmt.Errorf("%s not in allows list", action)
}
type NodeActions map[NodeID]Actions
2023-07-26 13:28:03 -06:00
func (actions NodeActions) MarshalJSON() ([]byte, error) {
tmp := map[string]Actions{}
for id, a := range(actions) {
tmp[id.String()] = a
}
return json.Marshal(tmp)
}
2023-07-31 19:44:52 -06:00
func (actions *NodeActions) UnmarshalJSON(data []byte) error {
tmp := map[string]Actions{}
err := json.Unmarshal(data, &tmp)
if err != nil {
return err
}
for id_str, a := range(tmp) {
id, err := ParseID(id_str)
if err != nil {
return err
}
2023-07-31 19:44:52 -06:00
ac := *actions
ac[id] = a
}
return nil
}
func NewPerNodePolicy(node_actions NodeActions) PerNodePolicy {
2023-07-26 13:28:03 -06:00
if node_actions == nil {
node_actions = NodeActions{}
2023-07-26 13:28:03 -06:00
}
return PerNodePolicy{
2023-07-26 13:28:03 -06:00
NodeActions: node_actions,
}
}
type PerNodePolicy struct {
NodeActions NodeActions `json:"node_actions"`
2023-07-26 13:28:03 -06:00
}
2023-08-01 20:55:15 -06:00
func (policy *PerNodePolicy) Type() PolicyType {
2023-07-26 13:28:03 -06:00
return PerNodePolicyType
}
2023-08-01 20:55:15 -06:00
func (policy *PerNodePolicy) Serialize() ([]byte, error) {
return json.MarshalIndent(policy, "", " ")
2023-07-26 13:28:03 -06:00
}
2023-08-01 20:55:15 -06:00
func (policy *PerNodePolicy) Deserialize(ctx *Context, data []byte) error {
return json.Unmarshal(data, policy)
}
2023-07-27 00:30:24 -06:00
func NewAllNodesPolicy(actions Actions) AllNodesPolicy {
if actions == nil {
actions = Actions{}
}
return AllNodesPolicy{
Actions: actions,
}
}
type AllNodesPolicy struct {
Actions Actions
2023-07-27 00:30:24 -06:00
}
2023-08-01 20:55:15 -06:00
func (policy *AllNodesPolicy) Type() PolicyType {
2023-07-27 00:30:24 -06:00
return AllNodesPolicyType
}
2023-08-01 20:55:15 -06:00
func (policy *AllNodesPolicy) Serialize() ([]byte, error) {
2023-07-27 00:30:24 -06:00
return json.MarshalIndent(policy, "", " ")
}
2023-08-01 20:55:15 -06:00
func (policy *AllNodesPolicy) Deserialize(ctx *Context, data []byte) error {
return json.Unmarshal(data, policy)
}
var ErrorSignalAction = Action{"ERROR_RESP"}
var ReadResultSignalAction = Action{"READ_RESULT"}
var AuthorizedSignalAction = Action{"AUTHORIZED_READ"}
2023-08-01 20:55:15 -06:00
var defaultPolicy = NewAllNodesPolicy(Actions{ErrorSignalAction, ReadResultSignalAction, AuthorizedSignalAction})
var DefaultACLPolicies = []Policy{
2023-08-01 20:55:15 -06:00
&defaultPolicy,
}