graphvent/policy.go

124 lines
2.8 KiB
Go

2023-07-20 23:19:10 -06:00
package graphvent
import (
"encoding/json"
"fmt"
2023-07-20 23:19:10 -06:00
)
type Policy interface {
2023-07-25 21:43:15 -06:00
Serialize() ([]byte, error)
Allows(context *StateContext, principal *Node, action string, node *Node) bool
}
2023-07-25 21:43:15 -06:00
func LoadAllNodesPolicy(ctx *Context, data []byte) (Policy, error) {
var policy AllNodesPolicy
err := json.Unmarshal(data, &policy)
if err != nil {
return policy, err
}
2023-07-25 21:43:15 -06:00
return policy, nil
}
2023-07-25 21:43:15 -06:00
type AllNodesPolicy struct {
Actions []string `json:"actions"`
2023-07-20 23:19:10 -06:00
}
2023-07-25 21:43:15 -06:00
func (policy AllNodesPolicy) Type() PolicyType {
return PolicyType("simple_policy")
2023-07-20 23:19:10 -06:00
}
2023-07-25 21:43:15 -06:00
func (policy AllNodesPolicy) Serialize() ([]byte, error) {
return json.MarshalIndent(&policy, "", " ")
2023-07-20 23:19:10 -06:00
}
2023-07-25 21:43:15 -06:00
// Extension to allow a node to hold ACL policies
type ACLPolicyExtension struct {
Policies map[PolicyType]Policy
2023-07-20 23:19:10 -06:00
}
2023-07-25 21:43:15 -06:00
type PolicyLoadFunc func(*Context, []byte) (Policy, error)
type PolicyInfo struct {
Load PolicyLoadFunc
Type PolicyType
2023-07-20 23:19:10 -06:00
}
2023-07-25 21:43:15 -06:00
type ACLPolicyExtensionContext struct {
Types map[PolicyType]PolicyInfo
2023-07-20 23:19:10 -06:00
}
2023-07-25 21:43:15 -06:00
func (ext ACLPolicyExtension) Serialize() ([]byte, error) {
policies := map[string][]byte{}
for name, policy := range(ext.Policies) {
ser, err := policy.Serialize()
2023-07-20 23:19:10 -06:00
if err != nil {
return nil, err
}
2023-07-25 21:43:15 -06:00
policies[string(name)] = ser
2023-07-20 23:19:10 -06:00
}
2023-07-25 21:43:15 -06:00
return json.MarshalIndent(&struct{
Policies map[string][]byte `json:"policies"`
}{
Policies: policies,
}, "", " ")
2023-07-21 13:55:27 -06:00
}
2023-07-25 21:43:15 -06:00
func (ext ACLPolicyExtension) Process(context *StateContext, node *Node, signal GraphSignal) error {
return nil
2023-07-21 13:55:27 -06:00
}
2023-07-25 21:43:15 -06:00
func LoadACLPolicyExtension(ctx *Context, data []byte) (Extension, error) {
var j struct {
Policies map[string][]byte `json:"policies"`
2023-07-24 22:52:15 -06:00
}
2023-07-25 21:43:15 -06:00
err := json.Unmarshal(data, &j)
if err != nil {
return nil, err
2023-07-21 13:55:27 -06:00
}
2023-07-25 21:43:15 -06:00
policies := map[PolicyType]Policy{}
acl_ctx := ctx.ExtByType(ACLPolicyExtType).Data.(ACLPolicyExtensionContext)
for name, ser := range(j.Policies) {
policy_def, exists := acl_ctx.Types[PolicyType(name)]
if exists == false {
return nil, fmt.Errorf("%s is not a known policy type", name)
2023-07-24 22:52:15 -06:00
}
2023-07-25 21:43:15 -06:00
policy, err := policy_def.Load(ctx, ser)
if err != nil {
return nil, err
2023-07-24 22:52:15 -06:00
}
2023-07-25 21:43:15 -06:00
policies[PolicyType(name)] = policy
2023-07-24 22:52:15 -06:00
}
2023-07-21 13:55:27 -06:00
2023-07-25 21:43:15 -06:00
return ACLPolicyExtension{
Policies: policies,
}, nil
2023-07-24 01:12:30 -06:00
}
2023-07-25 21:43:15 -06:00
const ACLPolicyExtType = ExtType("ACL_POLICIES")
func (ext ACLPolicyExtension) Type() ExtType {
return ACLPolicyExtType
2023-07-24 01:12:30 -06:00
}
2023-07-25 21:43:15 -06:00
// Check if the extension allows the principal to perform action on node
func (ext ACLPolicyExtension) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
for _, policy := range(ext.Policies) {
if policy.Allows(context, principal, action, node) == true {
return true
2023-07-24 01:12:30 -06:00
}
}
return false
}
2023-07-25 21:43:15 -06:00
func (policy AllNodesPolicy) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
for _, a := range(policy.Actions) {
if a == action {
return true
2023-07-25 00:57:54 -06:00
}
}
return false
}
2023-07-25 21:43:15 -06:00