Files
Mike Cohen 25ed2ddf26 Refactored accessors and improved permissions. (#4386)
The PR refactors the accessor API to add a descriptor for each accessor,
like vql plugins and functions. This allows a more structured approach
to documentation.

Additionally, the descriptor can specify the type of permissions
required to use the accessor, just like plugins. Some accessrs are
configured through scope variables, and this now adds a self documenting
args descriptor just like plugins.

This PR also introduces a new permission NETWORK. This permission
declares that the user is able to access the network and it is enforced
by various plugins/functions and accessors that access the network. This
additional permission provide finer grained control over user activity.
2025-08-07 00:17:17 +10:00

169 lines
4.4 KiB
Go

package accessors_test
import (
"strings"
"testing"
"github.com/Velocidex/ordereddict"
"www.velocidex.com/golang/velociraptor/accessors"
"www.velocidex.com/golang/velociraptor/accessors/zip"
config_proto "www.velocidex.com/golang/velociraptor/config/proto"
"www.velocidex.com/golang/velociraptor/constants"
"www.velocidex.com/golang/velociraptor/json"
vql_subsystem "www.velocidex.com/golang/velociraptor/vql"
"www.velocidex.com/golang/velociraptor/vql/acl_managers"
"www.velocidex.com/golang/velociraptor/vtesting/goldie"
_ "www.velocidex.com/golang/velociraptor/accessors/ntfs"
_ "www.velocidex.com/golang/velociraptor/accessors/offset"
)
type api_tests struct {
name string
path string
components string
}
var (
// Trim the prefix from a path
trim_tests = []api_tests{
{"Simple Path",
"C:/Windows/System32", "C:"},
{"Simple Path Deep",
"C:/Windows/System32", "C:,Windows"},
{"Complex Pathspec",
`{
"DelegateAccessor": "raw_ntfs",
"Delegate":{
"DelegateAccessor": "file",
"DelegatePath":"/mnt/flat",
"Path":"/Windows/System32/Config/SYSTEM"
},
"Path":"ControlSet001"
}`,
"ControlSet001"},
// Trim just one prefix directory.
{"Complex Pathspec Deep",
`{
"DelegateAccessor": "raw_ntfs",
"Delegate":{
"DelegateAccessor": "file",
"DelegatePath":"/mnt/flat",
"Path":"/Windows/System32/Config/SYSTEM"
},
"Path":"ControlSet001/Foo/Bar"
}`,
"ControlSet001"},
}
append_tests = []api_tests{
{"Simple Path",
"C:/Windows/", "System32,notepad.exe"},
{"Complex Pathspec",
`{
"DelegateAccessor": "raw_ntfs",
"Delegate":{
"DelegateAccessor": "file",
"DelegatePath":"/mnt/flat",
"Path":"/Windows/System32/Config/SYSTEM"
},
"Path":"ControlSet001"
}`,
"Foo,Bar"},
}
)
// Make sure OSPath can handle complex path manipulations
func TestOSPathOperationsTrimComponents(t *testing.T) {
result := ordereddict.NewDict()
for _, test_case := range trim_tests {
a := accessors.MustNewWindowsOSPath(test_case.path)
components := strings.Split(test_case.components, ",")
trimmed := a.TrimComponents(components...)
result.Set(test_case.name, trimmed)
}
goldie.Assert(t, "TestOSPathOperationsTrimComponents",
json.MustMarshalIndent(result))
}
func TestOSPathOperationsAppendComponents(t *testing.T) {
result := ordereddict.NewDict()
for _, test_case := range append_tests {
a := accessors.MustNewWindowsOSPath(test_case.path)
components := strings.Split(test_case.components, ",")
trimmed := a.Append(components...)
result.Set(test_case.name, trimmed)
}
goldie.Assert(t, "TestOSPathOperationsAppendComponents",
json.MustMarshalIndent(result))
}
type human_string_tests_t struct {
name string
pathspec string
path_type string
}
var human_string_tests = []human_string_tests_t{
{"Deep Pathspec",
`{
"Path": "/ControlSet001",
"DelegateAccessor": "raw_ntfs",
"Delegate": {
"DelegateAccessor":"offset",
"Delegate": {
"DelegateAccessor": "virt",
"DelegatePath": "/shared/mnt/flat",
"Path": "122683392"
},
"Path":"/Windows/System32/Config/SYSTEM"
}
}
`, "linux"},
{"Normal path", `C:\Windows\System32`, "windows"},
}
func TestOSPathHumanString(t *testing.T) {
config_obj := &config_proto.Config{}
// To make this test run on Linux and Windows the same we use a
// neutral accessor.
device_manager := accessors.GetDefaultDeviceManager(config_obj).Copy()
device_manager.Register(accessors.DescribeAccessor(
accessors.NewVirtualFilesystemAccessor(accessors.MustNewLinuxOSPath("")),
accessors.AccessorDescriptor{
Name: "virt",
}))
scope := vql_subsystem.MakeScope().AppendVars(ordereddict.NewDict().
Set(vql_subsystem.ACL_MANAGER_VAR, acl_managers.NullACLManager{}).
Set(constants.SCOPE_DEVICE_MANAGER, device_manager))
result := ordereddict.NewDict()
for _, test_case := range human_string_tests {
switch test_case.path_type {
case "linux":
a := accessors.MustNewLinuxOSPath(test_case.pathspec)
result.Set(test_case.name, a.HumanString(scope))
case "windows":
a := accessors.MustNewWindowsOSPath(test_case.pathspec)
result.Set(test_case.name, a.HumanString(scope))
}
}
goldie.Assert(t, "TestOSPathHumanString",
json.MustMarshalIndent(result))
}
func init() {
// Override the file accessor with something that uses Generic
// ospath so tests are the same on windows and linux.
accessors.Register(&zip.ZipFileSystemAccessor{})
}