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:
parent
00555722b2
commit
9523694879
2 changed files with 104 additions and 0 deletions
54
internal/disk/path_policy.go
Normal file
54
internal/disk/path_policy.go
Normal 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
|
||||
}
|
||||
50
internal/disk/path_policy_test.go
Normal file
50
internal/disk/path_policy_test.go
Normal 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)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue