|
|
|
@ -7,7 +7,38 @@ import (
|
|
|
|
|
|
|
|
|
|
type Policy interface {
|
|
|
|
|
Serializable[PolicyType]
|
|
|
|
|
Allows(context *StateContext, principal *Node, action string, node *Node) bool
|
|
|
|
|
Allows(context *StateContext, principal_id NodeID, action string, node *Node) bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO
|
|
|
|
|
func (policy *AllNodesPolicy) Allows(context *StateContext, principal_id NodeID, action string, node *Node) bool {
|
|
|
|
|
return policy.Actions.Allows(action)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *RequirementOfPolicy) Allows(context *StateContext, principal_id NodeID, action string, node *Node) bool {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *PerNodePolicy) Allows(context *StateContext, principal_id NodeID, action string, node *Node) bool {
|
|
|
|
|
for id, actions := range(policy.NodeActions) {
|
|
|
|
|
if id != principal_id {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for _, a := range(actions) {
|
|
|
|
|
if a == action {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *ParentOfPolicy) Allows(context *StateContext, principal_id NodeID, action string, node *Node) bool {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *ChildOfPolicy) Allows(context *StateContext, principal_id NodeID, action string, node *Node) bool {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const RequirementOfPolicyType = PolicyType("REQUIREMENT_OF")
|
|
|
|
@ -24,27 +55,6 @@ func NewRequirementOfPolicy(nodes NodeActions) RequirementOfPolicy {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if any of principals dependencies are in the policy
|
|
|
|
|
func (policy *RequirementOfPolicy) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
|
|
|
|
|
lockable_ext, err := GetExt[*LockableExt](principal)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for dep_id, _ := range(lockable_ext.Dependencies) {
|
|
|
|
|
for node_id, actions := range(policy.NodeActions) {
|
|
|
|
|
if node_id == dep_id {
|
|
|
|
|
if actions.Allows(action) == true {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ChildOfPolicyType = PolicyType("CHILD_OF")
|
|
|
|
|
type ChildOfPolicy struct {
|
|
|
|
|
PerNodePolicy
|
|
|
|
@ -53,29 +63,6 @@ func (policy *ChildOfPolicy) Type() PolicyType {
|
|
|
|
|
return ChildOfPolicyType
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *ChildOfPolicy) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
|
|
|
|
|
context.Graph.Log.Logf("policy", "CHILD_OF_POLICY: %+v", policy)
|
|
|
|
|
thread_ext, err := GetExt[*ThreadExt](principal)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent := thread_ext.Parent
|
|
|
|
|
if parent != nil {
|
|
|
|
|
actions, exists := policy.NodeActions[parent.ID]
|
|
|
|
|
if exists == false {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
for _, a := range(actions) {
|
|
|
|
|
if a == action {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Actions []string
|
|
|
|
|
|
|
|
|
|
func (actions Actions) Allows(action string) bool {
|
|
|
|
@ -130,29 +117,6 @@ func (policy *ParentOfPolicy) Type() PolicyType {
|
|
|
|
|
return ParentOfPolicyType
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *ParentOfPolicy) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
|
|
|
|
|
context.Graph.Log.Logf("policy", "PARENT_OF_POLICY: %+v", policy)
|
|
|
|
|
for id, actions := range(policy.NodeActions) {
|
|
|
|
|
thread_ext, err := GetExt[*ThreadExt](context.Graph.Nodes[id])
|
|
|
|
|
if err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context.Graph.Log.Logf("policy", "PARENT_OF_PARENT: %s %+v", id, thread_ext.Parent)
|
|
|
|
|
if thread_ext.Parent != nil {
|
|
|
|
|
if thread_ext.Parent.ID == principal.ID {
|
|
|
|
|
for _, a := range(actions) {
|
|
|
|
|
if a == action {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewParentOfPolicy(node_actions NodeActions) ParentOfPolicy {
|
|
|
|
|
return ParentOfPolicy{
|
|
|
|
|
PerNodePolicy: NewPerNodePolicy(node_actions),
|
|
|
|
@ -193,20 +157,6 @@ func (policy *PerNodePolicy) Serialize() ([]byte, error) {
|
|
|
|
|
}, "", " ")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *PerNodePolicy) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
|
|
|
|
|
for id, actions := range(policy.NodeActions) {
|
|
|
|
|
if id != principal.ID {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for _, a := range(actions) {
|
|
|
|
|
if a == action {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewAllNodesPolicy(actions Actions) AllNodesPolicy {
|
|
|
|
|
if actions == nil {
|
|
|
|
|
actions = Actions{}
|
|
|
|
@ -230,44 +180,11 @@ func (policy *AllNodesPolicy) Serialize() ([]byte, error) {
|
|
|
|
|
return json.MarshalIndent(policy, "", " ")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (policy *AllNodesPolicy) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
|
|
|
|
|
return policy.Actions.Allows(action)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Extension to allow a node to hold ACL policies
|
|
|
|
|
type ACLPolicyExt struct {
|
|
|
|
|
Policies map[PolicyType]Policy
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The ACL extension stores a map of nodes to delegate ACL to, and a list of policies
|
|
|
|
|
type ACLExt struct {
|
|
|
|
|
Delegations NodeMap
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ext *ACLExt) Process(context *StateContext, node *Node, signal Signal) error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func LoadACLExt(ctx *Context, data []byte) (Extension, error) {
|
|
|
|
|
var j struct {
|
|
|
|
|
Delegations []string `json:"delegation"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err := json.Unmarshal(data, &j)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delegations, err := RestoreNodeList(ctx, j.Delegations)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &ACLExt{
|
|
|
|
|
Delegations: delegations,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NodeList(nodes ...*Node) NodeMap {
|
|
|
|
|
m := NodeMap{}
|
|
|
|
@ -277,36 +194,6 @@ func NodeList(nodes ...*Node) NodeMap {
|
|
|
|
|
return m
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewACLExt(delegations NodeMap) *ACLExt {
|
|
|
|
|
if delegations == nil {
|
|
|
|
|
delegations = NodeMap{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &ACLExt{
|
|
|
|
|
Delegations: delegations,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ext *ACLExt) Serialize() ([]byte, error) {
|
|
|
|
|
delegations := make([]string, len(ext.Delegations))
|
|
|
|
|
i := 0
|
|
|
|
|
for id, _ := range(ext.Delegations) {
|
|
|
|
|
delegations[i] = id.String()
|
|
|
|
|
i += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return json.MarshalIndent(&struct{
|
|
|
|
|
Delegations []string `json:"delegations"`
|
|
|
|
|
}{
|
|
|
|
|
Delegations: delegations,
|
|
|
|
|
}, "", " ")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ACLExtType = ExtType("ACL")
|
|
|
|
|
func (ext *ACLExt) Type() ExtType {
|
|
|
|
|
return ACLExtType
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PolicyLoadFunc func(*Context, []byte) (Policy, error)
|
|
|
|
|
type PolicyInfo struct {
|
|
|
|
|
Load PolicyLoadFunc
|
|
|
|
@ -427,11 +314,11 @@ func (ext *ACLPolicyExt) Type() ExtType {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if the extension allows the principal to perform action on node
|
|
|
|
|
func (ext *ACLPolicyExt) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
|
|
|
|
|
func (ext *ACLPolicyExt) Allows(context *StateContext, principal_id NodeID, action string, node *Node) bool {
|
|
|
|
|
context.Graph.Log.Logf("policy", "POLICY_EXT_ALLOWED: %+v", ext)
|
|
|
|
|
for _, policy := range(ext.Policies) {
|
|
|
|
|
context.Graph.Log.Logf("policy", "POLICY_CHECK_POLICY: %+v", policy)
|
|
|
|
|
if policy.Allows(context, principal, action, node) == true {
|
|
|
|
|
if policy.Allows(context, principal_id, action, node) == true {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|