disk: new path policies struct and methods

Build a new path policy struct, ased on the new path trie struct.
It is designed to be able to store policies for paths. A Check
method can then be used to look up the policy for a given path
based on the defined policies.
This commit is contained in:
Christian Kellner 2022-08-06 21:03:03 +02:00
parent 00555722b2
commit 9523694879
2 changed files with 104 additions and 0 deletions

View file

@ -0,0 +1,54 @@
package disk
import (
"fmt"
"path"
)
type PathPolicy struct {
Deny bool // explicitly do not allow this entry
Exact bool // require and exact match, no subdirs
}
type PathPolicies = PathTrie
// Create a new PathPolicies trie from a map of path to PathPolicy
func NewPathPolicies(entries map[string]PathPolicy) *PathPolicies {
noType := make(map[string]interface{}, len(entries))
for k, v := range entries {
noType[k] = v
}
return NewPathTrieFromMap(noType)
}
// Check a given path at dir against the PathPolicies
func (pol *PathPolicies) Check(dir string) error {
// Quickly check we have a mountpoint and it is absolute
if dir == "" || dir[0] != '/' {
return fmt.Errorf("mountpoint must be absolute path")
}
// ensure that only clean mountpoints are valid
if dir != path.Clean(dir) {
return fmt.Errorf("mountpoint must be a canonical path")
}
node, left := pol.Lookup(dir)
policy, ok := node.Payload.(PathPolicy)
if !ok {
panic("programming error: invalid path trie payload")
}
// 1) path is explicitly not allowed or
// 2) a subpath was match but an explicit match is required
if policy.Deny || (policy.Exact && len(left) > 0) {
return fmt.Errorf("path '%s ' is not allowed", dir)
}
// exact match or recursive mountpoints allowed
return nil
}

View file

@ -0,0 +1,50 @@
package disk
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestPathPolicyCheck(t *testing.T) {
assert := assert.New(t)
entires := map[string]PathPolicy{
"/": {Exact: true},
"/boot": {Exact: true},
"/boot/efi": {Exact: true},
"/var": {},
"/var/empty": {Deny: true},
"/srv": {},
"/home": {},
}
policies := NewPathPolicies(entires)
assert.NotNil(policies)
tests := map[string]bool{
"/": true,
"/custom": false,
"/boot": true,
"/boot/grub2": false,
"/boot/efi": true,
"/boot/efi/redora": false,
"/srv": true,
"/srv/www": true,
"/srv/www/data": true,
"/var": true,
"/var/log": true,
"/var/empty": false,
"/var/empty/dir": false,
}
for k, v := range tests {
err := policies.Check(k)
if v {
assert.NoError(err)
} else {
assert.Errorf(err, "unexpected error for path '%s'", k)
}
}
}